cron ist der älteste und am weitesten verbreitete Scheduler unter Unix. Ein Daemon liest sogenannte Crontabs, vergleicht sie minütlich mit der aktuellen Uhrzeit und startet Befehle, sobald die Felder passen. Klassische Aufgaben sind Backups, Log-Rotation, Cleanup-Skripte oder regelmäßige Reports. Auf modernen Systemen steht cron neben systemd-Timern — beide haben ihre Berechtigung, aber cron bleibt durch seine Kompaktheit und universelle Verfügbarkeit unverzichtbar.

Was cron macht

cron ist ein Hintergrundprozess, der typischerweise bereits beim Systemstart aktiv wird (crond, cron oder vixie-cron, je nach Distribution). Einmal pro Minute prüft er, ob in einer der hinterlegten Crontabs eine Zeile zu der aktuellen Minute passt, und führt den entsprechenden Befehl aus. Es gibt keine Sub-Minuten-Auflösung — wer alle paar Sekunden etwas tun will, braucht ein anderes Werkzeug.

Klassische Anwendungsfälle:

  • Backups in der Nacht, wenn niemand das System belastet
  • Log-Rotation und Aufräumen alter Dateien
  • Wiederkehrende Reports, etwa Mailversand am Monatsanfang
  • System-Maintenance wie Paket-Cache-Bereinigung oder Datenbank-Vacuum
  • Health-Checks und Monitoring-Skripte alle paar Minuten

Auf modernen Systemen mit systemd gibt es mit systemd-Timern eine Alternative, die mehr Kontrolle bietet (Abhängigkeiten, Logs in journalctl, Recovery nach Ausfall). cron bleibt aber wegen seiner Einfachheit und universellen Verfügbarkeit Standard auf nahezu jeder Linux- und Unix-Maschine.

crontab-Syntax

Eine Cron-Zeile besteht aus fünf Zeitfeldern, gefolgt vom auszuführenden Befehl. Die Reihenfolge ist immer dieselbe und sollte sitzen.

FeldBedeutungErlaubter Bereich
1Minute0 bis 59
2Stunde0 bis 23
3Tag im Monat1 bis 31
4Monat1 bis 12 (oder jan-dec)
5Wochentag0 bis 7 (oder sun-sat, 0 und 7 = Sonntag)
6Befehlbeliebige Shell-Zeile

In jedem Feld sind verschiedene Schreibweisen möglich:

SchreibweiseBedeutungBeispiel
*jeder Wert im Bereich* * * * * = jede Minute
*/nalle n Einheiten*/5 = alle 5 Minuten
a-bBereich von a bis b1-5 = Montag bis Freitag
a,b,cListe konkreter Werte0,15,30,45 = viertelstündlich
a-b/nSchritt innerhalb Range0-30/10 = 0, 10, 20, 30

Eine typische Zeile sieht so aus — ausgeführt jeden Tag um 03:30 Uhr:

Bash Beispiel-Crontab-Zeile
30 3 * * * /home/user/backup.sh

Spezielle Strings

Statt fünf Sterne zu schreiben, lassen sich häufige Schedules mit lesbaren Kürzeln ausdrücken. Das macht eine Crontab auf den ersten Blick verständlicher.

KürzelEntsprichtBedeutung
@rebootEinmal beim Cron-Start nach Boot
@yearly / @annually0 0 1 1 *Jährlich am 1. Januar 00:00
@monthly0 0 1 * *Monatlich am Ersten 00:00
@weekly0 0 * * 0Wöchentlich am Sonntag 00:00
@daily / @midnight0 0 * * *Täglich um Mitternacht
@hourly0 * * * *Zur vollen Stunde

Nicht jede cron-Implementation kennt alle Kürzel — @reboot ist zum Beispiel auf Vixie-cron, ISC-cron und cronie verfügbar, aber nicht auf jedem minimalistischen Embedded-cron.

Eigene crontab — crontab -e

