Wie du einen Cron-Ausdruck liest
Ein Cron-Ausdruck besteht aus fünf durch Leerzeichen getrennten Werten, die von links nach rechts als Minute, Stunde, Monatstag, Monat und Wochentag gelesen werden. Der Job läuft, wenn die aktuelle Zeit auf jedes Feld passt.
30 4 * * 1
│ │ │ │ │
│ │ │ │ └── day of week (1 = Monday)
│ │ │ └──── month (any)
│ │ └────── day of month (any)
│ └──────── hour (4am)
└─────────── minute (30)
Der da liest sich als „um 04:30 an jedem Montag“.
Die fünf Felder
| # | Feld | Erlaubte Werte | Anmerkungen |
|---|---|---|---|
| 1 | Minute | 0 bis 59 | |
| 2 | Stunde | 0 bis 23 | 24-Stunden-Zählung, 0 ist Mitternacht |
| 3 | Monatstag | 1 bis 31 | |
| 4 | Monat | 1 bis 12 oder JAN bis DEC | |
| 5 | Wochentag | 0 bis 6 oder SUN bis SAT | 0 ist Sonntag, und die meisten Cron-Implementierungen akzeptieren auch 7 |
Manche Scheduler nutzen eine andere Form. Quartz, das viel Java-Software verwendet, stellt die Sekunden voran, ergänzt ein optionales Jahr und nummeriert seine Wochentage von 1 bis 7 beginnend mit Sonntag. Wenn ein Ausdruck sechs oder sieben Felder hat, prüfe, für welches System er geschrieben wurde, bevor du deiner Lesart traust.
Die Operatoren
Es gibt vier, und sie lassen sich innerhalb eines einzelnen Feldes kombinieren.
| Symbol | Name | Beispiel | Bedeutung |
|---|---|---|---|
* | Beliebig | * * * * * | Jede Minute jedes Tages |
, | Liste | 0 9,13,17 * * * | Um 09:00, 13:00 und 17:00 |
- | Bereich | 0 9-17 * * * | Stündlich von 09:00 bis einschließlich 17:00 |
/ | Schritt | */15 * * * * | Um :00, :15, :30 und :45 |
Ein Schritt wird immer auf einen Bereich angewendet. */15 im Minutenfeld bedeutet „beginne bei 0 und nimm jeden 15. Wert bis 59“. Du kannst auch einen ausdrücklich genannten Bereich in Schritten durchlaufen: 5-30/10 ergibt 5, 15 und 25 und hört dann auf, weil 35 hinter dem Ende liegt.
Schritte bedeuten nicht „alle 15 Minuten ab jetzt“; sie wählen feste Werte von der Uhr ab. */40 löst bei :00 und :40 aus und wartet dann nur 20 Minuten bis zur :00 der nächsten Stunde, weil die Zählung in jeder Stunde neu beginnt. Listen können Bereiche und Schritte enthalten, 0 0-6/2,12,18-23 * * * ist also ein gültiges Stundenfeld.
Namen und Kurzformen
Die Felder für Monat und Wochentag akzeptieren dreibuchstabige Namen, und die Schreibweise spielt keine Rolle, JAN, jan und Jan sind also dasselbe. Die klassische crontab-Dokumentation sagt, dass Bereiche und Listen von Namen nicht erlaubt sind, viele moderne Implementierungen akzeptieren MON-FRI aber sehr wohl. Wenn du nicht sicher weißt, was deinen Job ausführt, nimm Zahlen: 1-5 ist überall eindeutig.
Mehrere Kurzformen ersetzen den gesamten Ausdruck aus fünf Feldern:
| Kurzform | Entspricht | Läuft |
|---|---|---|
@yearly oder @annually | 0 0 1 1 * | Mitternacht am 1. Januar |
@monthly | 0 0 1 * * | Mitternacht am 1. des Monats |
@weekly | 0 0 * * 0 | Mitternacht am Sonntag |
@daily oder @midnight | 0 0 * * * | Täglich um Mitternacht |
@hourly | 0 * * * * | Zur vollen Stunde |
@reboot gibt es ebenfalls, aber das ist kein Zeitplan: Es führt den Job einmal aus, wenn cron selbst startet.
Die Falle mit Monatstag und Wochentag
Das ist die Stelle, an der es wehtut. Wenn sowohl das Feld für den Monatstag als auch das für den Wochentag eingeschränkt ist, also keines von beiden * lautet, führt cron den Job aus, wenn eines von beiden passt, und nicht, wenn beide passen.
0 0 13 * 5
Du liest das vielleicht als „Mitternacht an Freitag, dem 13.“. Tatsächlich bedeutet es „Mitternacht am 13. jedes Monats und außerdem Mitternacht an jedem Freitag“: über sechzig Läufe im Jahr statt einem oder zweien.
Das UND-Verhalten, das du erwartet hast, gilt nur, wenn eines der beiden Felder * ist. 0 0 * * 5 ist also jeder Freitag und 0 0 13 * * jeder 13., beides völlig normal. Erst beide einzuschränken löst das ODER aus.
Es gibt keinen Standardweg, „Freitag, der 13.“ in fünf Feldern auszudrücken. Der übliche Ausweg ist, jeden 13. einzuplanen und den Job den Wochentag prüfen zu lassen, bevor er irgendetwas tut.
Eine verwandte Feinheit: Manche Implementierungen entscheiden anhand der Frage, ob ein Feld wörtlich mit * beginnt, ob es eingeschränkt ist. Dort gilt 0-6 im Wochentagsfeld als eingeschränkt, obwohl es jeden Tag abdeckt, und schaltet klammheimlich das ODER-Verhalten ein. Nimm *, wenn du „beliebig“ meinst.
Fehler, auf die es sich zu prüfen lohnt
* */2 * * *läuft jede Minute in jeder zweiten Stunde: 720 Läufe am Tag. Gemeint war0 */2 * * *, und das sind 12.- Ein fehlendes Minutenfeld schiebt alles um eins nach links und lässt sich meist trotzdem parsen, was dir einen gültigen Zeitplan zur völlig falschen Zeit beschert.
0 0 31 * *überspringt stillschweigend die Monate ohne 31.- Cron nutzt die Zeitzone des Systems oder des Benutzers, sofern der Scheduler dich keine setzen lässt. Wenn die Uhren wegen der Sommerzeit umgestellt werden, läuft ein Job in der übersprungenen Stunde je nach Implementierung womöglich gar nicht, und einer in der wiederholten Stunde womöglich zweimal. Jobs, die einmal am Tag laufen müssen, planst du am sichersten außerhalb der frühen Morgenstunden, in die die Umstellung fällt.
Im Zweifel liest du den Ausdruck als Satz zurück und prüfst dann die nächsten paar Zeitpunkte, zu denen er tatsächlich auslösen würde. Wenn diese Daten nicht das sind, was du beschrieben hast, ist der Ausdruck falsch und nicht deine Lesart.