
У меня есть файл модуля systemd (serv_unit.service):
[Unit]
Description=My service
[Service]
Type=simple
Restart=always
RestartSec=60
StartLimitInterval=400
StartLimitBurst=3
ExecStart=/etc/init.d/myscript start
[Install]
WantedBy=multi-user.target
/etc/init.d/myscript
source /etc/myfile.sh # JAVA_home & other vars are resolved through this file
mode=$1
case "$mode" in
'start')
# Start daemon
daemon --user=abc $JAVA_HOME/bin/java -cp $appClassPath $MAIN_CLASS $args &
Проблема, с которой я сталкиваюсь, возникает при запуске следующей команды:
systemctl start serv_unit.service
Я не вижу процесс Java. Но когда я удаляю завершающий&то есть:
daemon --user=abc $JAVA_HOME/bin/java -cp $appClassPath $MAIN_CLASS $args
можно увидеть процесс Java (и этот процесс Java не аварийно завершается, что исключает возможность его аварийного завершения в фоновом режиме)
В чем причина?
решение1
Помимо основного вопроса, вызов скриптов init.d из systemd немного избыточен и вообще плохая идея для начала. Вот все, что вам нужно:
User=abc
EnvironmentFile=/etc/myfile.conf
ExecStart=/usr/bin/env $JAVA_HOME/bin/java -cp $appClassPath $MAIN_CLASS $args
EnvironmentFile может содержать только простые назначения KEY=value, но если конфигурация должна быть представлена в синтаксисе скрипта оболочки, вы также можете использовать:
User=abc
ExecStart=/bin/sh -c ". /etc/myfile.sh && exec $$JAVA_HOME/bin/java -cp $$appClassPath $$MAIN_CLASS $$args"
(В обоих случаях следует также установить SyslogIdentifier=
, выдает ли служба сообщения stdout.)
Типы услуг
Ожидается, что службы Systemd будут следовать определенным правилам. У одного .service
блока может быть только один «главный» процесс-демон, и эта Type=
опция сообщает systemd, как работает этот процесс.
Type=simple
указывает, что начальный процесс (т.е. то, что запущено из ExecStart=) сам по себе является основным процессом службы. Как только основной процесс завершается, служба считаетсяостановился, поэтому все остатки убираются.
Это означает, что если вы используете Type=simple, вы сообщаете systemd, что демонне будетперейти в 'фоновый'. Фактически, вы также сообщаете systemd, чтоскрипт init.d– нет daemon
– это основной процесс сервиса...
Поэтому было бы лучше, если бы скрипт init.d не только не пытался перевести сам демон в фоновый режим, но и запускал его exec
следующим образом:
case "$mode" in
'start-foreground')
# Start daemon in foreground
exec daemon --user=abc $JAVA_HOME/bin/java -cp $appClassPath $MAIN_CLASS $args
С другой стороны,Type=forking
указывает на то, что первоначальный процессволяfork и выход во время процедуры запуска, а основной процесс должен быть обнаружен из PIDFile= или эвристически.
Какой из них использовать
С демонами, которые имеютвстроенныйРежим 'daemonize' Type=forking
имеет существенное преимущество: служба systemd остается в состоянии 'Starting' до тех пор, пока демон наконец не попытается перейти в фоновый режим, после чего он окончательно переходит в состояние 'Started/Active'. Это помогает при настройке зависимостей, например, служба A может объявить "After=B.service".
Но если фоновый режим выполняется внешними средствами, такими как &
функция оболочки, без чего-либо, что могло бы сообщить, готов ли демон или нет, то это полностьюбесполезныйи вам, вероятно, следует просто использовать его Type=simple
без каких-либо фоновых опций.