Skip to content
Zurück zum Blog
Tutorials

Crontab-Spickzettel: 50+ Cron-Ausdrücke und moderner Scheduler-Guide

Crontab-Spickzettel mit 50+ kopierfertigen Cron-Ausdrücken, Syntax Feld für Feld erklärt, OR-Falle, Zeitzonen-Fixes und Kubernetes/GitHub/AWS im Vergleich.

13 Min. Lesezeit

Crontab-Spickzettel: 50+ Cron-Ausdrücke, Syntax und moderner Scheduler-Guide

Ein Cron-Ausdruck besteht aus fünf Feldern (Minute, Stunde, Tag im Monat, Monat, Wochentag), gefolgt von einem Befehl. Diese Grammatik steuert die Unix-Zeitplanung seit 1979 und läuft heute auch unter Kubernetes CronJobs, GitHub Actions, AWS EventBridge und Vercel-Cron-Triggern. Wer sie einmal beherrscht, kann sie überall einsetzen.

Diese Seite richtet sich an Entwicklerinnen und Entwickler, die sofort einen Ausdruck brauchen: eine Linux-Aufgabe, einen Kubernetes CronJob, einen GitHub-Actions-Trigger oder die Fehlersuche, warum ein Fünf-Minuten-Job nur stündlich feuert. Scrollen Sie zur Schnellreferenz-Tabelle für kopierfertige Ausdrücke, springen Sie zu Syntax entschlüsselt für die Feldregeln oder öffnen Sie den Crontab Generator — eine datenschutzfreundliche crontab-guru-Alternative, die im Browser läuft —, um Ausdrücke live zu prüfen.

Schnellreferenz-Tabelle für Cron-Ausdrücke

Dreißig Ausdrücke decken die häufigsten Zeitplanungsfälle ab. Jeder ist gültiges POSIX-Cron mit fünf Feldern: einfügen in crontab -e, in ein Kubernetes-schedule: oder in ein GitHub-Actions-cron:.

ZeitplanCron-AusdruckKlartext
Jede Minute* * * * *jede Minute, den ganzen Tag, jeden Tag
Alle 5 Minuten*/5 * * * *Minute 0, 5, 10, …, 55
Alle 15 Minuten*/15 * * * *Minute 0, 15, 30, 45
Alle 30 Minuten*/30 * * * *Minute 0 und 30
Jede Stunde0 * * * *zur vollen Stunde
Alle 2 Stunden0 */2 * * *Stunde 0, 2, 4, …, 22
Alle 6 Stunden0 */6 * * *Stunde 0, 6, 12, 18
Zweimal täglich (9 Uhr + 21 Uhr)0 9,21 * * *Minute 0 der Stunden 9 und 21
Werktags um 9 Uhr0 9 * * 1-5Mo–Fr 09:00
Wochenende um 9 Uhr0 9 * * 0,6Sa und So 09:00
Täglich um Mitternacht0 0 * * *jeden Tag 00:00
Täglich um 2:30 Uhr30 2 * * *ruhiges Batch-Fenster
Jeden Montag um 9 Uhr0 9 * * 1Montags 09:00
Jeden Freitag um 17 Uhr0 17 * * 5Freitags 17:00
Jeden Sonntag um Mitternacht0 0 * * 0entspricht @weekly
Monatsersten um Mitternacht0 0 1 * *1. Tag 00:00 (entspricht @monthly)
15. jedes Monats um 12 Uhr0 12 15 * *Gehaltsfenster zur Monatsmitte
Letzter-Tag-Prüfung (Wrapper)0 0 28-31 * * + Skriptbenötigt Datumsprüfung
Quartalsweise (1. Jan/Apr/Jul/Okt)0 0 1 JAN,APR,JUL,OCT *erster Tag jedes Quartals
Jährlich (1. Januar)0 0 1 1 * oder @yearlyNeujahrsmitternacht
Alle 5 Min werktags 9–17 Uhr*/5 9-17 * * 1-5Polling während Geschäftszeiten
Alle 30 Min am Wochenende*/30 * * * 0,6Sa/So-Monitoring
Zweimal pro Stunde, :15 und :4515,45 * * * *versetzt zum :00-Ansturm
Erster Montag (Wrapper)0 9 1-7 * 1 + AND-PrüfungWrapper nötig (siehe unten)
Makros@hourly @daily @weekly @monthly @yearlynicht-standard, aber weit verbreitet
Nur beim Neustart@rebootnicht-standard, nur Vixie-Cron

Fügen Sie einen dieser Ausdrücke in den Crontab Generator ein, um die nächsten fünf Auslösungen zu prüfen. Das ist der schnellste Pre-Deploy-Check.

Cron-Syntax entschlüsselt: die 5 Felder

Ein Cron-Ausdruck besteht aus fünf durch Leerzeichen getrennten Feldern und einem Befehl. Jedes Feld steuert ein Segment des Zeitplans. Das ist der Kern der Cron-Ausdrucks-Syntax in jedem Scheduler dieses Guides.

┌──────────── Minute       (0 - 59)
│ ┌────────── Stunde       (0 - 23)
│ │ ┌──────── Tag im Monat (1 - 31)
│ │ │ ┌────── Monat        (1 - 12 oder JAN-DEC)
│ │ │ │ ┌──── Wochentag    (0 - 6 oder SUN-SAT; 0 und 7 stehen beide für Sonntag)
│ │ │ │ │
* * * * *  auszuführender-Befehl

Eselsbrücke: „Meine Stunde Tut Mir Weh” für Minute, Stunde, Tag im Monat, Monat, Wochentag. Von links nach rechts, von der kleinsten zur größten Einheit.

Erlaubte Werte Feld für Feld

FeldBereichAliaseHinweise
Minute0–59keine0 bedeutet „zur vollen Stunde”
Stunde0–23keine24-Stunden-Uhr; 0 ist Mitternacht, 12 ist Mittag
Tag im Monat1–31keineungültige Tage feuern stillschweigend nie (31. Februar)
Monat1–12JAN, FEB, MAR, …, DECGroß-/Kleinschreibung egal
Wochentag0–7SUN, MON, TUE, …, SAT0 und 7 stehen beide für Sonntag

Operatoren im Detail

Fünf Operatoren decken jeden Standard-Cron-Ausdruck ab:

OperatorBedeutungBeispielBedeutet
*beliebiger Wert* * * * *jede Minute
,Liste0 9,12,17 * * *09:00, 12:00, 17:00
-inklusiver Bereich0 9-17 * * *jede Stunde von 09:00 bis 17:00
/Schritt*/15 * * * *Minute 0, 15, 30, 45
gemischtkombiniert0 9-12,14-17 * * *Vormittag + Nachmittag, Mittagspause aussparen

Beim Schritt-Operator lohnt sich ein zweiter Blick. */N ist am niedrigsten Wert des Feldes verankert, nicht an der aktuellen Uhrzeit. */15 bedeutet „Minute 0, 15, 30, 45 jeder Stunde”, nicht „alle 15 Minuten ab jetzt”. Speichern Sie um 12:03 ab, läuft der nächste Job um 12:15. Mit einer Nicht-Wildcard-Basis liest sich 5/15 als „starte bei 5, dann alle 15”: Minute 5, 20, 35, 50.

Benannte Monate und Wochentage

Schreiben Sie Monate und Wochentage als Namen, Groß-/Kleinschreibung ist egal:

0 0 1 JAN,APR,JUL,OCT *    # erster Tag jedes Quartals
0 9 * * MON-FRI            # werktags um 9 Uhr
0 17 * * FRI               # Freitag um 17 Uhr

Namen sind im Code-Review lesbarer; numerische Formen sind etwas portabler. Wählen Sie pro Projekt einen Stil.

Nicht standardisierte Makros: @reboot, @daily und Verwandte

Die meisten Cron-Implementierungen akzeptieren sechs Abkürzungsmakros:

MakroBedeutetBedeutung
@yearly / @annually0 0 1 1 *einmal im Jahr, 1. Januar um Mitternacht
@monthly0 0 1 * *Monatsersten um Mitternacht
@weekly0 0 * * 0jeden Sonntag um Mitternacht
@daily / @midnight0 0 * * *jeden Tag um Mitternacht
@hourly0 * * * *zu jeder vollen Stunde
@reboot(speziell)einmal beim Start des Cron-Daemons

Diese Makros sind nicht standardisiert: Vixie-Cron und Cronie unterstützen sie, Kubernetes CronJob, GitHub Actions und AWS EventBridge nicht. Für portable Ausdrücke schreiben Sie die Fünf-Feld-Form aus. @reboot funktioniert in Containern selten, weil der Cron-Daemon dort meist nicht der Init-Prozess ist.

50+ kopierfertige Cron-Ausdrücke (nach Anwendungsfall gruppiert)

Die Schnellreferenz-Tabelle deckt die häufigen Fälle ab. Dieser Abschnitt geht in sechs Kategorien mit dichteren Cron-Job-Beispielen tiefer.

Alle N Minuten

* * * * *          # jede Minute
*/2 * * * *        # alle 2 Minuten
*/5 * * * *        # alle 5 Minuten — der Klassiker „cron expression every 5 minutes"
*/10 * * * *       # alle 10 Minuten
*/15 * * * *       # alle 15 Minuten
*/30 * * * *       # alle 30 Minuten
0,30 * * * *       # explizite Minuten 0 und 30 (gleich wie */30)
*/45 * * * *       # WARNUNG: feuert nur bei 0 und 45, dann erfolgt der Wrap

*/45 ist eine klassische Stolperfalle: Minute reicht von 0 bis 59, also landet der Job bei 0 und 45 und springt dann zur nächsten Stunde. Für eine echte 45-Minuten-Kadenz brauchen Sie einen externen Worker.

Stündliche Varianten

0 * * * *          # jede Stunde zur :00
30 * * * *         # jede Stunde zur :30
0 */2 * * *        # alle 2 Stunden, gerade Stunden
0 */6 * * *        # alle 6 Stunden
0 */12 * * *       # zweimal täglich um 00:00 und 12:00
15 */2 * * *       # alle 2 Stunden, um 15 Min versetzt (vermeidet :00-Spike)

Täglich zu festen Zeiten

0 0 * * *          # Mitternacht (= @daily / @midnight)
30 2 * * *         # 02:30 — ruhiges Batch-Fenster
0 9 * * *          # 09:00
45 23 * * *        # 23:45 — Tagesabschluss-Rollups
0 9,12,17 * * *    # dreimal täglich
0 9-17 * * *       # jede Stunde von 09:00 bis 17:00

Wöchentliche Zeitpläne

0 9 * * 1-5        # werktags um 9 Uhr
0 9 * * 0,6        # Wochenende um 9 Uhr
0 18 * * 5         # freitags um 18 Uhr
0 0 * * 0          # Sonntag um Mitternacht (= @weekly)
0 9 * * MON,WED,FRI # Mo/Mi/Fr um 9 Uhr
*/30 9-17 * * 1-5  # alle 30 Min, Geschäftszeiten, werktags

Monatlich und quartalsweise

0 0 1 * *          # Monatsersten um Mitternacht (= @monthly)
0 0 15 * *         # 15. — Gehaltsfenster
0 0 1,15 * *       # 1. und 15. — halbmonatlich
0 0 1 */3 *        # quartalsweise: 1. Januar, April, Juli, Oktober
0 0 1 JAN,APR,JUL,OCT *  # dasselbe, mit Monatsnamen
0 0 28-31 * *      # letzte Tage — mit Datumsprüfungs-Wrapper kombinieren

Für den letzten Tag des Monats gibt es keinen nativen POSIX-Ausdruck. Verwenden Sie einen Wrapper, der date -d tomorrow +%d = 01 prüft, oder einen Scheduler mit nativer Unterstützung (Quartz hat L; Kubernetes nicht).

Jährlich und Makro-Abkürzungen

0 0 1 1 *          # 1. Januar um Mitternacht (= @yearly / @annually)
0 0 25 12 *        # Weihnachten um Mitternacht
@yearly            # = 0 0 1 1 *
@monthly           # = 0 0 1 * *
@weekly            # = 0 0 * * 0
@daily             # = 0 0 * * *
@hourly            # = 0 * * * *
@reboot            # speziell: einmal beim Daemon-Start (nur Vixie-Cron)

