Ausführen eines Skripts beim Herunterfahren, bevor das Netzwerk ausfällt

Ausführen eines Skripts beim Herunterfahren, bevor das Netzwerk ausfällt

Ich möchte ein Skript ausführen, wenn mein Computer (Ubuntu 22.04) heruntergefahren wird, das Netzwerk aber noch verfügbar ist.

Der Rat indieser Threadhilfreich erklärt, wie man eine systemd-Dienstdatei erstellt, die beim Herunterfahren ausgeführt wird, und das Skript wurde tatsächlich ausgeführt, aber das Skript konnte eine Aufgabe nicht abschließen, die Zugriff auf das Netzwerk erforderte, also gehe ich davon aus, dass das Netzwerk bereits heruntergefahren wurde.

Wenn verschiedene Threads gefunden werden (zBDieses hier) darüber, wie man sicherstellt, dass ein Skript ausgeführt wird, bevor das Netzwerk heruntergefahren wird, aber alle schienen leicht unterschiedliche Ratschläge zu geben. Ich habe verschiedene Permutationen von Before=network-online.target, After=network-online.target und Requires=network-online.target ausprobiert, aber keine davon schien zu funktionieren.

Weiß jemand, wie man sicherstellt, dass das Skript ausgeführt werden kann, während das Netzwerk noch verfügbar ist?

Übrigens bin ich nicht darauf festgelegt, dies als systemd-Aufgabe zu tun. Ich ging davon aus, dass dies die beste Vorgehensweise wäre, aber wenn es eine andere Möglichkeit gibt, dasselbe zu erreichen, wäre das in Ordnung.

Antwort1

Ich weiß nicht, ob das hilft, aber schauen Sie sich die systemd .target-Dateien an. Das ist, was systemd beim Herunterfahren tatsächlich ausführt. Hier ist ein Link.

https://documentation.suse.com/smart/linux/html/reference-managing-systemd-targets-systemctl/index.html

shutdown.target
       A special target unit that terminates the services on system
       shutdown.

       Services that shall be terminated on system shutdown shall add
       Conflicts= and Before= dependencies to this unit for their service
       unit, which is implicitly done when DefaultDependencies=yes is set
       (the default).

Die .target-Dateien befinden sich zusammen /usr/lib/systemd/systemmit den .service-Dateien. Ich würde das auf einer VM machen, auf der ich problemlos einen Snapshot zurücksetzen kann ;)

Antwort2

OK, ich habe noch ein bisschen herumprobiert und Fortschritte gemacht, aber das Problem noch nicht wirklich gelöst.

Es stellt sich heraus, dass das Netzwerk einigermaßen funktioniert, wenn ich After=network.target in der Servicedatei habe. Es scheint, dass die Namensauflösung nicht funktioniert. Wenn ich also die Interaktion mit dem Remotecomputer ausführe und dabei den Hostnamen des Remotecomputers angebe, funktioniert es nicht. Wenn ich ihn jedoch über seine IP-Adresse angebe, funktioniert es.

Ich hatte gehofft, dass ich dies beheben könnte, indem ich After=network.target nss-lookup.target einstelle, aber das hat es nicht behoben.

Irgendwelche Ideen, was ich sonst noch versuchen könnte?

Antwort3

Spontan fällt mir meine alte Glatze und ich könnte ein Bash-Skript schreiben:

#!/bin/bash
Your Commands;
shutdown -h now

Das Herunterfahren sollte erst ausgeführt werden, wenn die Ausführung „Ihrer Befehle“ abgeschlossen ist.

Das Skript könnte „myshutdown“ heißen und sogar als Alias ​​für den Systembefehl verwendet werden.

(Es scheint mir zu simpel und ich bin sicher, dass mich jemand auf meine Fehler hinweisen wird!) (Danke für die Bearbeitung zum Aufräumen des Codes, „Marco“)

Antwort4

Der Schlüssel zum Verständnis, wie man einen Dienst beim Herunterfahren stoppen kann, bevor das Netzwerk verloren geht, ist das Wissen, dassDie Reihenfolge beim Herunterfahren ist die umgekehrte Reihenfolge beim Hochfahren.. Daher sollte Ihr Dienst beginnennach network-online.targetund ist gleichzeitig von abhängig network-online.target, da das Netzwerk aktiv sein muss. Darüber hinaus gibt es ExecStart=und ExecStop=Aktionen, die Sie definieren können. Da das Skript beim Herunterfahren ausgeführt werden soll, also wenn der Dienst beendet wird, möchten Sie ExecStop=den Verweis auf Ihr Skript definieren.

Gehen Sie zum Einrichten wie folgt vor:

  • Im[Einheit]Abschnitt, erstellen Sie eine Requires=network-online.targetAbhängigkeit
  • Legen Sie die Reihenfolge auf fest After=network-online.target.
  • Im[Service]Abschnitt: Definieren Sie keine ExecStart=Aktion.
  • Setzen Sie RemainAfterExit=true, da wir keine ExecStart=Aktion erstellt haben.
  • Erstellen Sie abschließend eine ExecStop=Aktion, die auf Ihr Skript verweist, beispielsweise ExecStop=/home/username/bin/testscript.sh.

Erinnern,Die Reihenfolge beim Herunterfahren ist die umgekehrte Reihenfolge beim Hochfahren.. Wenn Ihr Dienst also gestoppt wird, ExecStop=wird Ihr Skript, das in platziert ist, ausgeführt. Und weil wir diesen Dienst gestartet habennach network-online.target, es wird heruntergefahrenVorAlle Dienste network-online.targetsind heruntergefahren.

Als Beispiel...

Hier ist ein einfaches Testskript, mit dem Sie curlIhre öffentliche IP-Adresse abrufen können. Damit dies ordnungsgemäß ausgeführt werden kann, ist DNS erforderlich.

#!/bin/bash

# NAME: testscript.sh
# PATH: /home/username/bin

NOW=`date`
IP=`curl -s https://ipinfoio/ip`

echo $NOW $IP >> /home/username/ipaddresses

Erstellen Sie als Nächstes eine systemd-Service-/Unit-Datei in /etc/systemd/system. Ich habe diese genannt testservice.service.

[Unit]
Description:Test service to execute at shutdown prior to losing network
Requires=network-online.target
After=network-online.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStop=/home/username/bin/testscript.sh

[Install]
WantedBy=multi-user.target

Sagen Sie systemd, dass es unsere Datei lesen soll:

sudo systemctl daemon-reload

Aktivieren Sie den Dienst:

sudo systemctl enable testservice.service

Starten Sie dann das System neu und Sie werden sehen, dass die Datei /home/username/ipaddressmit einem Zeitstempel beim Herunterfahren und Ihrer öffentlichen IP-Adresse aktualisiert wird.

verwandte Informationen