Jeder User hat seine eigene Crontab. Sie wird nicht direkt als Datei bearbeitet, sondern über das Werkzeug crontab, das die Datei nach Speichern validiert.

BefehlWirkung
crontab -eEigene Crontab im $EDITOR öffnen
crontab -lEigene Crontab auflisten
crontab -rEigene Crontab komplett löschen — ohne Rückfrage
crontab -u name -eCrontab eines anderen Users editieren (root)

crontab -r löscht alle Einträge auf einmal und fragt nicht nach. Wer das versehentlich auslöst, hat keinen Backup-Mechanismus. Best Practice: Vorher crontab -l > meine-crontab.bak sichern.

Welcher Editor benutzt wird, steuert die Variable EDITOR (oder VISUAL):

Bash Editor explizit setzen
EDITOR=vim crontab -e

Die intern gespeicherten Crontabs liegen unter /var/spool/cron/crontabs/ (Debian) oder /var/spool/cron/ (Red Hat) — diese Dateien sollten nie direkt editiert werden, da cron sie sonst ignoriert oder neu lädt.

System-Crontabs

Neben den User-Crontabs gibt es System-weite Mechanismen. Sie unterscheiden sich in einem entscheidenden Detail: Vor dem Befehl steht eine User-Spalte, weil das System wissen muss, mit welchen Rechten der Job läuft.

PfadZweckFormat
/etc/crontabZentrale System-Crontab5 Zeitfelder + User + Befehl
/etc/cron.d/Einzeldateien für Pakete und Adminswie /etc/crontab, mit User-Spalte
/etc/cron.hourly/Skripte stündlichnur ausführbare Skripte, keine Cron-Syntax
/etc/cron.daily/Skripte täglichnur Skripte
/etc/cron.weekly/Skripte wöchentlichnur Skripte
/etc/cron.monthly/Skripte monatlichnur Skripte

In den /etc/cron.{hourly,daily,weekly,monthly}/-Verzeichnissen brauchst du keine Cron-Zeile zu schreiben — du legst einfach ein ausführbares Skript ab. cron (oder anacron, siehe nächster Abschnitt) startet es zum entsprechenden Zeitpunkt. Die Reihenfolge richtet sich nach dem Dateinamen, daher sind Präfixe wie 00-cleanup oder 10-backup üblich.

anacron

Klassischer cron geht davon aus, dass das System 24/7 läuft. Auf Servern stimmt das. Auf Laptops oder Workstations, die nachts ausgeschaltet sind, würden Jobs um 03:00 Uhr nie ausgeführt.

anacron löst dieses Problem: Es merkt sich, wann ein Job zuletzt erfolgreich gelaufen ist (in /var/spool/anacron/), und holt versäumte Daily-, Weekly- und Monthly-Jobs nach, sobald das System wieder läuft. Konfiguriert wird das in /etc/anacrontab.

Auf vielen Distributionen (Ubuntu, Fedora) ist anacron so eingebunden, dass cron die cron.daily/cron.weekly/cron.monthly-Verzeichnisse gar nicht direkt ausführt — stattdessen ruft eine cron-Zeile anacron auf, das dann nach Bedarf nachholt. Wer auf einem Laptop nicht versteht, warum die Daily-Jobs nicht zur erwarteten Uhrzeit laufen, findet hier die Erklärung.

Cron-Output und Logs

cron behandelt jeden auf stdout oder stderr ausgegebenen Text als Mail. Wenn ein Job etwas ausgibt, schickt cron eine lokale Mail an den User (über sendmail oder einen anderen MTA). Auf Servern ohne Mail-Setup landet diese Mail nirgends — die Ausgabe geht verloren.

In der Praxis ist das Standard-Pattern: Output explizit selbst loggen.

Bash Job mit Logging
0 3 * * * /home/user/backup.sh >> /var/log/backup.log 2>&1

