Cron-Ausdrucks-Syntax erklärt
Cron-Ausdrücke gehören zu den Themen, die Entwickler einmal lernen, deren Details sie wieder vergessen und die sie dann alle sechs Monate erneut nachschlagen. Eine fünfstellige Zeichenkette wie 30 9 * * 1-5 kann einen überraschend spezifischen Zeitplan kodieren — "jeden Werktag um 9:30 Uhr" — aber die Syntax hat gerade genug Sonderfälle, um echte Verwirrung zu erzeugen: 0-basierte vs. 1-basierte Felder, Sonntag als sowohl 0 als auch 7, der Unterschied zwischen dem Unix-Standard und der sechsstelligen Erweiterung von Quartz sowie das subtile Verhalten von Schrittewerten in Kombination mit Bereichen.
Dieser Leitfaden behandelt die Cron-Syntax von Grund auf und arbeitet sich dann durch jedes Sonderzeichen mit konkreten Beispielen durch. Ob Sie einen Cron-Job für einen Linux-Daemon schreiben, einen GitHub-Actions-Zeitplan konfigurieren oder eine AWS-EventBridge-Regel einrichten — die gleichen zugrunde liegenden Konzepte gelten, mit einigen wichtigen plattformspezifischen Unterschieden, die ebenfalls erklärt werden.
Die fünf Standardfelder
Ein Standard-Cron-Ausdruck hat fünf durch Leerzeichen getrennte Felder, von links nach rechts gelesen: Minute, Stunde, Tag des Monats, Monat und Wochentag. Jedes Feld schränkt ein, wann der Job entlang dieser Dimension ausgeführt wird. Ein Job wird nur ausgeführt, wenn alle fünf Felder gleichzeitig übereinstimmen.
# Feld Position Bereich Sonderzeichen
# ─────────────────────────────────────────────────────
# Minute 1 0-59 * / , -
# Stunde 2 0-23 * / , -
# Tag des Monats 3 1-31 * / , - ? L W
# Monat 4 1-12 oder JAN-DEC * / , -
# Wochentag 5 0-7 (0=7=So) oder SUN-SAT * / , - ? L #
Lesen eines Ausdrucks wie 30 9 * * 1-5: Minute 30, Stunde 9, beliebiger Tag des Monats, beliebiger Monat, Wochentag 1 bis 5 (Montag bis Freitag). Ergebnis: 9:30 Uhr jeden Werktag.
Feld 1: Minute (0–59)
Das Minutenfeld gibt an, in welcher Minute(n) der Stunde der Job ausgeführt werden soll. 0 bedeutet zur vollen Stunde, 30 bedeutet zur halben Stunde, 59 bedeutet eine Minute vor dem Stundenwechsel. * führt den Job jede Minute aus.
Feld 2: Stunde (0–23)
Stunden verwenden das 24-Stunden-Format. 0 ist Mitternacht, 12 ist Mittag, 23 ist 23:00 Uhr. In Cron gibt es kein AM/PM — ein Job um 9:00 Uhr morgens hat Stunde 9, und ein Job um 21:00 Uhr hat Stunde 21.
Feld 3: Tag des Monats (1–31)
Anders als die anderen Felder beginnt der Tag-des-Monats bei 1, nicht bei 0. Gültige Werte sind 1 bis 31. Wenn Sie einen Tag angeben, der in einem bestimmten Monat nicht existiert (z. B. Tag 31 im April), wird der Job in diesem Monat einfach nicht ausgeführt. In Quartz steht das Sonderzeichen L für den letzten Tag des Monats, unabhängig davon, wie viele Tage er hat.
Feld 4: Monat (1–12)
Monatswerte laufen von 1 (Januar) bis 12 (Dezember). Viele Scheduler akzeptieren auch dreibuchstabige Abkürzungen: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC. Diese sind in den meisten Implementierungen nicht case-sensitiv.
Feld 5: Wochentag (0–7)
Dies ist das Feld mit dem meisten historischen Ballast. Sowohl 0 als auch 7 stehen für Sonntag — das ist eine Kompatibilitätseigenheit aus frühen Unix-Zeiten. Montag ist 1, Dienstag 2, bis Samstag 6. Dreibuchstabige Namen funktionieren auch hier: SUN, MON, TUE, WED, THU, FRI, SAT.
Wenn sowohl Tag-des-Monats als auch Wochentag angegeben sind (keines ist *), verwenden die meisten Unix-Cron-Daemons ODER-Logik: Der Job läuft, wenn eines der Felder übereinstimmt. Das überrascht viele Entwickler. Wenn Sie "den 15., aber nur wenn es ein Werktag ist" möchten, müssen Sie diese zusätzliche Prüfung im Job-Skript selbst implementieren, nicht im Cron-Ausdruck.
Sonderzeichen
Sternchen (*) — Jeder Wert
Das Sternchen stimmt mit jedem gültigen Wert eines Felds überein. Im Minutenfeld bedeutet * die Minuten 0 bis 59. Im Monatsfeld bedeutet es alle 12 Monate. Es ist das häufigste Zeichen in Cron-Ausdrücken.
Schrägstrich (/) — Schrittewerte
Der Schrägstrich definiert ein Schrittintervall. */5 im Minutenfeld bedeutet "alle 5 Minuten". Genauer gesagt bedeutet es "jeden Wert im Bereich, der durch 5 teilbar ist, beginnend ab dem ersten Wert im Bereich". */5 in Minuten ergibt also 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55.
Schritte können mit Bereichen kombiniert werden: 10-30/5 im Minutenfeld bedeutet alle 5 Minuten zwischen Minute 10 und Minute 30, was 10, 15, 20, 25, 30 ergibt. Der Schritt beginnt ab der unteren Grenze des Bereichs.
Komma (,) — Liste von Werten
Kommas erstellen eine Liste spezifischer Werte. 1,3,5 im Monatsfeld bedeutet Januar, März und Mai. 9,17 im Stundenfeld bedeutet 9:00 und 17:00 Uhr. Sie können beliebig viele Werte auflisten und diese mit anderen Konstrukten kombinieren.
Bindestrich (-) — Bereich
Ein Bindestrich gibt einen inklusiven Bereich an. 1-5 im Wochentag-Feld bedeutet Montag bis Freitag. 9-17 im Stundenfeld bedeutet 9 bis 17 Uhr. Bereiche sind an beiden Enden inklusive.
Fragezeichen (?) — Kein spezifischer Wert (nur Quartz)
Standard-Unix-Cron unterstützt ? nicht. Im Quartz Scheduler wird es in den Feldern für Tag-des-Monats oder Wochentag verwendet und bedeutet "dieses Feld ist mir egal". Da Quartz Konflikte zwischen Tag-des-Monats und Wochentag nicht immer auflösen kann, muss eines der beiden auf ? gesetzt werden, wenn das andere angegeben ist. 0 0 15 * ? bedeutet "am 15. jedes Monats, an jedem Wochentag". 0 0 ? * MON bedeutet "jeden Montag, an jedem Tag des Monats".
L — Letzter (nur Quartz)
L im Tag-des-Monats-Feld bedeutet der letzte Tag des Monats. L im Wochentag-Feld bedeutet Samstag, oder in Kombination mit einer Zahl (z. B. 5L) das letzte Vorkommen dieses Wochentags im Monat. 5L ist der letzte Freitag des Monats.
W — Nächster Werktag (nur Quartz)
W im Tag-des-Monats-Feld findet den nächsten Werktag (Montag–Freitag) zum angegebenen Tag. 15W bedeutet der nächste Werktag zum 15. Wenn der 15. ein Samstag ist, läuft der Job am 14. (Freitag). Wenn er ein Sonntag ist, läuft er am 16. (Montag). W überschreitet keine Monatsgrenzen.
Raute (#) — N-ter Wochentag des Monats (nur Quartz)
# gibt das N-te Vorkommen eines Wochentags in einem Monat an. 5#2 bedeutet der zweite Freitag des Monats. 2#1 bedeutet der erste Dienstag. Wenn das angegebene Vorkommen in einem bestimmten Monat nicht existiert, wird der Job in diesem Monat nicht ausgeführt.
Häufige Cron-Muster
# Every minute
* * * * *
# Every day at midnight (00:00)
0 0 * * *
# Every day at 9:30 AM
30 9 * * *
# Every Monday at 8:00 AM
0 8 * * 1
# First day of every month at noon
0 12 1 * *
# Every 15 minutes
*/15 * * * *
# Weekdays at 6:00 PM
0 18 * * 1-5 Sie können diese Ausdrücke mit dem Cron Parser-Tool testen und validieren, das die nächsten fünf Ausführungszeiten für jeden Ausdruck anzeigt und ungültige Syntax hervorhebt. Verwenden Sie den Timestamp Converter, wenn Sie überprüfen möchten, welchem Zeitpunkt ein bestimmter Unix-Timestamp in Ihrer lokalen Zeitzone entspricht.
Die 6-Feld-Erweiterung: Quartz Scheduler
Der Quartz Scheduler — im Java-Ökosystem weit verbreitet und von vielen Enterprise-Schedulern übernommen — fügt am Anfang des Ausdrucks ein obligatorisches Sekundenfeld hinzu. Das Format wird: Sekunde Minute Stunde Tag-des-Monats Monat Wochentag.
# Quartz 6-field: second minute hour day month weekday
# Run at exactly 00 seconds, 30 minutes, every hour
0 30 * * * ?
# Run at midnight every day
0 0 0 * * ?
# Run every 5 seconds
0/5 * * * * ?
# Last day of month at 10:00 AM
0 0 10 L * ?
# Last Friday of month at 3:00 PM
0 0 15 ? * 6L
Wesentliche Unterschiede zu Standard-Cron: Das Sekundenfeld (0–59) ist das erste und obligatorische Feld; der Wochentag verwendet 1 (Sonntag) bis 7 (Samstag), nicht 0–6; ? ist entweder in Tag-des-Monats oder Wochentag erforderlich, wenn das andere angegeben ist; und L, W und # sind gültige Sonderzeichen.
Fügen Sie niemals einen Quartz-Ausdruck ohne Anpassungen in eine Unix-Crontab ein — Sie müssen das Sekundenfeld entfernen und die Wochentagnummerierung anpassen. Die Parser sind nicht austauschbar.
Cron in verschiedenen Systemen
Linux/Unix crontab (Vixie cron)
Die ursprüngliche und häufigste Form. Fünf Felder, durch Leerzeichen getrennt, gefolgt vom Befehl. Umgebungsvariablen wie CRON_TZ oder TZ legen die Zeitzone fest. Benutzer-Crontabs werden mit crontab -e bearbeitet; System-Crontabs befinden sich in /etc/cron.d/. Die Abkürzungen @reboot, @daily, @hourly, @weekly und @monthly werden als Aliase für häufige Muster weitgehend unterstützt.
GitHub Actions
GitHub Actions verwendet standardmäßige 5-Feld-Cron-Syntax, die Zeitzone ist jedoch immer UTC — es gibt keine Möglichkeit, eine lokale Zeitzone im Ausdruck selbst anzugeben. Ausdrücke werden auf Repository-Ebene ausgewertet, nicht pro Job. Beachten Sie, dass geplante Workflows bei hoher Last in der GitHub-Infrastruktur um mehrere Minuten verzögert werden können.
# GitHub Actions schedule syntax (5-field UTC only)
on:
schedule:
# Run every day at 02:30 UTC
- cron: '30 2 * * *'
# Run every Monday at 09:00 UTC
- cron: '0 9 * * 1' Die offizielle GitHub Actions Cron-Dokumentation weist darauf hin, dass das Mindestintervall 5 Minuten beträgt — Ausdrücke, die häufiger ausgeführt würden, werden stillschweigend ignoriert.
AWS EventBridge (CloudWatch Events)
AWS EventBridge unterstützt sowohl Rate-Ausdrücke (rate(5 minutes)) als auch Cron-Ausdrücke. Ihre Cron-Variante hat 6 Felder, unterscheidet sich aber von Quartz: Der Wochentag verwendet Sun–Sat-Namen oder 1–7, wobei 1 Sonntag ist; alle Zeiten sind UTC; und mindestens eines der Felder Tag-des-Monats oder Wochentag muss ? sein. AWS unterstützt die Zeichen W oder # nicht.
# AWS EventBridge (cron in UTC, 6-field variant)
# Runs every day at 10:00 AM UTC
cron(0 10 * * ? *)
# Runs at 6:00 PM on the last weekday of every month
cron(0 18 L-1 * ? *) Kubernetes CronJob
Kubernetes CronJob verwendet standardmäßige 5-Feld-Cron-Syntax. Die Zeitzone entspricht standardmäßig der Zeitzone des kube-controller-manager-Prozesses (bei verwalteten Clustern üblicherweise UTC). Kubernetes 1.25 hat das Feld timeZone zur CronJob-Spezifikation hinzugefügt, das die Konfiguration der Zeitzone pro Job ermöglicht, ohne auf die Systemzeitzone angewiesen zu sein.
Node.js (node-cron / cron npm)
Das beliebte Paket node-cron unterstützt standardmäßige 5-Feld-Ausdrücke sowie ein optionales 6. Sekundenfeld am Anfang. Das Paket cron ist Quartz-kompatibel. Beide unterstützen Zeitzonenzeichenketten (z. B. America/New_York) als Konstruktoroption. Prüfen Sie die Dokumentation Ihres jeweiligen Pakets, um zu bestätigen, welches Format erwartet wird.
Häufige Fallstricke
Zeitzonenannahmen
Cron läuft in der Server- oder Container-Zeitzone, die in Cloud-Umgebungen häufig UTC ist. Ein Job, der um "9 Uhr Geschäftszeit" laufen soll und auf 0 9 * * * eingestellt ist, wird um 9:00 UTC ausgeführt — was je nach Offset und Sommerzeit 4:00 Uhr, 5:00 Uhr oder 11:00 Uhr in Ihrer lokalen Zeitzone sein kann. Setzen Sie immer CRON_TZ, verwenden Sie das Zeitzonenfeld Ihres Schedulers, oder rechnen Sie Ihre Zielzeit explizit in UTC um. Der Timezone Converter hilft Ihnen, das UTC-Äquivalent für jede lokale Zeit in jeder Zeitzone zu finden.
ODER-Logik bei Tag-des-Monats / Wochentag
In Unix-Cron werden bei Angabe sowohl des Tag-des-Monats als auch des Wochentags (keines ist *) beide mit ODER verknüpft: Der Job läuft, wenn eines der Felder übereinstimmt. 0 9 15 * 1 läuft also am 15. jedes Monats UND jeden Montag — nicht nur an Montagen, die zufällig der 15. sind. Um UND-Logik zu erreichen, müssen Sie die zusätzliche Prüfung im Job-Skript selbst implementieren.
Schrittewerte mit Bereichen verwechseln
*/5 bedeutet "alle 5 Minuten ab 0" (0, 5, 10 ...). 5/5 bedeutet "alle 5 Minuten ab 5" (5, 10, 15 ...). 5-30/5 bedeutet "alle 5 Minuten zwischen Minute 5 und Minute 30" (5, 10, 15, 20, 25, 30). Die Kombination mit Bereichen kann unerwartete Ergebnisse erzeugen, wenn Sie nicht bewusst auf den Startwert achten.
Die "jede Sekunde"-Falle
Die minimale Auflösung von Cron im standardmäßigen 5-Feld-Format beträgt eine Minute. Sie können einen Cron-Job nicht so planen, dass er jede Sekunde oder alle paar Sekunden mittels einer Crontab ausgeführt wird. Für Sub-Minuten-Scheduling verwenden Sie einen sprachebenen Timer (setInterval in Node.js, APScheduler in Python) oder ein zweckmäßiges Queue-System anstelle von Cron. Wenn Sie alle 30 Sekunden benötigen, führen Sie zwei Cron-Jobs aus: einen bei * * * * * und einen, der 30 Sekunden wartet, bevor er ausgeführt wird.
Die Monatsnummerierung vergessen
In Standard-Cron laufen die Monate von 1 (Januar) bis 12 (Dezember). In manchen Programmiersprachen-Datums-APIs sind Monate 0-basiert (0 = Januar, 11 = Dezember). Wenn Sie Cron-Ausdrücke programmgesteuert aus Datumsobjekten generieren, überprüfen Sie sorgfältig, ob Sie im Monatsfeld keinen Off-by-one-Fehler haben.
Ihre Ausdrücke validieren
Der Cron Parser auf Toova zeigt die nächsten fünf geplanten Ausführungszeiten für jeden Ausdruck an, unterstützt sowohl 5-Feld- als auch 6-Feld-Quartz-Syntax und markiert ungültige Werte direkt im Editor. Zum schnellen Überprüfen ist crontab.guru ein bekanntes interaktives Tool, das Ausdrücke auf einfaches Englisch beschreibt. Beide sind nützlich als Lesezeichen.
Wenn Sie mit Timestamps und geplanten Zeiten arbeiten, übersetzt der Timestamp Converter zwischen Unix-Timestamps und für Menschen lesbaren Datumsangaben in jeder Zeitzone. Für zeitzonensensitives Scheduling kombinieren Sie ihn mit dem Timezone Converter, um Offsets, Sommerzeitübergänge und UTC-Äquivalente zu überprüfen, bevor Sie Ihren endgültigen Ausdruck schreiben.