[gelöst] Shutdown-Skript für systemd

Warum Debian und/oder eine seiner Spielarten? Was muss ich vorher wissen? Wo geht es nach der Installation weiter?
Antworten
Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

[gelöst] Shutdown-Skript für systemd

Beitrag von Ulidor » 28.05.2015 18:42:16

Hallo,

ich möchte beim Shutdown unter Jessie mit systemd ein bash-Skript ausführen, das ein Backup auf USB-Stick durchführt.

Dazu habe ich eine Konfigurationsdatei namens partbackup.service im Verzeichnis /etc/systemd/system/ mit diesem Inhalt erstellt:

Code: Alles auswählen

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

[Service]
ExecStart=/root/00/system/partback/test

[Install]
WantedBy=reboot.target halt.target poweroff.target
Das hinter ExecStart= angegebene (und auf der Kommandozeile getestete) bash-Skript enthält zum Testen erst mal nur einen echo-Befehl, dann sleep 5 und dann wird das Datum in eine Datei geschrieben.
Erwartet habe ich, dass die Ausgabe des echo-Befehls beim Herunterfahren erscheint, dann das System für 5 Sekunden anhält und anschließend die Datumsdatei geschrieben wird. Die /etc/systemd/system.conf habe ich so eingestellt, dass systemd die Statusmeldungen anzeigt. Es ist aber beim Reboot weder die echo-Ausgabe zu sehen, noch hält das System für 5 Sekunden an, noch wird die Datumsdatei geschrieben.

Was mache ich falsch? Ich habe leider von systemd keine Ahnung, wie man vermutlich sieht. Ich möchte auch nicht stundenlang englische man-pages lesen. Die Konfigurationsdatei habe ich von einer anderen kopiert und „auf gut Glück" verändert.

Gruß
Rolf
Zuletzt geändert von Ulidor am 31.05.2015 19:05:26, insgesamt 1-mal geändert.
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Shutdown-Skript für systemd

Beitrag von Ulidor » 28.05.2015 19:18:42

Ich habe den Befehl

Code: Alles auswählen

# systemctl daemon-reload
abgesetzt und auf der Kommandozeile lässt sich die Unit starten:

Code: Alles auswählen

# systemctl start partbackup.service
# systemctl status partbackup.service
● partbackup.service - Partbackup
   Loaded: loaded (/etc/systemd/system/partbackup.service; disabled)
   Active: active (running) since Do 2015-05-28 19:15:29 CEST; 3s ago
 Main PID: 1539 (test)
   CGroup: /system.slice/partbackup.service
           ├─1539 /bin/bash /root/00/system/partback/test
           └─1540 sleep 5

Mai 28 19:15:29 ulidor test[1539]: Hallo, hier ist das Testskript!!!!!!!!!!!!!!!!!!!
Trotzdem passiert beim Reboot anscheinend nichts.
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Benutzeravatar
smutbert
Beiträge: 8350
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

Re: Shutdown-Skript für systemd

Beitrag von smutbert » 28.05.2015 19:37:16

Dass die Ausgabe von dem echo-Befehl nicht auf der Konsole erscheint sondern nur im Log ist normal, solange man es nicht anders konfiguriert. Manches ist mir da auch noch nicht klar, aber vielleicht wäre es eine gute Idee die Dinge, die dein Skript zum Laufen benötigt noch mit After= in die unit hineinzuschreiben, womöglich einfach genügt bereits

Code: Alles auswählen

After=basic.target
Das hat aber bestimmt nichts damit zu tun, dass deine unit nicht so läuft wie du es willst. Dafür hätte ich eine andere Idee und zwar eine ganz normale service-unit, die eigentlich auch bereits beim Systemstart aufgerufen wird (ExecStart), die eigentliche Arbeit aber erst beim Stoppen/Herunterfahren (ExecStop) erledigt:

Code: Alles auswählen

[Unit]
Description=Partbackup
After=basic.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=/root/00/system/partback/test

[Install]
WantedBy=multi-user.target
vielleicht gibt es aber auch eine elegantere Möglichkeit…

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Re: Shutdown-Skript für systemd

Beitrag von Ulidor » 28.05.2015 20:50:18

Danke, smutbert, das bringt mich immerhin schon einen großen Schritt weiter. Zwar ist die Ausgabe von echo tatsächlich noch nicht zu sehen, aber der Shutdown-Prozess pausiert kurz und die Datumsdatei wird geschrieben.

Und ich dachte, hinter ExecStart= wird einfach nur das von der Unit zu startende Programm geschrieben. Dass es bedeutet, dass es beim Systemstart ausgeführt werden soll, und es auch ExecStop gibt, wusste ich nicht. Als Vorlage habe ich /etc/systemd/system/shutdown.target.wants/unattended-upgrades.service verwendet.