>> hängt an die Log-Datei an, 2>&1 leitet stderr ebenfalls dort hinein. So sind Erfolgs- und Fehlermeldungen an einer Stelle nachlesbar.

cron selbst loggt seine Aktivität (welcher Job wann gestartet wurde) ins System-Log. Je nach Distribution findest du diese Einträge mit:

Bash cron-Logs prüfen
journalctl -u cron

Auf Systemen ohne systemd liegt das Cron-Log oft in /var/log/syslog oder /var/log/cron.

Cron-Restrictions

Standardmäßig darf jeder User seine eigene Crontab pflegen. Wer das einschränken will, nutzt zwei Dateien:

DateiWirkung
/etc/cron.allowWenn vorhanden: nur gelistete User dürfen crontab -e
/etc/cron.denyWenn vorhanden: gelistete User dürfen nicht

Existiert cron.allow, wird cron.deny ignoriert. Existiert keine der beiden, hängt das Standardverhalten von der Distribution ab — typischerweise dürfen alle User. root ist von beiden Dateien ausgenommen.

Praxis-Patterns

Konkrete Beispiele aus dem Alltag — jeder Block ist erläutert.

Daily-Backup um 3 Uhr, Output in eine Log-Datei umgeleitet, damit nichts an den lokalen MTA geschickt wird:

Bash Tägliches Backup
0 3 * * * /home/user/backup.sh > /var/log/backup.log 2>&1

Beim Boot ein Service-Skript starten — praktisch für User-Services, die nicht über systemd laufen sollen:

Bash Bei Boot ausführen
@reboot /home/user/start-services.sh

Alle 15 Minuten einen Health-Check ausführen. */15 bedeutet: Minute 0, 15, 30, 45 jeder Stunde:

Bash Alle 15 Minuten
*/15 * * * * /usr/local/bin/check.sh

Werktags um 9 Uhr eine Morgenmail verschicken. 1-5 umfasst Montag bis Freitag (Sonntag = 0):

Bash Nur Werktags
0 9 * * 1-5 /usr/local/bin/morning-mail.sh

PATH explizit setzen — als erste Zeilen der Crontab. Cron startet mit minimalem Environment, in dem /usr/local/bin oft fehlt:

Bash Crontab-Header mit Variablen
PATH=/usr/local/bin:/usr/bin:/bin
SHELL=/bin/bash
MAILTO=admin@example.com

Für einmalige Läufe in der Zukunft (zum Beispiel zum Testen) ist at der passendere Befehl — cron ist nur für wiederkehrende Aufgaben gedacht.

Stolperfallen

Cron startet mit minimalem Environment

cron-Jobs laufen nicht mit deiner interaktiven Shell-Umgebung. Es gibt kein ~/.bashrc, kein vollständiges PATH, oft kein HOME im erwarteten Sinne. Das ist die häufigste Ursache für „Mein Skript läuft im Terminal, aber nicht in cron”. Lösung: PATH und andere benötigte Variablen entweder oben in der Crontab setzen oder im Skript selbst per source einlesen. Skripte vorab mit env -i bash -c 'mein-skript.sh' testen — das simuliert das leere cron-Env.

Prozentzeichen sind Newline-Trigger

In einer Crontab-Zeile bedeutet ein nicht-escaptes % einen Zeilenumbruch — alles nach dem ersten % wird als stdin an den Befehl gegeben. Ein date +%Y-%m-%d direkt in der Crontab schlägt fehl. Entweder mit Backslash escapen (\%Y-\%m-\%d) oder den Befehl in ein Skript auslagern, das selber date aufruft. Letzteres ist die robustere Variante.

Wochentag 0 oder 7 = Sonntag — je nach cron

Klassisch akzeptiert cron sowohl 0 als auch 7 für Sonntag. Manche minimalen Implementationen kennen nur 0-6 oder nur 1-7. Wer auf einem ungewöhnlichen System schreibt, sollte das vorher in der Manpage nachsehen — eine Crontab, die auf Linux funktioniert, kann auf BusyBox-cron eines Embedded-Systems still scheitern.