All diese Ausdrücke lassen sich in den Crontab Generator einfügen, um die nächsten fünf Auslösungen zu prüfen. Das ist der günstigste Smoke-Test vor dem Deploy.

Cron vs. systemd-Timer vs. Cloud-Scheduler: Entscheidungsmatrix

Cron ist die Standardwahl, aber nicht immer die beste. Die sieben gängigsten Scheduler im Vergleich. Das hilft bei „cron vs systemd timer”-Entscheidungen, Kubernetes CronJob gegen Vercel-Cron-Job oder der Migration von crontab in die Managed-Cloud.

EigenschaftVixie-Cronsystemd-TimerK8s CronJobGHA scheduleAWS EventBridgeVercel CronCloudflare Workers
Feld-Syntax5-Feld POSIXOnCalendar-Spec5-Feld POSIX + timeZone5-Feld POSIX6-Feld Quartz mit ?5-Feld POSIX5-Feld POSIX
Mindestintervall1 Minute1 Sekunde1 Minutebest effort, ≥15 Min empfohlen1 Minute1 Minute (Pro-Tarif)1 Minute
Explizite ZeitzoneCRON_TZ=Persistent=truespec.timeZone (1.27+)nur UTCScheduleExpressionTimezonenur UTCnur UTC
Wiederherstellung verpasster Läufenein (anacron)ja (Persistent=true)ja (startingDeadlineSeconds)neinjaneinnein
Retry / Backoffneinteilweiseja (backoffLimit)Retry bei Fehlerjaneinja
Concurrency-Kontrollenein (flock)teilweiseja (concurrencyPolicy)neinneinneinnein
@reboot-Unterstützungjaja (via OnBootSec=)neinneinneinneinnein

systemd-Timer: wann Sie Cron vorziehen sollten

Auf systemd-basiertem Linux sind Timer eine ernstzunehmende Alternative: lesbare Kalender-Syntax, Journal-Integration, Wiederherstellung verpasster Läufe. Ein Timer mit zugehörigem Service:

# daily-report.timer
[Unit]
Description=Tagesbericht um 9 Uhr ausführen
[Timer]
OnCalendar=*-*-* 09:00:00
Persistent=true
Unit=daily-report.service
[Install]
WantedBy=timers.target
# daily-report.service
[Unit]
Description=Tagesbericht-Job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/daily-report.sh
User=reporter

Aktivieren mit systemctl enable --now daily-report.timer. Der entscheidende Vorteil ist Persistent=true: war die Maschine um 9 Uhr aus, feuert der Timer sofort beim Booten. Vixie-Cron hat ohne anacron kein Äquivalent. Zur Service-Härtung siehe unsere Security Best Practices.

Kubernetes CronJob

Kubernetes umschließt den POSIX-Zeitplan mit Primitiven für Concurrency, Historie und explizite Zeitzone:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-report
spec:
  schedule: "0 2 * * *"
  timeZone: "America/New_York"     # Kubernetes 1.27+
  concurrencyPolicy: Forbid        # niemals zwei gleichzeitig
  startingDeadlineSeconds: 300     # überspringen, wenn >5 Min verzögert
  jobTemplate:
    spec:
      backoffLimit: 2
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: reporter
              image: reporter:1.4.0
              command: ["/usr/local/bin/report.sh"]

concurrencyPolicy: Forbid ist Ihr flock-Äquivalent. Ohne diese Einstellung stapelt sich ein langlaufender Job auf seinen Nachfolger. Sämtliche Stellschrauben finden Sie in der Feld-Referenz.

GitHub Actions: Eigenheiten der Zeitplanung

GitHub Actions akzeptiert standardisierten POSIX-Cron mit fünf Feldern:

on:
  schedule:
    - cron: '0 9 * * 1-5'   # werktags um 9 Uhr UTC

Best Effort: bei hoher Last auf GitHubs Runnern können Jobs Minuten zu spät feuern oder ganz ausfallen. Vermeiden Sie Intervalle unter fünfzehn Minuten. Eine Zeitzonen-Einstellung gibt es nicht, der Zeitplan läuft immer in UTC.

AWS EventBridge: Quartz-Stil mit sechs Feldern

AWS EventBridge verwendet ein Cron im Quartz-Stil mit sechs Feldern und einem verpflichtenden ? in einem der beiden Tagesfelder:

