Wie erstelle ich einen virtuellen systemd-Dienst, um mehrere Instanzen gemeinsam zu stoppen/starten?

Wie erstelle ich einen virtuellen systemd-Dienst, um mehrere Instanzen gemeinsam zu stoppen/starten?

Ich plane, mehrere Instanzen derselben Web-App für Kunden zu hosten, die verwenden systemd. Ich möchte in der Lage sein stop, startjede Kundeninstanz mithilfe von zu verwalten systemdund die gesamte Sammlung von Kundeninstanzen als einen einzigen Dienst zu behandeln, der gemeinsam gestoppt und gestartet werden kann.

systemdscheint die Bausteine ​​bereitzustellen PartOf, die ich mithilfe von und Vorlagen-Unit-Dateien brauche, aber wenn ich den übergeordneten Dienst stoppe, wird der untergeordnete Kundendienst nicht gestoppt. Wie kann ich das mit systemd zum Laufen bringen? Hier ist, was ich bisher habe.

Die übergeordnete Unit-Datei app.service:

[Unit]
Description=App Web Service

[Service]
# Don't run as a deamon (because we've got nothing to do directly)
Type=oneshot
# Just print something, because ExecStart is required
ExecStart=/bin/echo "App Service exists only to collectively start and stop App instances"
# Keep running after Exit start finished, because we want the instances that depend on this to keep running
RemainAfterExit=yes
StandardOutput=journal

Eine Unit-Vorlagendatei mit dem Namen [email protected], die zum Erstellen von Kundeninstanzen verwendet wird:

[Unit]
Description=%I Instance of App Web Service

[Service]
PartOf=app.service
ExecStart=/home/mark/bin/app-poc.sh %i
StandardOutput=journal

Mein app-poc.shSkript (Proof of Concept, der einfach in einer Schleife in eine Protokolldatei druckt):

#!/bin/bash
# Just a temporary code to fake a full daemon.
while :
do
  echo "The App PoC loop for $@"
  sleep 2;
done

Für den Proof of Concept habe ich die Systemd-Unit-Dateien in ~/.config/systemd/user.

Ich starte dann das übergeordnete Element und eine auf der Vorlage basierende Instanz (nachher systemctl --user daemon-reload):

systemctl --user start app
systemctl --user start [email protected]

Durch die Verwendung journalctl -fkann ich sehen, dass beide gestartet wurden und dass die Kundeninstanz weiterhin ausgeführt wird. Jetzt gehe ich davon aus, dass das Herunterfahren des übergeordneten Elements das untergeordnete Element stoppt (weil ich verwendet habePartOf), aber das ist nicht der Fall. Außerdem wird beim Starten des übergeordneten Elements das untergeordnete Element nicht wie erwartet gestartet.

systemctl --user stop app

Danke!

(Ich verwende Ubuntu 16.04 mit systemd 229).

Antwort1

Ich habe gelernt, dass dies der Zweck der systemd-Zieleinheiten ist. Durch die Verwendung einer Zieleinheit erhalte ich die gewünschten Vorteile, ohne den [Service]oben beschriebenen Fake-Abschnitt erstellen zu müssen. Eine funktionierende Beispieldatei einer Zieleinheit sieht folgendermaßen aus:

# named like app.target
[Unit]
Description=App Web Service

# This collection of apps should be started at boot time.
[Install]
WantedBy=multi-user.target

Dann sollte jede Kundeninstanz PartOfden [Unit]Abschnitt enthalten (wie von @meuh angemerkt) und sollte auch einen [Install]Abschnitt haben, damit an dem spezifischen Dienst gearbeitet werden kann enable:disable

# In a file name like [email protected]
[Unit]
Description=%I Instance of App Web Service
PartOf=app.target

[Service]
ExecStart=/home/mark/bin/app-poc.sh %i
Restart=on-failure
StandardOutput=journal

# When the service runs globally, make it run as a particular user for added security
#User=myapp
#Group=myapp

# When systemctl enable is used, make this start when the App service starts
[Install]
WantedBy=app.target

Um die Kundeninstanz aufzurufen und sie beim Start des Ziels starten zu lassen, wird dieser einmalige Aktivierungsbefehl verwendet:

 systemctl enable app

Jetzt kann ich an dieser Stelle stopund startzum Stoppen app@customereiner bestimmten Instanz verwenden oder und , start appum stop appalle Apps gleichzeitig zu stoppen.

Antwort2

Sie müssen die Linie verschieben

PartOf=app.service

aus [Service]und in den [Unit]Abschnitt, und fügen Sie die [Unit]der app.serviceListe der Kunden zu starten, zB

[email protected] [email protected]

oder wie sourcejedi in den Kommentaren sagte, Requires=dasselbe. Sie können die behalten, PartOfum Dienste zu stoppen, die Sie manuell starten und die nicht in der obigen Liste enthalten sind, wie .systemctl --user start [email protected]

verwandte Informationen