Aufräumarbeiten nach Scriptabbrüchen
Es kommt leider immer mal wieder vor, dass ein automatisierter Prozess auf ein Problem stößt und daher seine Verarbeitung abbricht. Das ist meistens kein Problem, man schaut nach woran es gelegen hat, behebt das Problem und führt den Prozess erneut aus. In manchen Fällen nimmt ein Script aber bestimmte Vorarbeiten vor, die ein erneutes Ausführen behindern, z.B. könnte ein Script Snapshots erzeugen und Mounten. Versucht man dies ein zweites Mal, wird dies zu Fehlermeldungen führen. Nutzt ein Script dann z.B. set -e
1 um bei Fehlern die weitere Ausführung abzubrechen, haben wir ein Problem und müssen die abschließenden Arbeiten des Scripts einmal manuell ausführen. Das kann realtiv komplex werden, vor allem weil man solche - eigentlich automatisierten - Vorgänge ja meist nicht mehr so wirklich auf dem Schirm hat.
Besser wäre es also, wenn unser Script bei einem Fehler oder manuellem Abbruch diese Aufgaben selbst erledigt. Hierzu dient der Befehl trap
2. Trap kann die Signale3 überwachen, die zu einem Scriptabbruch führen. Bevor das Script dann wirklich beendet wird, kann trap dann eine frei definierbare Funktion aufrufen:
do_cleanup () {
echo "ERROR, exiting..."
echo "Unmounting and removing snapshots"
/bin/umount /mnt/backup/data
/bin/umount /mnt/backup/root
/sbin/lvremove /dev/vg0/root-snapshot -f
/sbin/lvremove /dev/vg1/data-snapshot -f
echo ""
echo "Logfile:"
cat /tmp/backup.log
rm /tmp/backup.log
exit 2
}
trap 'echo "ERROR: Backup interrupted"; do_cleanup error; exit 2' INT TERM # Gracefully quit on (any) error
trap 'echo "received signal to stop"; do_cleanup interrupted; exit 1' SIGQUIT SIGTERM SIGINT # Gracefully quit on break
In dem Beispiel oben wird beim Abbruch des Scripts die Funktion do_cleanup()
ausgeführt. Es räumt ggf. erzeugte Snapshots auf und gibt ein Logfile auf stdout
4 aus, da das Script bei mir von einem Cronjob ausgeführt wird, würde dieser Output per Mail an mich geschickt und ich weiß, was schiefgelaufen ist.
Wie zu sehen ist, kann trap
auf verschiedene Ereignisse reagieren, ggf. auch unterschiedlich.
Etwas vorsichtig muss man mit trap 'echo "ERROR: Backup interrupted"; do_cleanup error; exit 2' INT TERM # Gracefully quit on (any) error
sein. Hier würde trap auf wirklich jeden Fehler im Scriptablauf mit einem Abbruch reagieren (also quasi so funktioniert wie set -e
. Praktisch aber aber definitiv die Nutzung von SIGQUIT
, SIGTERM
und SIGINT
, da man so das Script dann jederzeit mit Strg + C
abbrechen kann, ohne danach händisch aufräumen zu müssen. Gerade wenn man am Script noch arbeitet ist das wirklich Gold wert.