cron(0 9 * * ? *)

Feldreihenfolge: Minuten Stunden Tag-im-Monat Monat Wochentag Jahr. Eines der beiden Tagesfelder muss ? sein, wenn das andere eingeschränkt ist (Quartz’ Antwort auf die POSIX-OR-Mehrdeutigkeit). Wer den Ausdruck direkt aus dem Linux-crontab kopiert, scheitert an der Validierung.

Vercel Cron, Cloudflare Workers, Render Cron Jobs

Neuere Serverless-Plattformen standardisieren auf POSIX mit fünf Feldern. Ein Vercel-Cron-Job lebt in vercel.json als { "crons": [{ "path": "/api/cron/nightly", "schedule": "0 2 * * *" }] }. Cloudflare Workers Cron Triggers nutzen wrangler.toml:

[triggers]
crons = ["*/15 * * * *", "0 9 * * 1-5"]

Render verwendet render.yaml. Alle drei laufen in UTC ohne Zeitzonen-Override pro Zeitplan. Planen Sie von Anfang an in UTC.

7 Cron-Debugging-Fallen (und wie Sie sie aufdecken)

Hinter den meisten Berichten „mein Cron-Job läuft nicht” stecken eine von sieben Ursachen. Arbeiten Sie diese Liste durch, bevor Sie den Scheduler beschuldigen.

Falle 1: PATH ist minimal

Cron startet Jobs mit minimalem $PATH, typischerweise /usr/bin:/bin. Ihre interaktive Shell hat /usr/local/bin, ~/.cargo/bin und ein Dutzend .bashrc-Einträge. Keiner davon existiert in Cron. Das ist die häufigste Ursache von Cron-PATH-Problemen beim Debugging.

Symptom: node: command not found. Lösung: Setzen Sie PATH ganz oben in der crontab oder verwenden Sie absolute Pfade.

SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin

*/15 * * * *  /usr/local/bin/poll-api.sh
0 9 * * *     /home/deploy/.cargo/bin/my-rust-cli

Falle 2: stdout und stderr gehen lautlos verloren

Standardmäßig landet Cron-Output in einem Mail-Spool, den niemand liest. Der Job scheitert stillschweigend. Leiten Sie beide Streams um:

*/15 * * * *  /usr/local/bin/job.sh >> /var/log/job.log 2>&1

Für JSON-Output leiten Sie über jq; zum Extrahieren von Log-Zeilen siehe unseren Regex-Spickzettel. Bei systemd-Timern fängt journalctl -u your-timer.service die Ausgabe ein.

Falle 3: Zeitzonen-Drift zwischen Dev und Prod

Sie schreiben 0 9 * * * auf Ihrem Laptop in New York und erwarten 9 Uhr Eastern. Der Server läuft in UTC. Der Cron feuert um 9 Uhr UTC, also 4 Uhr Eastern, bevor irgendjemand es merkt. Lösung: Server auf UTC stellen und Zeitpläne in UTC schreiben, oder die Zeitzone explizit pinnen.

CRON_TZ=America/New_York
0 9 * * *  /usr/local/bin/morning-report.sh

CRON_TZ funktioniert in Vixie-Cron 3.0+; Kubernetes 1.27+ bietet spec.timeZone; AWS EventBridge hat ScheduleExpressionTimezone; GitHub Actions ist immer UTC. Zu UTC, Sommerzeit und Epoch-Arithmetik siehe unseren Unix-Timestamp-Guide.

Falle 4: Unmaskiertes % in Befehlen

Cron behandelt ein unmaskiertes % als Zeilenumbruch: der Rest der Zeile wird dem Befehl als stdin zugeführt. Damit bricht date +"%Y-%m-%d". Maskieren Sie jedes % als \%, oder verlagern Sie die Logik in ein Skript:

0 0 * * *  echo "Lauf um $(date +"\%Y-\%m-\%d")" >> /tmp/log

Falle 5: Überlappende Läufe

Ein */5 * * * *-Job, der gelegentlich sieben Minuten dauert, startet die nächste Instanz, bevor die vorherige fertig ist. Zwei Kopien streiten um dieselbe Zeile, dasselbe Lockfile und dasselbe API-Kontingent. Serialisieren Sie mit flock:

