Назад | Перейти на главную страницу

Запуск сценария bash из systemd, как если бы я вошел в систему

У меня есть сервис, реализованный в виде сценария 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.