Wie muss ich das denn konfigurieren, damit die Ausgaben des Skripts auf der Konsole erscheinen? Das Skript soll u.a. anzeigen, wie viel Speicherplatz vor und nach dem Backup auf dem USB-Stick ist.
Ich hatte das Skript bisher unter Wheezy mit SystemV verwendet, aber Systemd ist so schnell, dass ich wohl noch einen sleep-Befehl einfügen muss, damit ich die Ausgabe überhaupt verfolgen könnte.
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Benutzeravatar
smutbert
Beiträge: 8350
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

Re: Shutdown-Skript für systemd

Beitrag von smutbert » 28.05.2015 21:45:22

Ulidor hat geschrieben:[…]
Und ich dachte, hinter ExecStart= wird einfach nur das von der Unit zu startende Programm geschrieben. Dass es bedeutet, dass es beim Systemstart ausgeführt werden soll, und es auch ExecStop gibt, wusste ich nicht.[…]
nicht ganz, da habe ich mich mißverständlich ausgedrückt. ExecStart wird beim Start des Services ausgeführt und ExecStop beim (oder vielleicht sogar zum :?: ) Beenden des Services, nur fällt eben meistens ersteres mit dem Systemstart und zweiteres mit dem Shutdown zusammen.
Ulidor hat geschrieben: Wie muss ich das denn konfigurieren, damit die Ausgaben des Skripts auf der Konsole erscheinen? Das Skript soll u.a. anzeigen, wie viel Speicherplatz vor und nach dem Backup auf dem USB-Stick ist.
[…]
Dazu gibt es wahrscheinlich mehrere Möglichkeiten. Einerseits könntest du in /etc/systemd/journald.conf

Code: Alles auswählen

ForwardToConsole=yes
setzen.

Oder du könntest vielleicht in dem Skript selbst die Ausgabe nach /dev/tty0 umleiten (keine Ahnung ob das eine gute Idee ist), dann landet nur die Ausgabe deines Skripts auf der Konsole (zumindest sollte das nach meinem Verständnis so sein ☺).

journalctl zum Anzeigen des Protokolls ist aber auch sehr praktisch, vielleicht freundest du dich damit an? In der Standardkonfiguration wird das Protokoll von systemd-journald dauerhaft gespeichert, sobald du das Verzeichnis /var/log/journal anlegst, was natürlich notwendig ist, wenn man nach dem nächsten Start die Ausgabe eines beim vorigen Shutdown ausgeführten Skripts kontrollieren will.
Jedenfalls solltest du dann mit

Code: Alles auswählen

# journalctl -b 1 -u partbackup
die Ausgabe deines Skriptes vom vorigen Shutdown ansehen können.

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Re: Shutdown-Skript für systemd

Beitrag von Ulidor » 29.05.2015 17:20:24

Die Ausgabe auf der Konsole wäre mir schon wichtig, damit ich eventuelle Fehlermeldungen des Skripts sofort sehen könnte.

Ich weiß noch nicht, welche Methode ich wählen werde, Ich bin hier auf dem neu installierten Jessie auf das unerwartete Problem gestoßen, dass umount oft für ca. zwei Minuten hängen bleibt und damit das Skript am Ende blockiert. Okay, das wäre jetzt auch nicht soo schlimm, wenn ich mich darauf verlassen könnte, dass der Rechner nach dieser „Bedenkzeit" auf jeden Fall herunter fährt. Das macht Jessie aber leider auch nicht immer.

Erst mal vielen Dank! Ich melde mich wieder, wenn ich daran weiter arbeite.
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Benutzeravatar
smutbert
Beiträge: 8350
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

Re: Shutdown-Skript für systemd

Beitrag von smutbert » 29.05.2015 18:04:54

Hab gerade etwas in der Manpage von systemd.exec gefunden:
[…]
StandardOutput=
Controls where file descriptor 1 (STDOUT) of the executed processes is connected to. Takes one of inherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console, kmsg+console or socket.

inherit duplicates the file descriptor of standard input for standard output.

null connects standard output to /dev/null, i.e. everything written to it will be lost.

tty connects standard output to a tty (as configured via TTYPath=, see below). If the TTY is used for output only, the executed process will not become the controlling process of the terminal, and will not fail or wait for other processes to release the terminal.

journal connects standard output with the journal which is accessible via journalctl(1). Note that everything that is written to syslog or kmsg (see below) is implicitly stored in the journal as well, the specific two options listed below are hence supersets of this one.

syslog connects standard output to the syslog(3) system syslog service, in addition to the journal. Note that the journal daemon is usually configured to forward everything it receives to syslog anyway, in which case this option is no different from journal.

kmsg connects standard output with the kernel log buffer which is accessible via dmesg(1), in addition to the journal. The journal daemon might be configured to send all logs to kmsg anyway, in which case this option is no different from journal.

journal+console, syslog+console and kmsg+console work in a similar way as the three options above but copy the output to the system console as well.

socket connects standard output to a socket acquired via socket activation. The semantics are similar to the same option of StandardInput=.