*/5 * * * *  flock -n /tmp/job.lock /usr/local/bin/job.sh

-n beendet sofort, falls das Lock gehalten wird. Für Kubernetes setzen Sie concurrencyPolicy: Forbid. Bei Lockfile-Berechtigungen lohnt sich ein Blick: siehe Security Best Practices.

Falle 6: @reboot in Containern

@reboot läuft einmal beim Start des Cron-Daemons. In einer VM entspricht das dem Boot. In einem Container ist der Cron-Daemon meist nicht PID 1 und läuft möglicherweise gar nicht. Verwenden Sie @reboot nicht in Containern. Legen Sie Run-once-at-boot-Logik stattdessen in Ihren Entrypoint oder in einen Init-Container.

Falle 7: POSIX-OR-Semantik für Tag im Monat / Wochentag

Die teuerste Cron-Falle. POSIX-Regel: wenn sowohl Tag im Monat als auch Wochentag eingeschränkt sind (keines ist *), feuert der Zeitplan, sobald eines zutrifft.

0 0 1 * 5 sieht aus wie „Mitternacht am 1., nur freitags”, feuert aber am 1. UND an jedem Freitag: sechs bis zehn zusätzliche Auslösungen pro Monat.

# FALSCH: sieht aus wie „1. des Monats, nur wenn Freitag"
0 0 1 * 5
# RICHTIG: nur eine Einschränkung wählen
0 0 1 * *          # jeden 1. des Monats
0 0 * * 5          # jeden Freitag
# AND-Semantik braucht einen Wrapper
0 0 1-7 * 5  [ "$(date +\%u)" = "5" ] && /script    # nur erster Freitag

Verdächtige Ausdrücke in den Crontab Generator einfügen. Die Next-Run-Vorschau macht die OR-Falle sofort sichtbar.

Moderne Scheduler: wann Cron NICHT geeignet ist

Cron passt für „diesen Befehl ungefähr zu dieser Zeit, in fester Kadenz”. Für mehrere benachbarte Probleme ist er falsch:

  • Workflows mit Abhängigkeiten (führe A aus, dann B falls A erfolgreich) → Airflow, Prefect, Dagster.
  • Retry, exponentielles Backoff, Dead-Letter-Queues → Temporal, AWS Step Functions, Sidekiq.
  • Sub-Minuten-Intervalle → langlebiger Worker, der zwischen Iterationen schläft.
  • Sekundengenaue Auslösung → dedizierter Daemon; Managed Scheduler garantieren keine exakten Zeitpunkte.
  • Event-getriebene Arbeit → Webhooks, Message-Queues, Change-Data-Capture-Streams.

Cron verschwindet nicht. Airflow, Step Functions und Sidekiq akzeptieren alle Cron-Ausdrücke als Einstieg in ihre Workflows. Die Fünf-Feld-Grammatik ist wiederverwendbar.

Kubernetes-CronJob-Feldreferenz

Die Entscheidungsmatrix oben zeigte einen minimalen CronJob. Die vollständige Feldreferenz für die kubernetes cronjob syntax:

FeldStandardWas es tut
scheduleerforderlichPOSIX-Cron-Ausdruck mit 5 Feldern
timeZoneController-TZexplizite Zeitzone (1.27+); IANA-Namen verwenden
concurrencyPolicyAllowForbid überspringt neue Läufe, solange der vorherige aktiv ist; Replace bricht ihn ab
startingDeadlineSecondsunbegrenztüberspringen bei größerer Verzögerung
successfulJobsHistoryLimit3erfolgreiche Jobs behalten
failedJobsHistoryLimit1fehlgeschlagene Jobs behalten
suspendfalsepausieren, ohne zu löschen
backoffLimit6Pod-Retries, bevor der Job als Failed markiert wird
activeDeadlineSecondsnicht gesetztharte Obergrenze für die Pod-Laufzeit
ttlSecondsAfterFinishednicht gesetztJob automatisch nach so vielen Sekunden löschen

