Systemd: So führen Sie ein Skript nur beim Herunterfahren aus (nicht beim Neustart)

Systemd: So führen Sie ein Skript nur beim Herunterfahren aus (nicht beim Neustart)

Es gibt hier viele Lösungen zum Ausführen eines Skripts beim Herunterfahren/Neustart, aber ich möchte, dass mein Skript nur beim Herunterfahren ausgeführt wird.

Ich habe versucht, mein Skript in /usr/lib/systemd/systemd-shutdown zu platzieren und den Parameter $1 zu überprüfen, wie zu sehenHier, aber es funktioniert nicht.

Irgendwelche Ideen ?

System: Archlinux mit Gnome-Shell

$systemctl --version                                                                                                                                                                                 
systemd 229
+PAM -AUDIT -SELINUX -IMA -APPARMOR +SMACK -SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN

Antwort1

Ich habe endlich herausgefunden, wie das geht.

Das ist ein etwas stümperhafter Gedanke, aber er funktioniert.

Ich habe einen Teil dieses Threads verwendet:https://stackoverflow.com/questions/25166085/wie-kann-ein-systemd-gesteuerter-dienst-zwischen-shutdown-und-reboot-unterscheiden

und dieser Thread: Wie führe ich direkt vor dem Herunterfahren ein Skript mit systemd aus?

Ich habe diesen Dienst erstellt/etc/systemd/system/shutdown_screen.service

[Unit]
Description=runs only upon shutdown
Conflicts=reboot.target
After=network.target

[Service]
Type=oneshot
ExecStart=/bin/true
ExecStop=/bin/bash /usr/local/bin/shutdown_screen
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Dies wird beim Herunterfahren/Neustart/Anhalten/was auch immer ausgeführt. (Vergessen Sie nicht, es zu aktivieren.)

Und in mein Skript /usr/local/bin/shutdown_screen habe ich Folgendes eingefügt:

#!/bin/bash
# send a shutdown message only at shutdown (not at reboot)    
/usr/bin/systemctl list-jobs | egrep -q 'reboot.target.*start' || echo "shutdown" | nc 192.168.0.180 4243 -w 1

Dadurch wird eine Abschaltmeldung an meinen Arduino gesendet, der wiederum meinen Bildschirm abschaltet.

Antwort2

Laut der systemd.specialManpage sollten Sie verwenden Before=poweroff.target.

ausschalten.target

A special target unit for shutting down and powering off the system.

Applications wanting to power off the system should start this unit.

runlevel0.target is an alias for this target unit, for compatibility with SysV.

Darüber hinaus sollten Sie, wie ich in meinem Kommentar erwähnt habe, benutzerdefinierte Skripts in ablegen /etc/systemd/system/. Das /usr/lib/systemd/system/Verzeichnis ist für vom System bereitgestellte Skripts vorgesehen.

Also, vielleicht so etwas wie das hier:

[Unit]
Description=runs only upon shutdown
DefaultDependencies=no
Conflicts=reboot.target
Before=shutdown.target
Requires=poweroff.target

[Service]
Type=oneshot
ExecStart=/bin/true
ExecStop=/usr/local/bin/yourscript
RemainAfterExit=yes

Antwort3

Aus den Antworten hier geht hervor, dass es viele Missverständnisse darüber gibt, wie systemd funktioniert. Erstens: Verwenden Sie keine Konflikte, um ein Ziel auszuschließen. Es ist beabsichtigt, zu verhindern, dass widersprüchliche Dienste gleichzeitig ausgeführt werden.

Wenn für eine Einheit die Einstellung „Conflicts=“ auf einer anderen Einheit festgelegt ist, wird durch das Starten der Einheit die Einheit gestoppt und umgekehrt.

Unit bedeutet eine .service-Datei, die einen bestimmten Dienst starten soll, nicht ein zu erreichendes Ziel. Mit anderen Worten: Conflicts=reboot.targetIm besten Fall ist es bedeutungslos und im schlimmsten Fall verhindert es einen Neustart. Tun Sie das nicht. Das heißt nicht, dass Sie dies beim Neustart nicht ausführen sollen. Es bedeutet, entweder diesen Dienst oder das reboot.target abzubrechen, je nach Zeitpunkt und wie systemd diese fehlerhafte Verwendung von Konflikten interpretiert.

Dies ist ein Beispiel für eine aktuell eingerichtete Einheit (auch bekannt als .service-Datei), die nur beim Herunterfahren und nicht beim Neustart ausgeführt wird:

[Unit]
Description=Play sound
DefaultDependencies=no
Before=poweroff.target halt.target

[Service]
ExecStart=/usr/local/bin/playsound.sh
ExecStop=/usr/local/bin/playsound.sh
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=poweroff.target halt.target 

poweroff.target entspricht dem alten Systemv-Runlevel0, das nur beim Herunterfahren erreicht wird. halt.target ist ein alternativer Herunterfahrpfad, der von systemd verwendet wird und auch nicht durch einen Neustart erreicht werden kann. Der Installationsabschnitt weist systemd an, diesen Dienst der Liste hinzuzufügen, die abgeschlossen werden muss, bevor poweroff.targetsie halt.targetals erreicht gilt.

Dieser Dienst ist auf meinem System installiert und läuft.

Antwort4

Ich habe die meisten Beiträge hier und auf verschiedenen Websites getestet. Der einzige, der tatsächlich nur beim Neustart funktionierte (nicht beim erneuten Booten - sondern tatsächlich beim Herunterfahren-Halten-Ausschalten fehlschlug), ist der Beitrag von @benoit2600. Sein zweiter/Lösungsbeitrag

Aber nach dem Testen habe ich festgestellt, dass Sie in Unit alle 4 Ziele verwenden können und es NUR ausgeführt wird, wenn eines davon tatsächlich verwendet wird. Der Rest entspricht seinen und Ihren Anforderungen. In „ExecStop=mycommand“ habe ich einfach meinen direkten Befehl eingegeben (da ich keinen vollständigen Bash benötigte).

[Unit]
Conflicts=reboot.target poweroff.target halt.target shutdown.target

verwandte Informationen