This setting defaults to the value set with DefaultStandardOutput= in systemd-system.conf(5), which defaults to journal.

StandardError=
Controls where file descriptor 2 (STDERR) of the executed processes is connected to. The available options are identical to those of StandardOutput=, with one exception: if set to inherit the file descriptor used for standard output is duplicated for standard error. This setting defaults to the value set with DefaultStandardError= in systemd-system.conf(5), which defaults to inherit.

TTYPath=
Sets the terminal device node to use if standard input, output, or error are connected to a TTY (see above). Defaults to /dev/console.
[…]
Mit

Code: Alles auswählen

…

[Service]
StandardOutput=syslog+console
StandardError=syslog+console
…

könntest solltest du also erreichen, dass die Ausgabe nur deiner systemd-unit auch auf der Konsole landet.

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Re: Shutdown-Skript für systemd

Beitrag von Ulidor » 29.05.2015 23:13:52

smutbert hat geschrieben:

Code: Alles auswählen

…

[Service]
StandardOutput=syslog+console
StandardError=syslog+console
…

Das habe ich jetzt in die Unit eingebaut und anschließend

Code: Alles auswählen

systemctl daemon-reload
ausgeführt, aber ich bekomme auf der Konsole keine Ausgabe und finde sie auch nicht bei

Code: Alles auswählen

# journalctl
...
# journalctl -b 1 -u partbackup
-- Logs begin at Fr 2015-05-29 22:56:55 CEST, end at Fr 2015-05-29 23:11:43 CEST. --
Muss ich meine Unit eigentlcih jedesmal bei laufendem System erst mit

Code: Alles auswählen

# systemctl start partbackup.service
starten? Wie machen das denn andere Units?
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Benutzeravatar
smutbert
Beiträge: 8350
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

Re: Shutdown-Skript für systemd

Beitrag von smutbert » 29.05.2015 23:19:35

Bei der Ausgabe weiß ich nicht weiter, aber damit du es nicht immer manuell starten musst, was ja nicht Sinn der Sache ist

Code: Alles auswählen

# systemctl enable partbackup

Benutzeravatar
smutbert
Beiträge: 8350
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

Re: Shutdown-Skript für systemd

Beitrag von smutbert » 29.05.2015 23:21:53

Ulidor hat geschrieben:[…]
...
# journalctl -b 1 -u partbackup
-- Logs begin at Fr 2015-05-29 22:56:55 CEST, end at Fr 2015-05-29 23:11:43 CEST. --[/code]
[…]
verflixt, da hat sich ein Fehler eingeschlichen:

Code: Alles auswählen

# journalctl --list-boots
# journalctl -b -1 -u partbackup

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Re: Shutdown-Skript für systemd

Beitrag von Ulidor » 30.05.2015 10:31:00

smutbert hat geschrieben:Bei der Ausgabe weiß ich nicht weiter, aber damit du es nicht immer manuell starten musst, was ja nicht Sinn der Sache ist

Code: Alles auswählen

# systemctl enable partbackup
Das ist ja einfach. :)

Die Ausgaben erscheinen doch in der Konsole, wobei allerdings anscheined frühe Ausgaben „verschluckt" werden. Ich habe jetzt als erste Zeile im Skript echo 10 stehen, dann wird alles angezeigt.
Kleiner Schönheitsfehler: Läuft ein einzelner Prozess des Skripts mal etwas länger (keine Ahnung, wo die Zeitgrenze liegt), dann erscheint „A stop job is running for Partbackup" und die Ausgabe des Prozesses erfolgt dahinter in derselben Zeile, während sonst jede Prozessausgabe in einer eigenen Zeile erscheint.

Ich habe jetzt mal mein Backup-Skript ausprobiert. Prinzipiell würde es laufen, aber an einer Stelle erscheint ein „Fatal Error", dass die Variable HOME nicht gefunden werden kann. Die Meldung kommt aber nicht aus der bash (die ja kein Problem mit ungesetzten Variablen hat) und es wird am Ende die Meldung meiner Funktion ausgegeben, über die das Skript regulär beendet wird, wenn also nicht die bash das Skript abgebrochen hat.

Kann es sein, dass mein Skript zu spät im Shutdown-Ablauf gestartet wird, so dass intern verwendete Variablen nicht mehr verfügbar sind? Im Skript verwende ich weder „$HOME", noch „~/".
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Re: Shutdown-Skript für systemd

Beitrag von Ulidor » 30.05.2015 10:45:20

So sieht mein Skript derzeit aus:

Code: Alles auswählen

#!/bin/bash

# Teil-Backup auf USB-Stick

stdrootuuid="bbbadfa0-229c-4bf9-a65d-70cc92dfb58a"
stickuuid="3c5151da-4473-43cb-af4d-32195a7aef15"
dirname="/mnt/partbackup"

batch="-batch"
silent="-silent"

sleep 10

echo -e "\033[0;36m$0\033[0m wird gestartet..."

