it-swarm.com.de

systemd ignoriert ExecStop in der Unit-Datei und führt es als Teil von ExecStart aus

Ich versuche, mehrere VirtualBox-Images beim Booten automatisch zu starten und beim Herunterfahren des Hosts vor dem Herunterfahren ordnungsgemäß herunterzufahren. Ich habe ein Bash-Skript, /usr/local/bin/vmctl.sh, das das Starten und Stoppen der Gast-Images über Aufrufe von VBoxManage verwaltet. Der Startaufruf ist sehr einfach - er durchläuft nur eine Liste von Bildern und ruft VBoxManage startvm --type headless "<imgname>" auf und beendet dann 0. Der Stoppaufruf durchläuft die Liste und ruft VBoxManage controlvm "<imgname>" acpipowerbutton auf und wiederholt sich, bis VBoxManage list runningvms ein zurückgibt leere Liste OR 60 Sekunden vergehen, bevor es 0 beendet. Das Ausführen des Skripts über die Befehlszeile funktioniert einwandfrei.

Ich habe eine Unit-Datei in /lib/systemd/system/vmctl.service eingerichtet:

[Unit]
Description=VirtualBox Control
After=virtualbox.service

[Service]
ExecStart=/usr/local/bin/vmctl.sh start
ExecStop=/usr/local/bin/vmctl.sh stop

[Install]
WantedBy=multi-user.target

Wenn ich systemctl start vmctl.service ausführe, werden sowohl die Start- als auch die Stoppzeile aufgerufen. Wenn ich systemctl stop vmctl.service aufrufe, gibt es einen Eintrag im Syslog, der Stopped VirtualBox Control angibt, aber nichts bewirkt.

Ich bin ein absoluter Neuling bei systemd. Ich habe kürzlich diese Ubuntu-Box auf 16.04 aktualisiert. Ich bin mir ziemlich sicher, dass es eine einfache Erklärung für dieses Verhalten gibt, die ich einfach nicht sehe.

Vielen Dank!


Update basierend auf Marks Vorschlag:

Ich habe die Syntax mit systemd-analyze verify /etc/systemd/system/vmctl.service bestätigt (nachdem ich die Datei dorthin verschoben habe - danke für den Tipp). Ich habe dann ExecStart und ExecStop wie vorgeschlagen geändert, habe systemctl daemon-reload ausgeführt und sehe immer noch dasselbe Verhalten. Das Protokoll zeigt, dass beide ausgeführt werden, wenn systemctl start vmctl aufgerufen wird, aber auch nicht, wenn systemctl stop vmctl ausgeführt wird:

# journalctl -u vmctl | tail
.
.
.
Apr 06 19:28:18 macmi10-builder systemd[1]: Started VirtualBox Control.
Apr 06 19:28:18 macmi10-builder echo[13901]: I started
Apr 06 19:28:18 macmi10-builder echo[13904]: I stopped
Apr 06 19:28:33 macmi10-builder systemd[1]: Stopped VirtualBox Control.
2
Jay MacDonald

Wie bereits erwähnt, besteht das Problem darin, dass vmctl.sh sofort beendet wird. Entgegen der Antwort von @ Christophe funktioniert das Gabeln höchstwahrscheinlich nicht, da vmctl.sh wahrscheinlich nicht verzweigt. Was Sie brauchen, ist ein oneshot Service mit RemainAfterExit=true. Wenn Sie es nur in oneshot ändern, erhalten Sie genau das gleiche Verhalten. Der Teil RemainAfterExit gibt an, dass der Dienst auch nach dem Beenden von ExecStart weiterhin als ausgeführt betrachtet werden sollte, sodass die ExecStop (s) nicht ausgeführt werden sollten.

5

Ihre systemd -Syntax ist korrekt. Ihr Problem liegt woanders.

Zunächst können Sie bestätigen, dass die Syntax selbst korrekt ist:

systemd-analyze verify /path/to/your/vmctl.service

Zweitens versuchen Sie, diese Zeilen zu ersetzen:

ExecStart=/bin/echo "I started"
ExecStop=/bin/echo "I stopped"

Nachdem Sie systemctl start vmctl oder systemctl stop vmctl ausgeführt haben, verwenden Sie journalctl -u vmctl, um die Protokolle zu überprüfen. Ich gehe davon aus, dass Sie bestätigen, dass systemd die richtigen Befehle ausgeführt hat.

Auch /lib/systemd/system ist für einen Speicherort für Pakete zur Verwaltung von Systemdateien vorgesehen. Dateien, die von Menschen geändert und manuell verwaltet werden, sollen in /etc/systemd/system abgelegt werden.

4
Mark Stosberg

Die Standardeinstellung für den Typ einer Service-Einheit ist Typ = einfach. Diese Einstellung wird verwendet, wenn der mit ExecStart = konfigurierte Prozess der Hauptprozess des Service ist. Eine solche Einheit wartet, bis der von ExecStart festgelegte Prozess zurückkehrt, und deaktiviert ihn dann, indem der von ExecStop festgelegte Prozess ausgeführt wird. In Ihrem Fall geschieht dies, sobald die virtuellen Maschinen gestartet wurden (nicht das, was Sie wollen).

Type = forking wird verwendet, wenn erwartet wird, dass der von ExecStart angegebene Prozess nach Abschluss des Startvorgangs beendet wird, während die untergeordneten Prozesse im Hintergrund weiterlaufen. Dies ist das Verhalten traditioneller UNIX-Daemons und in Ihrem Fall die empfohlene Wahl. Der von ExecStop angegebene Prozess wird ausgeführt, wenn der Dienst abstürzt oder wenn der Befehl "systemctl stop vmctl" ausgeführt wird.

So sollte Ihre Unit-Datei sein:

[Unit]
Description=VirtualBox Control
After=virtualbox.service

[Service]
Type=forking
ExecStart=/usr/local/bin/vmctl.sh start
ExecStop=/usr/local/bin/vmctl.sh stop

[Install]
WantedBy=multi-user.target
0
Christophe