Как узнать, был ли вызван сценарий из systemd или от пользователя?
Я создал сервис для демона старой школы. Мы только что перешли на systemd, и некоторые из моих администраторов любят напрямую вызывать rc-скрипт. Это не сработает в случае перезагрузки машины. Systemd не будет уважать PIDFile=
потому что новый запущенный демон не является частью своей контрольной группы службы.
Я добавил служебный файл и файл rc_script. Я не могу отличаться по идентификатору пользователя, потому что для использования скрипта пользователь должен быть foobaruser
.
Служба остановки теперь является проблемой, потому что systemd распознает это по удаленному файлу pid.
Итак, как мне узнать, был ли скрипт вызван из systemd?
[Unit]
Description=Foobar Service
After=syslog.target network.target
[Service]
Type=forking
User=foobaruser
LimitNOFILE=60000
LimitNPROC=8000
TasksMax=8000
PIDFile=/local/foobar/foo.pid
ExecStart=/opt/foobar/rc_script start
ExecStop=/opt/foobar/rc_script stop
TimeoutSec=100
TimeoutStopSec=300
KillMode=none
RemainAfterExit=no
Environment=LANG=de_DE.UTF-8
[Install]
WantedBy=multi-user.target
#!/bin/bash
case $1 in
start)
VAR_IS_SYSTEMD=$( ... script to check if bash is run from systemd ... )
if [ "$VAR_IS_SYSTEMD" = false ] ; then
sudo systemctl start foobar.service
exit
fi
# start service within systemd
;;
stop)
# stop service
;;
esac
Я согласен с другими постерами, что вы должны попытаться переписать службу, чтобы вообще не вызывать сценарий (это нормально, если ваши администраторы хотят продолжать его использовать, но нужны ли службе systemd все 36 параметров?) - но это также не трудно определить, был ли скрипт вызван из systemd.
systemd v232 добавил концепцию идентификатора вызова юнита, который передается юниту в $INVOCATION_ID
переменная окружения. Вы можете проверить, настроено оно или нет.
systemd v231 + устанавливает $JOURNAL_STREAM
переменная для служб, stdout или stderr которых подключены к журналу, что, похоже, относится к вашей службе, поэтому вы также можете проверить эту переменную, если вы используете systemd v231. (На v232 +, $INVOCATION_ID
определенно лучший выбор.)
Я не думаю, что в более старых версиях systemd всегда присутствует переменная окружения, но вы, конечно, можете определить ее самостоятельно, добавив что-то вроде этого в свою службу:
Environment=LAUNCHED_BY_SYSTEMD=1
Простое решение - использовать другой скрипт для запуска systemd. / Opt / foobar / rc_script должен просто вызвать systemctl start foobar.service
и systemctl stop foobar.service
.
Suse использует $SYSTEMD_NO_WRAP
, но я не знаю, является ли это стандартом systemd или специфичным для Suse.
if test -z "$SYSTEMD_NO_WRAP"; then
...
/usr/bin/systemctl [start|stop] xxx.service
Для «Amazon Linux 2» и «Red Hat Enterprise Linux 7» я нашел решение.
В этих системах Linux PID=1
является comm=systemd
. Родительский идентификатор PPID
запущенного скрипта systemd 1
.
Могут быть другие системы Linux, где это не так.
#!/bin/bash
VAR_IS_SYSTEMD_SYSTEM=$( [[ $(ps -o comm -p 1 --no-headers | tr -d ' ') == "systemd" ]] && echo true )
echo VAR_IS_SYSTEMD_SYSTEM = ${VAR_IS_SYSTEMD_SYSTEM}
VAR_IS_DAEMON_SCRIPT=$( [[ "${PPID}" == "1" ]] && echo true )
echo VAR_IS_DAEMON_SCRIPT = ${VAR_IS_DAEMON_SCRIPT}
if [[ "${VAR_IS_SYSTEMD_SYSTEM}" = true ]] && [[ "${VAR_IS_DAEMON_SCRIPT}" = true ]]; then
echo "You are a systemd Daemon Script"
else
echo "You are a normal Script"
fi
Используемые элементы / команды:
ps -o comm -p 1 --no-заголовки
Получить имя команды процесса 1
tr -d ''
Удалите пробелы форматирования из команды ps
"$ {PPID}"
Родительский PID процесса bash