Wie benutzt du dieses Tool?
- Auf dem Server crontab -l ausführen und die komplette Ausgabe kopieren, samt Kommentaren, Leerzeilen und Zuweisungen wie CRON_TZ oder MAILTO.
- Oben auswählen, ob es eine persönliche crontab ist oder eine Datei aus /etc/crontab mit Benutzer-Spalte, und die Zeitzone setzen, in der du denkst.
- Alles in das große Feld einfügen. Die Auswertung erscheint sofort, Zeile für Zeile, mit Klartext-Erklärung und nächstem Lauf.
- Den Kollisions-Block lesen. Steht dort ein Zeitpunkt mit mehreren Jobs, auf Vorschlag berechnen klicken und die entzerrte Datei kopieren.
- Zum Weitergeben unten den Bericht als Markdown holen oder als JSON, wenn ein Skript oder ein Assistent damit weiterarbeiten soll.
Was macht der Crontab-Prüfer?
Er nimmt das, was cron auf deinem Server wirklich liest: die
ganze Datei. Kommentarzeilen, Leerzeilen, Zuweisungen wie CRON_TZ=, PATH= und MAILTO=, den
Zeitplan und den Befehl dahinter. Nichts davon musst du vorher herausschneiden. Aus jeder Zeile wird
eine Zeile im Ergebnis: der Ausdruck im Klartext, der nächste Lauf in der Zone, die für genau diese
Zeile gilt, und die Hinweise, die dazu gehören.
Der Prüfer läuft vollständig in deinem Browser. Kein Upload, kein Server, keine Cookie-Wand. Das ist bei einer crontab kein Nebenaspekt, denn dort stehen Hostnamen, Skriptpfade, Datenbanknamen und gelegentlich ein Passwort, das jemand in eine Kommandozeile geschrieben hat, weil es schnell gehen musste.
Warum reicht ein Prüfer für einzelne Ausdrücke nicht?
Weil die interessanten Fehler zwischen den Zeilen liegen. Ein einzelner Ausdruck lässt sich in
Sekunden nachschlagen, und dafür gibt es gute Werkzeuge. Nur beantwortet keines davon die Fragen, die
man vor einer geerbten crontab wirklich hat: Läuft hier zweimal dasselbe? Kollidiert das Backup mit
dem Export? Gilt das CRON_TZ vom Anfang der Datei überhaupt noch für die Zeile ganz unten? Und
warum kommt seit dem Serverumzug keine Mail mehr?
Das sind Eigenschaften der Datei, nicht des Ausdrucks. Wer eine crontab Zeile für Zeile in ein Einzelfeld kopiert, sieht jede Zeile isoliert und genau deshalb keine dieser Fragen. Der Prüfer dreht die Reihenfolge um: erst die Datei, dann die Zeile.
Was passiert, wenn mehrere Jobs zur selben Minute starten?
Sie teilen sich alles. Prozessor, Festplatte, Netzwerk und meistens dieselbe Datenbank. Der klassische Fall sieht so aus:
0 0 * * * /usr/local/bin/backup-db.sh
0 0 * * * /usr/local/bin/backup-files.sh
@daily /usr/local/bin/rotate-logs.sh
0 0 * * 1 /usr/local/bin/weekly-report.sh
0 0 * * * /opt/app/bin/reindex.sh
Fünf Zeilen, vier davon täglich, eine wöchentlich. Montags um Mitternacht starten alle fünf innerhalb
derselben Minute. Auf dem Papier ist das ein Zeitplan, in der Praxis ein Lastberg. Und weil @daily
in nichts anderes als 0 0 * * * übersetzt wird, sieht man die Kollision beim Überfliegen nicht
einmal.
Der Prüfer rechnet für jeden Job die kommenden Ausführungen aus und legt sie nebeneinander. Trifft
mehr als ein Job denselben Zeitpunkt, wird das gemeldet, mit dem konkreten Datum, den beteiligten
Zeilennummern und dem Ausreißer, an dem am meisten gleichzeitig losläuft. Weil verglichen wird, wann
etwas läuft, und nicht, wie es geschrieben ist, fallen auch @daily gegen 0 0 * * * und der
Wochenjob gegen die Tagesjobs auf.
Wie entzerrt das Tool die Startzeiten?
Auf Knopfdruck und ohne den Rest der Datei anzufassen. Der erste Job jeder Kollision behält seine Minute, die übrigen rücken gleichmäßig über die Stunde. Aus den fünf Zeilen oben wird zum Beispiel Minute 0, 15, 35, 12 und 5, jeweils weiterhin um Mitternacht, weiterhin am selben Tag, mit demselben Befehl. Stunde, Tag und Monat bleiben unverändert.
Danach prüft der Vorschlag sich selbst: Die entzerrte Datei wird noch einmal komplett durchgerechnet. Bleibt ein Zeitpunkt übrig, an dem zwei Jobs zusammenliegen, wird weiter verschoben, bis nichts mehr kollidiert. Erst dann steht dort, dass es aufgeht. Zeilen, deren Minutenfeld eine Liste oder eine Schrittweite ist, werden nicht automatisch verschoben, weil ein Verschieben dort die Bedeutung verändern würde. Sie werden stattdessen namentlich zur Prüfung von Hand ausgewiesen.
Das Ergebnis ist die komplette Datei zum Kopieren, mit allen Kommentaren und Zuweisungen an
derselben Stelle wie vorher. Sie geht direkt zurück in crontab -e.
Welche Zeitzone gilt für einen Cronjob?
Die des Systems, solange nichts anderes dasteht. Nicht UTC, nicht die des Browsers und nicht die des Menschen, der die Zeile geschrieben hat. Wer das verwechselt, hat einen Job, der um sechs Uhr laufen soll und faktisch um Mitternacht läuft, ohne dass irgendein Logeintrag darauf hindeutet.
Eine Zeile CRON_TZ=Europe/Berlin ändert das, aber nur für die Zeilen darunter. Steht sie in der
Mitte der Datei, laufen die oberen Jobs weiter in der Systemzone. Der Prüfer setzt das genauso um: Er
merkt sich beim Durchgehen die jeweils zuletzt gesehene Zone und rechnet jede Zeile darin. Zeilen mit
abweichender Zone bekommen die Zone sichtbar dazugeschrieben, und die Übersicht zählt, wie viele
verschiedene Zonen in einer Datei stecken. Zwei sind fast immer ein Versehen.
Dazu kommt die Sommerzeit. Springt die Uhr vorwärts, fällt ein Job in der übersprungenen Stunde ersatzlos aus. Springt sie zurück, läuft er zweimal. Beides ist dokumentiertes Verhalten und kein Fehler, nur weiß es kaum jemand vor dem ersten doppelten Rechnungslauf.
Warum findet cron mein Skript nicht?
Weil cron in einer anderen Welt startet als deine Anmeldesitzung. Kein .bashrc, kein .profile,
keine Umgebungsvariablen aus dem Deployment und ein PATH, der laut crontab(5)
in der Regel nur aus /usr/bin und /bin besteht. Alles, was ein Versionsmanager, ein Paketmanager
oder ein eigenes Build nach /usr/local/bin oder ins Heimatverzeichnis gelegt hat, ist damit nicht
erreichbar.
Der Prüfer markiert jeden Befehl, der ohne Pfad geschrieben ist und nicht zur Grundausstattung
gehört. tar und find bekommen keinen Hinweis, ein selbstgeschriebenes cleanup schon. Steht
oben in der Datei ein PATH=, schweigt der Hinweis, weil die Voraussetzung dann erfüllt ist.
Ein zweiter Klassiker steckt im Befehl selbst: das Prozentzeichen. In einer crontab ist % kein
gewöhnliches Zeichen. cron schneidet die Zeile dort ab und schiebt den Rest dem Job auf die
Standardeingabe. Aus tar -czf backup-%Y.tgz wird tar -czf backup- und eine Datei, die niemand
sucht. Ein Backslash davor löst es. Der Prüfer findet die Stelle und zählt dabei die Backslashes
richtig, sodass ein bereits maskiertes Prozentzeichen keinen Fehlalarm auslöst.
Wohin geht die Ausgabe eines Cronjobs?
An den Mailversand, wenn du nichts anderes sagst. Erzeugt ein Job Ausgabe und ist sie nicht
umgeleitet, schickt cron sie an den Besitzer der crontab oder an die Adresse aus MAILTO. Auf
Servern ohne funktionierenden Mailversand landet sie damit im Nichts, ohne dass jemand es merkt.
Der Prüfer unterscheidet drei Zustände, weil sie sehr verschiedene Folgen haben. Kein Redirect und
kein MAILTO: jeder Lauf verschickt eine Mail. MAILTO="" gesetzt: die Ausgabe wird weggeworfen,
Fehlermeldungen eingeschlossen. Umgeleitet nach > /dev/null 2>&1: alles still, aber bewusst. Ein
2>/dev/null allein zählt dabei nicht als Umleitung, denn es bringt nur die Fehler zum Schweigen und
lässt die eigentliche Ausgabe weiterlaufen. Genau andersherum, als es gemeint war.
Was ist der Unterschied zwischen crontab -l und /etc/crontab?
Die Benutzer-Spalte. Eine persönliche crontab hat fünf Zeitfelder und danach direkt den Befehl. Die
systemweiten Dateien /etc/crontab und alles unter /etc/cron.d schieben zwischen Zeitplan und
Befehl eine Spalte mit dem Benutzernamen ein, unter dem der Job laufen soll.
Wer eine Zeile aus der einen Datei in die andere kopiert, produziert einen Fehler, der lautlos
bleibt. In einer persönlichen crontab wird aus root schlicht der Befehl, und cron versucht ein
Programm namens root zu starten. Deshalb wählst du oben die Art der Datei. Im persönlichen Modus
weist der Prüfer eine Zeile aus, die verdächtig nach einer Benutzer-Spalte aussieht.
Was prüft das Tool nicht?
Es sieht deinen Server nicht. Ob ein Skript existiert, ob es ausführbar ist, ob der Benutzer die Rechte hat und ob der Dienst überhaupt läuft, kann von hier aus niemand beantworten. Der Prüfer arbeitet mit dem Text, den du einfügst, und mit nichts sonst.
Er überwacht auch keine Ausführungen. Wenn du wissen willst, ob ein Job heute Nacht wirklich gelaufen ist, brauchst du eine Überwachung auf dem Server, kein Werkzeug im Browser. Und er verhindert nicht, dass ein Lauf den nächsten überholt: Dagegen hilft eine Sperrdatei im Skript, hier bekommst du nur den Hinweis, dass ein Job so häufig startet, dass es passieren kann.
Für einzelne Ausdrücke, für Quartz, für AWS EventBridge und für den Export nach GitHub Actions oder als Kubernetes-CronJob gibt es das Schwesterwerkzeug, den Cron-Expression-Builder. Wer eine Datei prüfen will, ist hier richtig. Wer eine Zeile bauen will, dort.
Zuletzt aktualisiert: