
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.
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/system
mit 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.target
und 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.target
Abhä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 keineExecStart=
Aktion erstellt haben. - Erstellen Sie abschließend eine
ExecStop=
Aktion, die auf Ihr Skript verweist, beispielsweiseExecStop=/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.target
sind heruntergefahren.
Als Beispiel...
Hier ist ein einfaches Testskript, mit dem Sie curl
Ihre ö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/ipaddress
mit einem Zeitstempel beim Herunterfahren und Ihrer öffentlichen IP-Adresse aktualisiert wird.