У меня есть сервис, реализованный в виде сценария Bash. Внутри на самом деле это приложение node.js, но для целей этого вопроса это может быть что угодно.
Основной вариант использования - мы разрабатываем / отлаживаем сценарий в интерактивной оболочке, а затем включаем его как службу.
Если я подключу ssh к своему устройству (вход в систему), вся моя среда будет там, и я могу запустить свой сценарий из командной строки, без проблем. Оболочка, в которой я нахожусь, подобрала правильную среду из .bashrc
, .profile
и т.д. и все работает.
Но если я запускаю его из службы systemd, он source
среда, как для интерактивной оболочки. Есть условия для добавления переменных среды в модуль, но то, что я здесь делаю, просто дублирует то, что делает моя интерактивная среда, и становится простым способом что-то забыть.
Я уверен, что для реальной производственной службы есть правильный способ сделать это, но это лабораторное приложение, и мне нужно упростить его, чтобы никто, работающий над сценарием, не знал, как работает systemd.
Итак, вопрос: что мне нужно сделать, чтобы сценарий, написанный для запуска в интерактивной оболочке Bash, запускался из systemd?
Я пробовал запустить bash с --login
, но это не работает. Также явно не делается source .bashrc
во внешнем скрипте.
Вот пример, над которым я работаю, чтобы выделить проблему:
основной скрипт (job.sh
):
#!/bin/bash
cd
while [ 1 ]
do
pwd
echo USER is $USER
echo PATH is $PATH
which node
node --version
sleep 1
done
Я вызываю это из другого скрипта (wrapper.sh
):
#!/bin/bash
echo starting wrapper...
bash --login /home/droid/job.sh
и вот мой job.service
единица в /etc/systemd/system/job.service
:
[Unit]
Description=Job Daemon
[Service]
User=droid
ExecStart=/home/droid/wrapper.sh
[Install]
WantedBy=multi-user.target
Что я не понимаю в systemd, что мешает мне заставить это работать?
Разница между запуском скрипта через systemd
и запускать его напрямую - это среда. Вы можете проверить это так. В своем файле модуля добавьте это в раздел [Service] для тестирования:
StandardOutput=console
Затем в вашем сценарии bash вверху добавьте эту строку, чтобы выгрузить среду:
env
Теперь запустите сценарий внутри и вне systemd и сравните выгружаемые переменные среды.
Особенность systemd в том, что он строго контролирует среду. Это повышает безопасность и обеспечивает согласованность.
Вы можете узнать больше о том, как systemd управляет средой в systemd.exec.
Заставить что-то запускать то же самое через CLI и через систему легко, если вы запустите его, как хотите, из systemd. Запустите его через CLI следующим образом:
systemctl start your-unit-name
Тогда systemd будет работать с точно такой же средой.
Вы просили об обратном: чтобы systemd запускал службу в среде «bash». Но это беспорядочная меняющаяся среда, которая может привести к противоречивым результатам. Напротив, среда выполнения systemd строго контролируется, что дает согласованные воспроизводимые результаты. Вот почему следует вывернуть вопрос наизнанку и спросить, как вы можете использовать свои службы в CLI, используя ту же согласованную, контролируемую среду выполнения, которую использует systemd.