getout ()
{
echo -e "\033[0;36m$0\033[0m ist beendet"
sleep 10
exit
}

[ -x /usr/bin/beep ] && dobeep="beep -l500 -r3"

# Prüfen auf Option -i (Interactive)
echo $@ | grep "i" > /dev/null
if [ "$?" = 0 ]
then
	batch=""
	silent=""
fi

# Prüfen auf Option -v (Verbose)
echo $@ | grep "v" > /dev/null
if [ "$?" = 0 ]
then
	silent=""
fi

# Ist die gemountete Root-Partition die vorgegebene?
rootuuid=$(blkid -s UUID -o value $(mount | grep ' / ' | cut -d' ' -f1))
[ $stdrootuuid != "$rootuuid" ] && getout

stickdev=$(findfs UUID=$stickuuid)
if [ "$?" != "0" ]
then
	echo -e "\n \033[0;31mFEHLER:\033[0m USB-Stick ist nicht vorhanden! \n" && eval $dobeep
	sleep 5
	getout
fi

fsck -a -C $stickdev
if [ "$?" != "0" ]
then
	echo -e "\n \033[0;31mFEHLER:\033[0m Überprüfen des USB-Sticks fehlgeschlagen! \n" && eval $dobeep
	sleep 5
	getout
fi

[ ! -d "$dirname" ] && mkdir $dirname
mount $stickdev $dirname
if [ "$?" != "0" ]
then
	echo -e "\n \033[0;31mFEHLER:\033[0m Mounten des USB-Sticks fehlgeschlagen! \n" && eval $dobeep
	sleep 5
	getout
fi

df -h $dirname
export UNISON=/root/00/system/partback/.unison
/usr/bin/time -f "\t%E real,\t%U user,\t%S sys" unison partbackup $batch $silent -logfile /root/00/system/partback/unison.log
df -h $dirname

if [ "$?" != "0" ]
then
	echo -e "\n \033[0;31mFEHLER:\033[0m Datenabgleich fehlgeschlagen! \n" && eval $dobeep
	sleep 5
else
	date > /root/00/system/partback/lastbackup
fi

umount $dirname

getout
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Benutzeravatar
smutbert
Beiträge: 8350
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

Re: Shutdown-Skript für systemd

Beitrag von smutbert » 30.05.2015 23:45:58

Ulidor hat geschrieben:[…]
Die Ausgaben erscheinen doch in der Konsole, wobei allerdings anscheined frühe Ausgaben „verschluckt" werden. Ich habe jetzt als erste Zeile im Skript echo 10 stehen, dann wird alles angezeigt.
Keine Ahnung wieso das so sein könnte…
Ulidor hat geschrieben: Kleiner Schönheitsfehler: Läuft ein einzelner Prozess des Skripts mal etwas länger (keine Ahnung, wo die Zeitgrenze liegt), dann erscheint „A stop job is running for Partbackup" und die Ausgabe des Prozesses erfolgt dahinter in derselben Zeile, während sonst jede Prozessausgabe in einer eigenen Zeile erscheint.
Das ist normal und das „Überschneiden“ der Ausgaben deines Skriptes mit denen von systemd lässt sich angesichts der Tatsache, dass hier womöglich viele Dinge parallel ausgeführt werden wohl kaum vermeiden.
Ulidor hat geschrieben: Ich habe jetzt mal mein Backup-Skript ausprobiert. Prinzipiell würde es laufen, aber an einer Stelle erscheint ein „Fatal Error", dass die Variable HOME nicht gefunden werden kann. Die Meldung kommt aber nicht aus der bash (die ja kein Problem mit ungesetzten Variablen hat) und es wird am Ende die Meldung meiner Funktion ausgegeben, über die das Skript regulär beendet wird, wenn also nicht die bash das Skript abgebrochen hat.

Kann es sein, dass mein Skript zu spät im Shutdown-Ablauf gestartet wird, so dass intern verwendete Variablen nicht mehr verfügbar sind? Im Skript verwende ich weder „$HOME", noch „~/".
Du kannst die Zeile After=… ändern deine Unit beim Hochfahren später (egal) und beim Herunterfahren früher ausgeführt wird. Außerdem kannst du falls notwendig Zeilen wie

Code: Alles auswählen

RequiresMountsFor=/mnt/meinDateisystem
zum Abschnitt [Unit] hinzufügen, um sicherzustellen, dass bestimmte Dateisysteme (noch?) gemountet sind. Dasselbe gilt für Environment=…, falls bestimmte Variablen gesetzt sein müssen.

Welcher Befehl bei deinem Skript $HOME benötigt, weiß ich nicht, außerdem hätte ich eigentlich damit gerechnet, dass es auf /root gesetzt ist, weil die Befehle in den units ja als root ausgeführt werden, fall nichts anderes angegeben ist, aber eigentlich kommt dafür fast nur unison in Frage — die ganzen sleeps und echos benötigen das wohl kaum.

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Re: Shutdown-Skript für systemd

