Cron Expression Generator

Visuell bauen, nächste Läufe sehen, Klartext-Erklärung

{{ __t('description') }}: {{ description }}
{{ __t('next_runs') }}
  • {{ d.toLocaleString() }}
{{ __t('presets') }}

Was ist eine cron-Expression?

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.

Wie cron intern arbeitet

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.

Syntax-Kurzreferenz

`*` 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.

Felder im Detail

Die fünf Felder einer klassischen cron-Expression (POSIX crontab) haben jeweils einen festen Wertebereich. Werte ausserhalb fuehren zu Parse-Fehlern.

  • Minute: 0-59. Beispiel */5 = alle 5 Minuten ab 0.
  • Hour: 0-23 im 24-Stunden-Format. Beispiel 9-17 = stuendlich von 9 bis 17 Uhr.
  • Day of month: 1-31. Achtung: ein 31 im Feld bedeutet im Februar nie ein Trigger.
  • Month: 1-12 oder JAN-DEC (case-insensitiv) in vielen Implementierungen.
  • Day of week: 0-6 wobei 0 und 7 beide Sonntag sind. Aliase SUN-SAT sind ueblich.

Praktische Beispiele aus dem Alltag

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.

Grenzen, Fallstricke, gute Praxis

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.

Haeufige Fragen zu cron

Was bedeutet * * * * *?
Jede Minute, jede Stunde, jeden Tag, jeden Monat, jeden Wochentag — also einmal pro Minute, 1440-mal pro Tag.
Wie schreibe ich "alle 30 Sekunden" in cron?
Geht in POSIX-cron nicht direkt, da die kleinste Aufloesung eine Minute ist. Workaround: zwei Eintraege * * * * * und * * * * * sleep 30; cmd, oder Quartz/Spring nutzen, die ein zusaetzliches Sekundenfeld haben.
Warum laeuft mein cron-Job nicht?
Die haeufigsten Ursachen: falscher PATH (cron startet mit minimaler Umgebung — absolute Pfade nutzen), fehlender Newline am Ende der crontab, falsches Konto (User-crontab vs. /etc/crontab), fehlende Ausfuehrungsrechte (chmod +x) oder ein Job, der per stdin liest und nichts bekommt.
Welche Zeitzone nutzt cron?
Standardmaessig die System-Lokalzeit. Setze 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).
Ist 0 0 1 * MON dasselbe wie "erster Montag im Monat"?
Nein. Da DayOfMonth und DayOfWeek mit OR verknuepft sind, triggert dieser Ausdruck am 1. jeden Monats UND an jedem Montag. Fuer den ersten Montag brauchst du Quartz-Syntax 0 0 0 ? * MON#1 oder eine Wrapper-Logik im Skript: "falls Datum > 7, exit".
Was passiert bei einer Sommerzeit-Umstellung?
Klassischer Unix-cron behandelt DST ungeschickt: Im Fruehjahr werden Jobs zwischen 02:00 und 03:00 uebersprungen, im Herbst doppelt ausgefuehrt. Vixie-cron und systemd-timers haben Heuristiken dagegen. Sichere Praxis: planen Jobs nicht zwischen 02:00 und 04:00 Lokalzeit, oder nutze UTC fuer alle Schedules.

Verwandte Tools