Могу ли я использовать systemd для запуска и остановки службы в зависимости от наличия файла?

9

Мой конфиг до сих пор:

foo.path

[Path] 
PathExists=/tmp/foo.path

[Install] 
WantedBy=multi.user.target

foo.service

[Unit]
Description=Matt Test
BindsTo=foo.path

[Service]
ExecStart=/bin/sh /home/mpekar/bin/foo.sh 
PIDFile=/run/foo.pid

Это прекрасно работает при запуске, но foo.service не будет убит при удалении /tmp/foo.path. Есть ли способ заставить systemd сделать это или это просто не подходящий инструмент для работы?

MPR
источник

Ответы:

4

Я бы попробовал это. Создайте дополнительный сервис, используя PathChanged:

Foo-stop.path

[Path] 
PathChanged=/tmp/foo.path

[Install] 
WantedBy=multi.user.target

Затем создайте: foo-stop.service

Сделайте так, чтобы скрипт «ExecStart» проверил, был ли /tmp/foo.pathудален (так как PathChanged может также запускать другие изменения). Если путь был удален, вызовите скрипт /bin/systemctl stop foo.

Марк Стосберг
источник
1
Я собираюсь принять это до тех пор, пока systemd не предложит такую ​​же возможность.
mpr
0

Если вы можете уничтожить процесс, связанный с PIDFile (/run/foo.pid) при удалении /tmp/foo.path (например, оба действия как действия в скрипте отключения службы), тогда да.

Я добился этого на Tomcat, работающем над <= RHEL-7.7, с сервисом разветвления, включающим в себя действие ExecStartPost, которое записывает содержимое pidfile приложения (catalina.pid) в путь PIDFile службы. «PathExists» в соответствующем файле .path отслеживает появление в этом catalina.pid, чтобы перехватить службу systemd, когда пользователь (в моем случае непривилегированный) вызывает сценарий запуска. Когда пользователь запускает завершение работы, pid-файл приложения удаляется, PID (также непривилегированный) изящно умирает, и systemd останавливает службу как следствие pid systemd.

poc.service:

[nouser@nohost system]# cat poc.service
# . . .
[Unit]
After=network.target
After=%p.path
Wants=%p.path
# . . . 
[Service]
Type=forking
Environment="%p_APPLICATION_PID_FILE=/opt/%p/logs/catalina.pid"
PIDFile=/var/run/%p.pid
ExecStart=/bin/sh -c '/path/to/tomcat/control/script/invoked/with/su/hypen start'
ExecStartPost=/bin/sh -c 'cat ${%p_APPLICATION_PID_FILE} > $(systemctl show %n -p PIDFile|cut -f2- -d"=")'
ExecStop=/bin/sh -c '/path/to/tomcat/control/script/invoked/with/su/hypen stop'
# . . .

poc.path:

[nouser@nohost system]# cat poc.path
# . . .
[Path]
PathExists=/opt/%p/logs/catalina.pid
# . . .

Этот способ также послужил мне для приложений Spring Boot. Но поскольку они родились висящими в процессе bash, мне пришлось немедленно убить этот родительский процесс, чтобы PID 1 стал родительским приложением. Если нет, journalctl показывает сообщение «* .service: Контроль процесса XXXXX, который не является нашим дочерним элементом. Скорее всего, мы не заметим, когда он завершится.», И в конце служба systemd не останавливается при отключении пользователя.

Пере Молто
источник