Beitrag von Ulidor » 31.05.2015 09:53:58

smutbert hat geschrieben:Das ist normal und das „Überschneiden“ der Ausgaben deines Skriptes mit denen von systemd lässt sich angesichts der Tatsache, dass hier womöglich viele Dinge parallel ausgeführt werden wohl kaum vermeiden.
Erstaunlich finde ich, dass anscheinend alle nachfolgenden Shutdown-Prozesse auf mein Skript warten, obwohl es ja relativ lange läuft. Aber gut so, sonst würde ich meine Meldungen ja nicht verfolgen können.

Wie ich es hinbekomme, dass meine Unit an einer bestimmten Stelle beim Shutdown gestartet wird, ist mir noch unklar, weil ich das Prinzip der Abhängigkeiten noch gar nicht durchschaue.

Und wenn ich es denn soweit hätte, dass sie beim Hochfahren z.B. direkt vor der grafischen Oberfläche gestartet würde, hieße es dann zwangsläufig, dass mein Skript beim Herunterfahren gleich nach dem Beenden der grafischen Oberfläche gestartet würde? Fürs Shutdown gibt es doch eigene Targets, mit vermutlich eigenen Abhängigkeiten.

Wie auch immer, das Problem mit der fehlenden HOME-Variablen scheint noch komplizierter zu sein. Ich hatte die Unit mal so verändert, um sie in die Shutdown-Targets einzubinden:

Code: Alles auswählen

[Unit]
Description=Partbackup
DefaultDependencies=no
Before=shutdown.target

[Service]
StandardOutput=syslog+console
StandardError=syslog+console
Type=oneshot
ExecStart=/bin/true
ExecStop=/root/00/system/partback/partback

[Install]
WantedBy=reboot.target halt.target poweroff.target
und bei laufendem System gestartet. Das Skript wurde sofort ausgeführt (warum eigentlich?), es wurde aber nichts ausgegeben (auch das verstehe ich nicht). Allerdings wurden die Ausgaben protokolliert:

Code: Alles auswählen

# systemctl status partbackup.service
● partbackup.service - Partbackup
   Loaded: loaded (/etc/systemd/system/partbackup.service; enabled)
   Active: inactive (dead) since So 2015-05-31 09:13:45 CEST; 12s ago
  Process: 1596 ExecStop=/root/00/system/partback/partback (code=exited, status=0/SUCCESS)
  Process: 1594 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
 Main PID: 1594 (code=exited, status=0/SUCCESS)

Mai 31 09:13:35 ulidor partback[1596]: fsck from util-linux 2.25.2
Mai 31 09:13:35 ulidor partback[1596]: partbackup: sauber, 67291/3842048 Dateien, 5167035/15359744 Blöcke
Mai 31 09:13:35 ulidor partback[1596]: Dateisystem    Größe Benutzt Verf. Verw% Eingehängt auf
Mai 31 09:13:35 ulidor partback[1596]: /dev/sdf1        58G     19G   36G   35% /mnt/partbackup
Mai 31 09:13:35 ulidor partback[1596]: Fatal error: exception Util.Fatal("Environment variable HOME not found")
Mai 31 09:13:35 ulidor partback[1596]: Command exited with non-zero status 2
Mai 31 09:13:35 ulidor partback[1596]: 0:00.00 real,        0.00 user,        0.00 sys
Mai 31 09:13:35 ulidor partback[1596]: Dateisystem    Größe Benutzt Verf. Verw% Eingehängt auf
Mai 31 09:13:35 ulidor partback[1596]: /dev/sdf1        58G     19G   36G   35% /mnt/partbackup
Mai 31 09:13:35 ulidor partback[1596]: /root/00/system/partback/partback ist beendet
Also selbst beim voll hochgefahrenen System fehlt die HOME-Variable. Starte ich das Skript auf der Kommandozeile läuft es einwandfrei durch. Systemd scheint mit Skripten anders umzugehen als wenn sie in einer Konsole gestartet werden. Das ist natürlich grundsätzlich nicht so gut.

Ich ich weiß nicht, wie ich das Skript so verändern kann, dass es läuft. Da die Fehlermeldung zwischen den beiden df-Aufrufen erfolgt, denke ich auch, dass es was mit unison zu tun hat. Aber auch in dem verwendeten Profil benutze ich nicht $HOME:

Code: Alles auswählen