Zwei häufige Stolperfallen: Wer timeZone vergisst, lässt den Zeitplan der Host-Zeitzone des kube-controller-managers folgen (auf Managed Kubernetes unvorhersehbar). Bei einem Minutenplan sammelt der Standardwert successfulJobsHistoryLimit: 3 drei Job-Objekte pro Minute an, solange ttlSecondsAfterFinished nicht gesetzt ist.

Plattformübergreifende Cron-Äquivalente

macOS launchd. Apple empfiehlt launchd anstelle von Cron. Ein launchd-Job ist eine .plist-Datei in ~/Library/LaunchAgents/:

<plist version="1.0"><dict>
  <key>Label</key><string>com.example.daily</string>
  <key>ProgramArguments</key><array><string>/usr/local/bin/daily.sh</string></array>
  <key>StartCalendarInterval</key>
  <dict><key>Hour</key><integer>9</integer><key>Minute</key><integer>0</integer></dict>
</dict></plist>

Laden mit launchctl load ~/Library/LaunchAgents/com.example.daily.plist. Anders als Cron holt launchd verpasste Läufe nach Sleep/Wake nach.

Windows Task Scheduler verwendet schtasks:

schtasks /create /tn "DailyReport" /tr "C:\scripts\report.bat" /sc DAILY /st 09:00
schtasks /create /tn "EveryFifteen" /tr "C:\scripts\poll.bat" /sc MINUTE /mo 15

Unter WSL läuft natives Linux-Cron, hält aber an, sobald die Session endet. Nutzen Sie den Task Scheduler, um dauerhaft laufende WSL-Jobs zu starten.

Cron in Docker-Containern. Die meisten Slim-Images (alpine, debian-slim, distroless) liefern keinen Cron-Daemon mit. Installieren Sie cronie oder busybox-cron und betreiben Sie sie als PID 1 mit tini oder s6-overlay. Fast immer vorzuziehen ist jedoch ein Kubernetes CronJob.

Fortgeschrittene Tipps und Muster

Letzter Tag des Monats

Cron hat keinen nativen „Letzter-Tag”-Operator. Lassen Sie den Job jeden Tag im 28–31-Fenster laufen und prüfen Sie, ob morgen der 1. ist:

0 23 28-31 * *  [ "$(date -d tomorrow +\%d)" = "01" ] && /usr/local/bin/eom.sh

N-ter Wochentag des Monats

„Erster Montag” nutzt dasselbe Wrapper-Muster: auf Tage 1–7 beschränken, dann den Wochentag prüfen:

0 9 1-7 * *  [ "$(date +\%u)" = "1" ] && /usr/local/bin/first-monday.sh

Für „letzter Freitag” nehmen Sie die Tage 25–31 plus die Wochentagsprüfung.

Zufälliger Versatz zur Lastverteilung

Wenn viele Maschinen denselben Cron ausführen, erzeugt 0 0 * * * um Mitternacht UTC einen Donnerherden-Effekt. Streuen Sie eine zufällige Verzögerung ein:

RANDOM_DELAY=10                                              # cronie / anacron, in Minuten
0 0 * * *  /usr/local/bin/job.sh

0 0 * * *  sleep $((RANDOM \% 600)); /usr/local/bin/job.sh   # portabel

Heartbeat-Monitoring

Cron scheitert stillschweigend. Das Dead-Man’s-Switch-Muster funktioniert so: der Job pingt nach jedem erfolgreichen Lauf einen Monitoring-Dienst, und der Dienst alarmiert, wenn ein erwarteter Ping ausbleibt. Healthchecks.io, Cronitor und Dead Man’s Snitch bieten kostenlose Tarife.

*/15 * * * *  /usr/local/bin/job.sh && curl -fsS --retry 3 https://hc-ping.com/your-uuid

Für Monitoring-Logik, die nach Antwort-Codes verzweigt (200 gesund, 429 ratenbegrenzt, 503 degradiert), siehe unseren HTTP-Statuscodes-Spickzettel.

Idempotenz ist eine Eigenschaft des Jobs, nicht des Schedulers

Cron kennt weder Retry noch Wiederherstellung verpasster Läufe noch Concurrency-Kontrolle. Die zuverlässigste Lösung ist, den Job selbst mehrfach-ausführungssicher zu machen. Statt „sende den heutigen Bericht um 9 Uhr” entwerfen Sie ihn als „sende den heutigen Bericht, wenn noch nicht gesendet”. Verpasste Läufe, Duplikate und manuelle Nachholungen münden dann alle in denselben Zustand.

