Visuell bauen, nächste Läufe sehen, Klartext-Erklärung
Eine cron-Expression ist eine 5-Felder-Notation aus der Unix-Welt, die definiert, wann ein Job ausgeführt wird: Minute, Stunde, Tag des Monats, Monat und Wochentag. Sie wird seit den 1970ern in Unix-Systemen verwendet und ist heute Standard in Kubernetes-CronJobs, GitLab/GitHub Actions, AWS CloudWatch und vielen anderen Systemen.
Der klassische Unix-Cron-Daemon liest beim Start die crontab-Dateien aus /etc/crontab und /var/spool/cron/crontabs/ und legt eine Liste aller Jobs im Speicher an. Jede Minute weckt der Daemon auf, vergleicht die aktuelle Wanduhrzeit mit allen fünf Feldern jeder Expression und startet alle Jobs, deren Felder matchen. Wichtig: cron prüft minutengenau, nicht sekundengenau — eine Sekundenkomponente gibt es im klassischen POSIX-cron schlicht nicht. Quartz und manche Spring/Java-Cron-Bibliotheken erweitern die Syntax auf sechs Felder mit führender Sekunde, was zur Inkompatibilität mit Unix-cron führt.
Das DayOfMonth- und das DayOfWeek-Feld haben eine Besonderheit: Sind beide gesetzt (nicht *), wird ein OR verknüpft, nicht ein AND. 0 0 13 * 5 bedeutet also "jeden 13. UND jeden Freitag um Mitternacht", nicht "jeden Freitag, der ein 13. ist". Wer letzteres will, braucht Quartz-Syntax oder muss im Job selbst prüfen. Auch wichtig: cron interpretiert die Werte im Kontext der Server-Lokalzeit, nicht UTC. Ein Job 0 3 * * * auf einem Server in Europe/Berlin läuft in der DST-Übergangsnacht im Frühjahr gar nicht (3 Uhr existiert nicht) und im Herbst zweimal (3 Uhr existiert doppelt) — moderne Implementierungen wie systemd-timers oder anacron behandeln das robuster.
Erweiterte Cron-Dialekte bringen Sonderzeichen mit: L (last day of month/week), W (nearest weekday), # (n-ter Wochentag im Monat — z.B. 5#2 = 2. Freitag). Diese sind Quartz/Spring-spezifisch und werden von Unix-cron, GitHub Actions oder Vercel Cron nicht verstanden. GitHub Actions akzeptiert Standard-POSIX-cron mit fünf Feldern, garantiert aber keine punktgenaue Ausführung — Jobs können mehrere Minuten verzögert starten, wenn die Runner-Queue belastet ist. Für millisekunden-genaue Scheduling-Anforderungen ist cron das falsche Werkzeug; nimm dann Task Queues wie Sidekiq, Celery oder dedizierte Scheduler wie Temporal.
`*` steht für alle Werte, Kommas (1,2,3) trennen Werte, Bindestriche (1-5) markieren Bereiche, Schrägstriche (*/15) markieren Schritte. Beispiele: `0 0 * * 0` = jeden Sonntag um Mitternacht, `*/10 * * * *` = alle 10 Minuten, `0 9-17 * * 1-5` = jede volle Stunde von 9-17 Uhr an Werktagen.
Die fünf Felder einer klassischen cron-Expression (POSIX crontab) haben jeweils einen festen Wertebereich. Werte ausserhalb fuehren zu Parse-Fehlern.
0-59. Beispiel */5 = alle 5 Minuten ab 0.0-23 im 24-Stunden-Format. Beispiel 9-17 = stuendlich von 9 bis 17 Uhr.1-31. Achtung: ein 31 im Feld bedeutet im Februar nie ein Trigger.1-12 oder JAN-DEC (case-insensitiv) in vielen Implementierungen.0-6 wobei 0 und 7 beide Sonntag sind. Aliase SUN-SAT sind ueblich.Diese Ausdruecke kommen so in Produktions-Crontabs vor. Kopiere sie als Startpunkt und passe sie an deine Zeitzone an.
0 9 * * 1-5 — Werktags um 9:00 Uhr, klassisch fuer Morning-Reports oder Slack-Standups.*/15 8-18 * * 1-5 — alle 15 Minuten waehrend der Buerozeiten, fuer Polling von Lieferanten-APIs.0 2 * * 0 — sonntags um 2 Uhr nachts: typisch fuer Vollbackups oder VACUUM ANALYZE in Postgres.30 3 1 * * — am 1. jedes Monats um 03:30 fuer Monatsabschluss, Rechnungs-Export oder Logrotate-Archivierung.0 0 1 1 * — einmal pro Jahr am 1. Januar um Mitternacht, zum Beispiel fuer Jahres-Counter-Reset.cron garantiert kein exactly-once-Verhalten. Stuerzt der Server zwischen zwei Wakeups ab, geht der Trigger verloren — anacron schliesst diese Luecke fuer einmal-pro-Tag-Jobs, klassisches cron tut das nicht. Laufen zwei Instanzen eines Jobs gleichzeitig (z.B. weil der vorherige Lauf noch nicht fertig ist), entstehen Race Conditions; nutze deshalb flock oder Datei-Locks im Skript selbst. In Container-Umgebungen wie Kubernetes ersetzt CronJob den Daemon, aber das concurrencyPolicy: Forbid-Flag muss explizit gesetzt werden, sonst startet K8s neue Pods waehrend der alte noch laeuft. Auch die Zeitzone ist eine haeufige Fehlerquelle: Container laufen oft in UTC, die Crontab-Datei aber wurde fuer Europe/Berlin geschrieben — Resultat sind Jobs zwei Stunden zu frueh. Setze CRON_TZ=Europe/Berlin oben in der crontab oder schalte explizit auf UTC um. Loggings via >> /var/log/job.log 2>&1 sind Pflicht, weil cron stdout/stderr per Mail verschickt, was in Containern verloren geht.
* * * * *?* * * * * und * * * * * sleep 30; cmd, oder Quartz/Spring nutzen, die ein zusaetzliches Sekundenfeld haben.chmod +x) oder ein Job, der per stdin liest und nichts bekommt.CRON_TZ=UTC (oder beliebige IANA-Zone) als erste Zeile der crontab oder per TZ-Variable. In Kubernetes CronJob steuert das Feld spec.timeZone die Auswertung (verfuegbar ab K8s 1.27).0 0 1 * MON dasselbe wie "erster Montag im Monat"?0 0 0 ? * MON#1 oder eine Wrapper-Logik im Skript: "falls Datum > 7, exit".