# Unison preferences file
root = /
root = /mnt/partbackup
ui = text
times = true
owner = true
group = true
force = /
path = home/rolf/00
path = home/rolf/.local/share/local-mail
#path = home/rolf/.kde/share/apps/kmail/mail
path = root/00
ignore = Path home/rolf/00/Daten/Audio/Audio
ignore = Path home/rolf/00/Daten/Bilder/DigiKam
ignore = Path home/rolf/.kde/share/apps/kmail/mail/Debian
ignore = Name root/00/system/partback/unison.log
# unison-Archivdateien in root/00/system/partback/.unison ausblenden:
ignore = Regex (.*[/])?\.unison[/][a-z][a-z][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Re: Shutdown-Skript für systemd

Beitrag von Ulidor » 31.05.2015 10:16:41

Mein Skript enthielt noch einen Fehler: Der zweite df-Aufruf darf erst nach der Abfrage, ob unison fehlerfrei war, kommen. Das habe ich geändert und noch mal das Skript über die Unit bei laufendem System ausgeführt:

Code: Alles auswählen

# systemctl status partbackup.service
● partbackup.service - Partbackup
   Loaded: loaded (/etc/systemd/system/partbackup.service; enabled)
   Active: inactive (dead) since So 2015-05-31 10:09:20 CEST; 3s ago
  Process: 1511 ExecStart=/root/00/system/partback/partback (code=exited, status=0/SUCCESS)
 Main PID: 1511 (code=exited, status=0/SUCCESS)

Mai 31 10:09:03 ulidor partback[1511]: partbackup: sauber, 67291/3842048 Dateien, 5167035/15359744 Blöcke
Mai 31 10:09:03 ulidor partback[1511]: Dateisystem    Größe Benutzt Verf. Verw% Eingehängt auf
Mai 31 10:09:03 ulidor partback[1511]: /dev/sdf1        58G     19G   36G   35% /mnt/partbackup
Mai 31 10:09:03 ulidor partback[1511]: Fatal error: exception Util.Fatal("Environment variable HOME not found")
Mai 31 10:09:03 ulidor partback[1511]: Command exited with non-zero status 2
Mai 31 10:09:03 ulidor partback[1511]: 0:00.00 real,        0.00 user,        0.00 sys
Mai 31 10:09:03 ulidor partback[1511]: FEHLER: Datenabgleich fehlgeschlagen!
Mai 31 10:09:10 ulidor partback[1511]: Dateisystem    Größe Benutzt Verf. Verw% Eingehängt auf
Mai 31 10:09:10 ulidor partback[1511]: /dev/sdf1        58G     19G   36G   35% /mnt/partbackup
Mai 31 10:09:10 ulidor partback[1511]: /root/00/system/partback/partback ist beendet
Jetzt kommt vom Skript die Meldung „FEHLER: Datenabgleich fehlgeschlagen!". Also ist es unison, das abbricht.
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: Shutdown-Skript für systemd

Beitrag von rendegast » 31.05.2015 11:23:48

Du könntest ja mal

Code: Alles auswählen

...

df -h $dirname
#export UNISON=/root/00/system/partback/.unison
set > /root/$(date "+%F%T").set
#/usr/bin/time -f "\t%E real,\t%U user,\t%S sys" unison partbackup .........
df -h $dirname

....
um das Environment eines systemd-Skripts zu bekommen.
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Re: Shutdown-Skript für systemd

Beitrag von Ulidor » 31.05.2015 18:12:50

Okay, das Skript habe ich so abgeändert und dann einmal über die Konsole gestartet und einmal bei hochgefahrenem System über die Unit. Die Unterschiede sind gewaltig (< = Konsole, > = Unit):

Code: Alles auswählen

# diff bash_2015-05-3117\:42\:05.set unit_2015-05-3117\:38\:11.set 
8c8
< BASH_SOURCE=([0]="00/system/partback/partback")
---
> BASH_SOURCE=([0]="/root/00/system/partback/partback")
11,12d10
< COLORFGBG='0;15'
< DESKTOP_SESSION=default
14,15d11
< DISPLAY=:0
< DM_CONTROL=/var/run/xdmctl
17d12
< GPG_AGENT_INFO=/tmp/gpg-PZFrdA/S.gpg-agent:1058:1
19,23d13
< GS_LIB=/home/rolf/.fonts
< GTK2_RC_FILES=/etc/gtk-2.0/gtkrc:/home/rolf/.gtkrc-2.0:/home/rolf/.kde/share/config/gtkrc-2.0
< GTK_RC_FILES=/etc/gtk/gtkrc:/home/rolf/.gtkrc:/home/rolf/.kde/share/config/gtkrc
< HISTCONTROL=ignorespace:ignoredups
< HOME=/root
27,34d16
< KDESU_USER=rolf
< KDE_MULTIHEAD=false
< KDE_SESSION_UID=1000
< KDE_SESSION_VERSION=4
< KONSOLE_DBUS_SERVICE=:1.10
< KONSOLE_DBUS_SESSION=/Sessions/1
< KONSOLE_DBUS_WINDOW=/Windows/1
< KONSOLE_PROFILE_NAME=
36,37d17
< LANGUAGE=
< LOGNAME=root
39d18
< MAIL=/var/mail/root
43c22
< PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/root/00/script
---
> PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
45,46c24
< PPID=1645
< PROFILEHOME=/root
---
> PPID=1
48,49c26
< PWD=/root
< QT_PLUGIN_PATH=/home/rolf/.kde/lib/kde4/plugins/:/usr/lib/kde4/plugins/
---
> PWD=/
52,56c29,30
< SHELL_SESSION_ID=8b9cca77c49e4000a7317ade2339d96f
< SHLVL=4
< SSH_AGENT_PID=1057
< SSH_AUTH_SOCK=/tmp/ssh-DdxX3eUHnwTM/agent.1020
< TERM=xterm
---
> SHLVL=1
> TERM=dumb
59,70d32
< USER=root
< WINDOWID=117440534
< WINDOWPATH=7
< XAUTHORITY=/tmp/kde-root/xauth-0-_0
< XCURSOR_THEME=Oxygen_White
< XDG_CURRENT_DESKTOP=KDE
< XDG_DATA_DIRS=/usr/share:/usr/share:/usr/local/share
< XDG_RUNTIME_DIR=/run/user/1000
< XDG_SEAT=seat0
< XDG_SESSION_ID=1
< XDG_VTNR=7
< XDM_MANAGED=method=classic,auto
Die Variable HOME gibt es jedenfalls beim Aufruf über die Unit nicht.
Aber warum stellt systemd der bash eine andere, stark reduzierte Umgebung zur Verfügung?

Ich habe den Aufruf in der Unit mal geändert in

Code: Alles auswählen

...
ExecStart=/bin/bash /root/00/system/partback/partback
...
aber das führt zum selben Ergebnis.
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Re: Shutdown-Skript für systemd

Beitrag von Ulidor » 31.05.2015 18:27:20

So läuft das Skript nun auch über die Unit (zumindest bei hochgefahrenem System):

Code: Alles auswählen

...
df -h $dirname
export UNISON=/root/00/system/partback/.unison
export HOME=/root
#set > /root/$(date "+%F%T").set
/usr/bin/time -f "\t%E real,\t%U user,\t%S sys" unison partbackup $batch $silent -logfile /root/00/system/partback/unison.log
...
Ich habe also nur die Variable HOME gesetzt, bevor unison läuft. Ich hatte schon befürchtet, dass es dann wieder abbricht, weil ihm eine weitere Variable fehlt, aber zum Glück nicht.

Mal sehen, ob ich es jetzt so hinbekomme, dass das Skript bei jedem Shutdown einwandfrei läuft.
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Beitrag von Ulidor » 31.05.2015 19:04:27

Nach mehreren Neustarts und Power-Off kann ich nun sagen, es läuft einwandfrei. :D

Ich bin froh, dass nun auch unter Jessie mit systemd bei jedem Herunterfahren ein Backup meiner wichtigsten Daten gemacht wird.

Vielen Dank, rendegast, und vielen herzlichen Dank, smutbert! :hail:
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Benutzeravatar
smutbert
Beiträge: 8350
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

Re: Shutdown-Skript für systemd

Beitrag von smutbert » 31.05.2015 19:07:13

Gerne, ein paar Kleinigkeiten noch einmal:
Ulidor hat geschrieben:[…]
Wie auch immer, das Problem mit der fehlenden HOME-Variablen scheint noch komplizierter zu sein. Ich hatte die Unit mal so verändert, um sie in die Shutdown-Targets einzubinden[…]
Alternativ könntest du auch im Abschnitt [Service] eine Zeile

Code: Alles auswählen

Environment="UNISON=/root/00/system/partback/.unison", "HOME=/root"
hinzufügen.
Ulidor hat geschrieben: Erstaunlich finde ich, dass anscheinend alle nachfolgenden Shutdown-Prozesse auf mein Skript warten, obwohl es ja relativ lange läuft. Aber gut so, sonst würde ich meine Meldungen ja nicht verfolgen können.
Das passiert wegen der Zeile After=basic.target so. Das bedeutet beim Hochfahren (in dem Fall egal, aber ich schreibe es der Vollständigkeit halber) wird deine unit erst gestartet nachdem basic.target bereits „läuft“ und beim Herunterfahren bereits beendet (dh dein Skript gestartet) solange basic.target noch läuft.
Alle Dienste und sonstigen units, die Teil von basic.target sind müssen beim Herunterfahren also auf dein Skript warten, welche das sind zeigt dir die Zeile After=… (Requires=… und Wants=… spielen vielleicht auch noch mithinein, obwohl sie laut manpage keinen Einfluss auf die Reihenfolge haben) der Ausgabe von

Code: Alles auswählen

$ systemctl show basic.target
Ulidor hat geschrieben: Wie ich es hinbekomme, dass meine Unit an einer bestimmten Stelle beim Shutdown gestartet wird, ist mir noch unklar, weil ich das Prinzip der Abhängigkeiten noch gar nicht durchschaue.

Und wenn ich es denn soweit hätte, dass sie beim Hochfahren z.B. direkt vor der grafischen Oberfläche gestartet würde, hieße es dann zwangsläufig, dass mein Skript beim Herunterfahren gleich nach dem Beenden der grafischen Oberfläche gestartet würde? Fürs Shutdown gibt es doch eigene Targets, mit vermutlich eigenen Abhängigkeiten.
So wie es jetzt ist passt das schon ganz gut glaube ich. Immerhin wird dein Skript beim Herunterfahren sehr früh gestartet ohne dass das Beenden der grafischen Oberfläche auf dein Skript warten müsste, was uU den Nachteil hätte, das du die Meldungen erst wieder nicht zu Gesicht bekämst.

Du kannst der Zeile After=… auch weitere units/Dienste hinzufügen, um das Skript beim Herunterfahren noch früher zu starten und du darfst nicht vergessen, dass die Reihenfolge gedanklich umdrehen musst:
Das "After=" bezieht sich auf das Hochfahren, beim Herunterfahren ist die Reihenfolge anders herum, je früher du es beim Herunterfahren also ausführen willst umso mehr Dienste oder um so umfangreichere targets könntest du in "After=" hineinschreiben. "Before=" hat beim Herunterfahen den gegenteiligen Effekt, es bedeutet, dass der Dienst beim Start früher gestartet wird und beim Herunterfahren später als die angegebenen units beendet wird.

(und auch nicht vergessen, das dein Skript das "Beenden" deiner service-unit darstellt und nicht etwas das starten!)

Benutzeravatar
Ulidor
Beiträge: 557
Registriert: 19.12.2004 21:54:40
Wohnort: Bielefeld

Re: Shutdown-Skript für systemd

Beitrag von Ulidor » 31.05.2015 19:37:35

smutbert hat geschrieben:Alternativ könntest du auch im Abschnitt [Service] eine Zeile

Code: Alles auswählen

Environment="UNISON=/root/00/system/partback/.unison", "HOME=/root"
hinzufügen.
Der Zeile mit HOME habe ich einen entsprechenden Kommentar hinzugefügt, aber die ist wohl in der Unit wirklich besser aufgehoben. Da hast du recht, danke für den Hinweis. Die Variable UNISON wird auch beim Aufruf über die Konsole gebraucht, deshalb lasse ich die lieber im Skript.
smutbert hat geschrieben:Das passiert wegen der Zeile After=basic.target so. Das bedeutet beim Hochfahren (in dem Fall egal, aber ich schreibe es der Vollständigkeit halber) wird deine unit erst gestartet nachdem basic.target bereits „läuft“ und beim Herunterfahren bereits beendet (dh dein Skript gestartet) solange basic.target noch läuft.
Alle Dienste und sonstigen units, die Teil von basic.target sind müssen beim Herunterfahren also auf dein Skript warten, welche das sind zeigt dir die Zeile After=… (Requires=… und Wants=… spielen vielleicht auch noch mithinein, obwohl sie laut manpage keinen Einfluss auf die Reihenfolge haben) der Ausgabe von

Code: Alles auswählen

$ systemctl show basic.target
Ah ja, so was habe ich gesucht, um durch den Wust von Abhängigkeiten besser durchzufinden. :)
smutbert hat geschrieben:So wie es jetzt ist passt das schon ganz gut glaube ich. Immerhin wird dein Skript beim Herunterfahren sehr früh gestartet ohne dass das Beenden der grafischen Oberfläche auf dein Skript warten müsste, was uU den Nachteil hätte, das du die Meldungen erst wieder nicht zu Gesicht bekämst.

