Kann ich systemd verwenden, um einen Dienst basierend auf dem Vorhandensein einer Datei zu starten und zu stoppen?

9

Meine bisherige Konfiguration lautet:

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

Dies funktioniert beim Start einwandfrei, aber foo.service wird nicht beendet, wenn /tmp/foo.path entfernt wird. Gibt es eine Möglichkeit, systemd dazu zu bringen, oder ist es einfach nicht das geeignete Werkzeug für den Job?

mpr
quelle

Antworten:

4

Ich würde es versuchen. Erstellen Sie einen zusätzlichen Service mit PathChanged:

foo-stop.path

[Path] 
PathChanged=/tmp/foo.path

[Install] 
WantedBy=multi.user.target

Dann erstellen Sie: foo-stop.service

Lassen Sie das Skript "ExecStart" überprüfen, ob /tmp/foo.pathes gelöscht wurde (da PathChanged auch bei anderen Änderungen ausgelöst werden kann). Wenn der Pfad entfernt wurde, rufen Sie das Skript auf /bin/systemctl stop foo.

Mark Stosberg
quelle
1
Ich werde dies so lange akzeptieren, bis systemd eine explizite Option bietet, um dasselbe zu tun.
mpr
0

Wenn Sie den an die PID-Datei (/run/foo.pid) gebundenen Prozess beenden können, wenn /tmp/foo.path entfernt wird (z. B. beide als Aktionen im Skript zum Herunterfahren des Dienstes), dann ja.

Ich habe es auf einem Tomcat erreicht, der über <= RHEL-7.7 ausgeführt wird, mit einem Forking-Service, der eine ExecStartPost-Aktion enthält, die den Inhalt der Anwendungs-PID-Datei (Catalina.PID) im PIDFile-Pfad des Dienstes notiert. Ein "PathExists" in der entsprechenden .path-Datei verfolgt das Erscheinen in dieser Catalina.pid, um den systemd-Dienst zu verknüpfen, wenn der Benutzer (in meinem Fall nicht privilegiert) das Startskript aufruft. Wenn der Benutzer das Herunterfahren startet, wird die Anwendungs-PID-Datei entfernt, die PID (ebenfalls nicht privilegiert) stirbt ordnungsgemäß und systemd stoppt den Dienst als Folge der Überwachung der systemd-PID.

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
# . . .

Dieser Weg diente mir auch für Spring Boot-Anwendungen. Aber als sie geboren wurden, die an einem Bash-Prozess hängen, musste ich diesen übergeordneten Prozess sofort beenden, um PID 1 als übergeordneten Anwendungsbereich zu erzwingen. Wenn nicht, zeigt journalctl die Meldung "* .service: Überwachungsprozess XXXXX, der nicht unser Kind ist. Wir werden es höchstwahrscheinlich nicht bemerken, wenn er beendet wird.", Und am Ende stoppt der systemd-Dienst nicht beim Herunterfahren des Benutzers.

Pere Moltó
quelle