Puis-je utiliser systemd pour démarrer et arrêter un service basé sur la présence d'un fichier?

9

Ma configuration jusqu'à présent est:

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

Cela fonctionne très bien au démarrage mais foo.service ne sera pas tué lorsque /tmp/foo.path sera supprimé. Existe-t-il un moyen de faire en sorte que systemd le fasse ou n'est-ce tout simplement pas l'outil approprié pour le travail?

mpr
la source

Réponses:

4

J'essaierais ça. Créez un service supplémentaire à l'aide de PathChanged:

foo-stop.path

[Path] 
PathChanged=/tmp/foo.path

[Install] 
WantedBy=multi.user.target

Créez ensuite: foo-stop.service

Faites vérifier le script "ExecStart" pour voir s'il a /tmp/foo.pathété supprimé (puisque PathChanged peut également se déclencher sur d'autres modifications). Si le chemin a été supprimé, appelez le script /bin/systemctl stop foo.

Mark Stosberg
la source
1
Je vais aller de l'avant et accepter cela jusqu'à ce que systemd offre une option explicite pour faire de même.
mpr
0

Si vous pouvez tuer le processus lié au fichier PID (/run/foo.pid) lorsque /tmp/foo.path est supprimé (par exemple, les deux en tant qu'actions dans le script d'arrêt du service), alors oui.

Je l'ai réalisé sur un Tomcat fonctionnant sur <= RHEL-7.7 avec un service de forking incluant une action ExecStartPost qui note le contenu du fichier pid de l'application (catalina.pid) dans le chemin PIDFile du service. Un "PathExists" dans le fichier .path correspondant traque l'apparition sur ce catalina.pid afin de connecter le service systemd lorsque l'utilisateur (dans mon cas, non privilégié) appelle le script de démarrage. Lorsque l'utilisateur lance l'arrêt, le fichier pid de l'application est supprimé, le PID (également non privilégié) meurt gracieusement et systemd arrête le service en tant que conséquence de supervision du 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
# . . .

Cette façon m'a également servi pour les applications Spring Boot. Mais comme ils sont nés suspendus à un processus bash, j'ai dû tuer immédiatement ce processus parent afin de forcer PID 1 à être le parent de l'application. Sinon, journalctl affiche un message "* .service: Superviser le processus XXXXX qui n'est pas notre enfant. Nous ne remarquerons probablement pas quand il se termine.", Et à la fin le service systemd ne s'arrête pas à l'action d'arrêt de l'utilisateur.

Pere Moltó
la source