Tag und Wochentag sind ODER, nicht UND

Wenn du sowohl Tag-im-Monat als auch Wochentag setzt, läuft der Job, sobald eine der beiden Bedingungen passt — nicht beide. 0 0 1 * 1 startet am Ersten jedes Monats und an jedem Montag. Wer ausschließlich „Montag, der ein Erster ist” will, kommt mit reiner Cron-Syntax nicht aus und braucht eine if-Prüfung im Skript.

Mail-Output ohne MTA verschwindet

cron versucht, jede Ausgabe per Mail zu verschicken. Auf Servern ohne installierten Mail Transfer Agent (Postfix, sendmail, ssmtp) landen diese Mails im Nirgendwo. Praktischer Effekt: Fehlermeldungen sind unsichtbar, du erfährst nicht, dass ein Job fehlschlägt. Konsequenz: Immer explizit in eine Log-Datei umleiten — >> /var/log/job.log 2>&1 — und das Log regelmäßig sichten oder per Monitoring überwachen.

`crontab -e` als root ist eine andere Crontab

Die Crontab gehört zum jeweiligen User. Wer sudo crontab -e eingibt, editiert die root-Crontab — nicht die eigene. Andersherum: Ein User-Job läuft mit den Rechten des Users, nicht mit root-Rechten. Vor jedem crontab -e lieber whoami ausführen oder crontab -u name -e mit explizitem User verwenden.

`@reboot` läuft nicht bei Container-Restart

@reboot startet den Job, wenn der cron-Daemon anläuft. In Containern ist cron oft gar nicht der Init-Prozess, läuft separat oder gar nicht. Ein Container-Restart ist daher nicht dasselbe wie ein klassischer System-Boot. Wer in Containern Init-artige Tasks braucht, nutzt das Container-eigene Entrypoint-Skript oder einen dedizierten Init wie tini.

Daylight Saving Time verdoppelt oder verschluckt Jobs

Bei der Zeitumstellung kann ein Job, der zwischen 02:00 und 03:00 Uhr terminiert ist, doppelt laufen (Winterzeit-Umstellung) oder gar nicht (Sommerzeit-Umstellung). Klassisches cron hat dagegen keine eingebaute Schutzlogik. Wer DST-immune Schedules braucht, ist mit systemd-Timern (OnCalendar= mit Persistent=true) oder mit fester UTC-Systemzeit besser aufgehoben.

Skripte vor cron-Einsatz mit leerem Env testen

Bevor du ein Skript per cron einplanst, simuliere die cron-Umgebung im Terminal: env -i HOME=$HOME PATH=/usr/bin:/bin bash -c '/pfad/zum/skript.sh'. Wenn es so durchläuft, läuft es auch unter cron. Das spart die typische Schleife aus „in cron einbauen, warten, fehlschlagen, debuggen”.

`crontab.guru` nutzen, aber nicht blind vertrauen

Online-Tools wie crontab.guru sind Gold wert, um komplexe Ausdrücke zu verifizieren. Sie zeigen aber nur die Standard-Vixie-Semantik. Distributionsspezifische Erweiterungen (@reboot-Verhalten, Random-Delays bei anacron, MAILTO-Variablen) sind nicht abgedeckt — im Zweifel die crontab(5)-Manpage des konkreten Systems lesen.

Weiterführende Ressourcen

Externe Quellen

  • at — Einmalige zeitgesteuerte Aufgaben
  • systemd-Timer — Moderne Alternative mit besseren Logs und Recovery
  • Prozess-Modell — Wie Linux-Prozesse aufgebaut sind
  • Shell-Scripting — Skripte schreiben, die cron startet
  • Signale — Prozesse beenden und steuern
/ Weiter

Zurück zu Prozesse & Jobs

Zur Übersicht