FAQ

Bedeutet */5 * * * * wirklich alle 5 Minuten?

Fast — */5 * * * * ist an Minute 0 verankert, nicht „alle 5 Minuten ab jetzt”. Der Job feuert bei Minute 0, 5, 10, …, 55 jeder Stunde. Der Schritt */N ist relativ zum niedrigsten Wert des Feldes, nicht zur aktuellen Uhrzeit. Speichern Sie um 12:03, läuft der nächste Job um 12:05, nicht um 12:08.

Was bedeutet 0 0 * * * in Cron?

0 0 * * * bedeutet jeden Tag um Mitternacht (00:00) in der lokalen Zeitzone des Servers. Felder: Minute 0, Stunde 0, beliebiger Tag im Monat, beliebiger Monat, beliebiger Wochentag. Entspricht den Makros @daily oder @midnight. Um die Zeitzone zu pinnen, ergänzen Sie CRON_TZ=America/New_York ganz oben in der crontab.

Wie führe ich einen Cron-Job alle 30 Sekunden aus?

Mit Standard-POSIX-Cron geht das nicht: die Mindestgranularität beträgt eine Minute. Drei Workarounds bieten sich an: zwei versetzte Jobs unter * * * * *, einer davon mit sleep 30 &&; ein systemd-Timer mit OnCalendar=*:*:0/30; oder ein langlebiger Worker, der zwischen Iterationen schläft. Die letzte Variante ist meist die richtige.

Welche Zeitzone verwendet Cron standardmäßig?

Die lokale Systemzeitzone des Servers (/etc/timezone oder die Umgebungsvariable TZ). Ein 9-Uhr-Cron auf einem UTC-Server feuert um 4 Uhr US-Ostküste. Lösung: CRON_TZ= oben in der crontab setzen oder Server auf UTC stellen und Zeitpläne in UTC entwerfen. GitHub Actions läuft immer in UTC, Kubernetes 1.27+ unterstützt spec.timeZone.

Warum läuft mein Cron-Job nicht?

Wenn Ihr Cron-Job nicht läuft, prüfen Sie der Reihe nach: Läuft der Cron-Daemon (systemctl status cron)? Ist $PATH in der crontab gesetzt? Wird stderr eingefangen (>> log 2>&1)? Ist die crontab des Nutzers geladen (crontab -l)? Ist % in Befehlen maskiert? Stimmt die Zeitzone mit Ihrer Erwartung überein? Die meisten „läuft nicht”-Meldungen sind der zweite oder dritte Punkt.

Ist die Kubernetes-CronJob-Syntax dieselbe wie Linux-Cron?

Ja für das Schedule-Feld: beide nutzen POSIX-Cron mit fünf Feldern. Kubernetes ergänzt spec.timeZone (1.27+), concurrencyPolicy zur Überlappungskontrolle, startingDeadlineSeconds für die Wiederherstellung verpasster Läufe und suspend: true zum Pausieren. Linux-Cron hat nichts davon, dort greifen Sie zu flock und anacron.

Was ist der Unterschied zwischen @reboot und @daily?

@daily ist ein Makro für 0 0 * * *: jeden Tag um Mitternacht nach festem Zeitplan. @reboot läuft einmal beim Start des Cron-Daemons, ohne wiederkehrenden Zeitplan. @reboot wird von Vixie-Cron und Cronie unterstützt, nicht aber von Kubernetes CronJob, GitHub Actions oder AWS EventBridge. In Containern feuert @reboot selten.

Was ist der Unterschied zwischen cron und crontab?

cron ist der Hintergrund-Daemon, der geplante Jobs ausführt; crontab ist die Datei, die sie auflistet (und der crontab-Befehl zum Bearbeiten dieser Datei). Der Daemon liest die crontab jedes Benutzers in einem Zyklus und führt die Befehle aus, deren Ausführungszeitpunkt dem cron-Ausdruck entspricht. Kurz gesagt: cron ist der Motor, crontab ist das Rezept.

Verwandte Artikel

Alle Artikel anzeigen