Du kannst der Zeile After=… auch weitere units/Dienste hinzufügen, um das Skript beim Herunterfahren noch früher zu starten und du darfst nicht vergessen, dass die Reihenfolge gedanklich umdrehen musst:
Das "After=" bezieht sich auf das Hochfahren, beim Herunterfahren ist die Reihenfolge anders herum, je früher du es beim Herunterfahren also ausführen willst umso mehr Dienste oder um so umfangreichere targets könntest du in "After=" hineinschreiben. "Before=" hat beim Herunterfahen den gegenteiligen Effekt, es bedeutet, dass der Dienst beim Start früher gestartet wird und beim Herunterfahren später als die angegebenen units beendet wird.

(und auch nicht vergessen, das dein Skript das "Beenden" deiner service-unit darstellt und nicht etwas das starten!)
Ja, okay, eigentlich wird meine Service-Unit „missbräuchlich" verwendet, denn sie dient ja eigentlich zum Starten, Neustarten und Beenden von deamons. Deshalb muss ja wohl auch der Start des „unsinnigen" /bin/true sein.
Das war mir anfangs nicht so klar, deshalb wollte ich die Unit in die Shutdown-Targets einbinden, weil das Skript ja beim Shutdown gestartet werden soll.
Ich denke auch, ich lasse es jetzt erst mal so, denn es läuft ja ganz gut.

Also auch noch vielen Dank für den Crash-Kurs in systemd! :D
Was erhält man, wenn man einen Windows-PC abschaltet? – Ausgemachten Blödsinn.

Antworten