Wie führe ich ein Skript mit systemd kurz vor dem Herunterfahren aus?

58

Was muss ich in den [install]Abschnitt einfügen, damit systemd /home/me/so.pldirekt vor dem Herunterfahren ausgeführt wird und auch bevor es /proc/self/net/devzerstört wird?

[Unit]
Description=Log Traffic

[Service]
ExecStart=/home/me/so.pl

[Install]
?
sid_com
quelle

Antworten:

66

Die vorgeschlagene Lösung besteht darin, das Service-Gerät als normalen Service zu betreiben - siehe [Install]Abschnitt. Also muss alles umgekehrt gedacht werden, auch Abhängigkeiten. Weil die Reihenfolge des Herunterfahrens die umgekehrte Startreihenfolge ist. Deshalb muss das Skript eingefügt werden ExecStop=.

Die folgende Lösung funktioniert für mich:

[Unit]
Description=...

[Service]
Type=oneshot
RemainAfterExit=true
ExecStop=<your script/program>

[Install]
WantedBy=multi-user.target

RemainAfterExit=truewird benötigt, wenn Sie keine ExecStartAktion haben.

Stellen Sie nach dem Erstellen der Datei sicher, dass systemctl daemon-reloadund systemctl enable yourservice --now.

Ich habe es gerade von systemd IRC bekommen, Credits gehen an mezcalero.

Matthias
quelle
6
Am Ubuntu 16.04 müssen Sie eine haben ExecStart=/bin/true.
Niels
3
Ich gehe davon aus, dass WARUMRemainAfterExit=true erforderlich ist, wenn keine vorhanden ExecStartist, weil systemdich nicht versuchen werde, auszuführen, ExecStopwenn ich der Meinung bin, dass der Dienst nicht ausgeführt wird. RemainAfterExit=trueveranlasst systemdzu glauben, dass der Dienst ausgeführt wird, wodurch er ExecStopbeim Herunterfahren ausgeführt wird.
Felipe Alvarez
1
Gibt es eine Möglichkeit, sicherzustellen, dass dieses Skript ausgeführt und abgeschlossen wird, bevor Benutzersitzungen und Benutzerprozesse beendet werden?
Richmb
@richmb Überhaupt nicht. Aus den Dokumenten :Note that it is usually not sufficient to specify a command for this setting that only asks the service to terminate (for example, by queuing some form of termination signal for it), but does not wait for it to do so.
svenwltr
Ich habe dies und verschiedene Iterationen darauf ausprobiert, aber es funktioniert nicht auf Debian Stretch.
2.
8

Soweit ich sehen kann, macht das, was ich brauche (aber ich weiß nicht genau warum).

[Unit]
Description=Log Traffic
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target


[Service]
ExecStart=/usr/local/bin/perl /home/me/log_traffic.pl --stop
Type=oneshot
sid_com
quelle
3
Es funktioniert aus zwei Gründen: 1) DefaultDependencies = no bewirkt, dass alle Abhängigkeiten ignoriert werden und beim Start "zuerst" und beim Stoppen "zuletzt" ausgeführt werden, wobei die Klauseln "Vorher" und "Nachher" immer beachtet werden. 2) Es gibt eine Before-Klausel für Shutdown- / Neustart- / Stopp-Ziele, die ausgeführt wird, kurz bevor Shutdown- / Neustart- / Stopp-Ziele erreicht werden (da sie nur bei Stopp ausgeführt werden, geschieht dies, was Sie möchten).
RDP
Sie können kexec.targetdas Vorher-Bit hinzufügen
Hanetzer
Das funktioniert bei mir nicht
Bug Killer
Ich sehe nicht, wie das funktioniert, wenn Sie nicht auch WantedBy=shutdown.target reboot.target halt.targetden [Unit]Abschnitt hinzufügen . Before=& After=Abhängigkeiten nicht ändern.
Rsaw
1
@FelipeAlvarez: Ich habe meinen Kommentar entfernt.
sid_com
7
  • Um einen Dienst direkt vor dem Starten eines der Dienste reboot / shutdown / halt / kexec auszuführen (dh im letzten Moment, bevor das Root-Dateisystem wieder schreibgeschützt wird), verwenden Sie diese Dienstkonfiguration:

    [Unit]
    Description=Save system clock on shutdown
    DefaultDependencies=no
    After=final.target
    
    [Service]
    Type=oneshot
    ExecStart=/usr/lib/systemd/scripts/fake-hwclock.sh save
    
    [Install]
    WantedBy=final.target
    

    Aktivieren Sie es mit:

    systemctl enable my_service.service
    
  • Um ein Skript direkt vor dem eigentlichen Neustart / Herunterfahren / Anhalten / Kexec auszuführen (wenn Sie nicht in das Root-Dateisystem schreiben können, da es schreibgeschützt erneut bereitgestellt wurde), fügen Sie dieses ausführbare Skript dem /usr/lib/systemd/system-shutdownVerzeichnis hinzu.

    Unmittelbar vor dem eigentlichen Systemstopp / Ausschalten / Neustart / Kexec führt systemd-shutdown alle ausführbaren Dateien in / usr / lib / systemd / system-shutdown / aus und übergibt ihnen ein Argument: entweder "Halt", "Ausschalten", "Neustart" "oder" kexec ", abhängig von der gewählten Aktion. Alle ausführbaren Dateien in diesem Verzeichnis werden parallel ausgeführt, und die Ausführung der Aktion wird nicht fortgesetzt, bevor alle ausführbaren Dateien abgeschlossen sind.

Siehe auch:

https://www.freedesktop.org/software/systemd/man/bootup.html

https://www.freedesktop.org/software/systemd/man/systemd-halt.service.html

Piotr Jurkiewicz
quelle
1
Ich möchte etwas so nah wie möglich ausführen, nachdem ich einen Neustart eingeleitet habe, weit vor dem final.target. Idealerweise möchte ich, dass es das erste ist, was nach dem Benutzer ausgeführt wird $ sudo reboot.
Jaime Hablutzel
5

Ich bin nicht ganz sicher, aber ich glaube nicht, dass Sie den Installationsteil benötigen, obwohl ich ihn explizit hinzugefügt habe. Ich habe es auch nicht getestet, aber ich denke, es sollte Ihnen den Einstieg erleichtern:

[Unit]
Description=Log Traffic
Requires=network.target
After=network.target
Before=shutdown.target
DefaultDependencies=no

[Service]
ExecStart=/home/me/so.pl
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=shutdown.target
Ulrich Dangel
quelle
Wenn ich das versuche, wird das Skript kurz nach dem Start (Booten) ausgeführt.
sid_com
@sid_com Versuchen Sie nach dem Lesen von thread.gmane.org/gmane.comp.sysutils.systemd.devel/4515/… , DefaultDependencies = no hinzuzufügen, und entfernen Sie möglicherweise den Installationsabschnitt. Andernfalls kann es hilfreich sein, die After / Required-Leitungen zu entfernen.
Ulrich Dangel