Cron-Jobs richtig planen: Zeitpläne, Logging und Fehlerbehandlung
Der klassische Cron-Fehler sieht so aus: Du testest ein Backup-Skript im Terminal, es läuft, du trägst es in die Crontab ein, und drei Wochen später stellst du fest, dass seit drei Wochen kein Backup existiert. Das Skript lief jede Nacht, brach jede Nacht ab, und niemand hat es gemerkt. Cron ist zuverlässig im Starten, aber völlig stumm im Scheitern. Dieser Beitrag zeigt dir, wie du Cron-Jobs so baust, dass du von Fehlern erfährst.
Die Syntax der Crontab und die ersten Beispiele hast du im Grundlagen-Tutorial Cron Job einrichten gesehen. Hier geht es um das, was danach kommt: Planung, Logging und Fehlerbehandlung.
Warum dein Skript im Cron anders läuft
Cron startet Jobs mit einer minimalen Umgebung. Dein PATH ist kürzer, deine Aliases fehlen, die Shell ist oft sh statt bash, und das Arbeitsverzeichnis ist dein Home, nicht das Verzeichnis des Skripts. Die häufigste Folge: Ein Befehl, der im Terminal gefunden wird, wird im Cron nicht gefunden. Die Lösung ist einfach und immer gleich: Schreib am Anfang des Skripts den vollen PATH, nutze absolute Pfade für alle Dateien und setze die Shell in der Crontab explizit mit SHELL=/bin/bash. Wer das einmal verinnerlicht hat, erspart sich die Hälfte aller Cron-Probleme.
Zeitpläne, die sich nicht in die Quere kommen
Ein Job, der länger läuft als sein Intervall, startet ein zweites Mal, bevor der erste fertig ist. Bei einem Backup bedeutet das zwei rsync-Prozesse auf denselben Dateien. Die Abhilfe ist ein Lock: flock -n /tmp/backup.lock /pfad/skript.sh startet das Skript nur, wenn kein anderes läuft. Plane außerdem Jobs, die dieselben Ressourcen brauchen, versetzt. Das Backup um 2:00, die Datenbankoptimierung um 2:00 und das Log-Rotieren um 2:00 ist ein klassischer Fehler, weil die volle Stunde für alle verlockend ist. Nimm 2:07, 2:41 und 3:13. Im Wiki von ubuntuusers.de findest du eine gute Übersicht der Sonderformen wie @daily und @reboot, die diese Planung vereinfachen, aber dasselbe Überlappungsproblem haben.
Logging: Wohin mit der Ausgabe
- Nie verwerfen: Die Umleitung nach
/dev/nullist der Grund, warum das Backup drei Wochen lang scheitern konnte. Leite in eine Logdatei um, mit Datum im Namen. - Fehler getrennt:
2>> /var/log/backup-error.logsammelt nur die Fehlermeldungen, die du täglich lesen kannst. - Logdateien rotieren, sonst füllen sie nach einem Jahr die Platte.
logrotateist dafür da und läuft selbst per Cron. - Zeitstempel im Skript: Schreib am Anfang und Ende eine Zeile mit
datein das Log. Dann siehst du, wie lange der Job braucht.
Fehlerbehandlung: Vom Scheitern erfahren
Ein Skript sollte mit einem Exit-Code ungleich null enden, wenn etwas schiefgeht, und es sollte dir das mitteilen. Setz am Anfang set -euo pipefail, damit das Skript beim ersten Fehler abbricht, statt mit kaputten Daten weiterzulaufen. Dann baue eine Benachrichtigung ein: eine E-Mail über den lokalen Mailer, eine Nachricht an einen Messenger-Bot oder eine Datei, die ein Überwachungsskript prüft. Es gibt eigene Monitoring-Werkzeuge für genau dieses Problem: Sie schlagen Alarm, wenn ein erwarteter Job sich nicht meldet. Neue Versionen solcher Werkzeuge tauchen regelmäßig in den Meldungen von LinuxNews auf, wer mitlesen will. Für einen Heimserver reicht oft ein zweiter Cron-Job, der prüft, ob die Backup-Datei von heute existiert, und sonst eine Mail schickt.
Testen, bevor es nachts läuft
Teste den Job mit derselben Umgebung, die Cron nutzt: env -i /bin/sh -c "/pfad/skript.sh" simuliert die leere Umgebung. Lass den Job einmal in fünf Minuten laufen, prüfe das Log, und stell dann erst den echten Zeitplan ein. Und schreib in die Crontab einen Kommentar über jede Zeile, was der Job tut und wer ihn angelegt hat. In einem Jahr wirst du dankbar sein.
Fazit: Cron startet, du überwachst
PATH setzen, absolute Pfade, Lock gegen Überlappung, Ausgabe ins Log, Exit-Codes und eine Benachrichtigung bei Fehlern: Mit diesen sechs Punkten wird ein Cron-Job von einem Zeitplan zu einem System, das du im Griff hast. Das Backup aus dem Anfang hätte am ersten Abend eine Mail geschickt. Und dann wären es drei Wochen Backups geworden.