01

Was ist Cron?

Cron ist der klassische Unix-Daemon für zeitgesteuerte Aufgaben — der stille Automatisierer im Hintergrund, der seit den 1970ern läuft und auf jedem Linux-System vorhanden ist. Der Name stammt vom griechischen Chronos (Zeit). Cron liest beim Start und bei Änderungen sogenannte Crontabs (Cron-Tabellen) und führt darin definierte Befehle zu exakt festgelegten Zeitpunkten aus.

Der Daemon selbst heißt je nach Distribution crond (Red Hat/CentOS) oder cron (Debian/Ubuntu). Er wacht im Hintergrund, prüft jede Minute die Crontab-Einträge und startet fällige Jobs als eigene Prozesse.

Daemon

Läuft dauerhaft im Hintergrund als Systemdienst. Startet automatisch beim Booten.

systemctl status cron
Crontab

Textdatei mit Zeitplan-Einträgen. Pro User eine eigene, plus systemweite Varianten.

/var/spool/cron/crontabs/
Auflösung

Minimale Zeitauflösung: 1 Minute. Für Sub-Minuten-Tasks → systemd-timer oder at.

min-granularity: 60s
Anacron

Ergänzung zu Cron für Rechner, die nicht 24/7 laufen — holt verpasste Jobs nach.

/etc/anacrontab
ℹ️
Cron vs. systemd-timer: Moderne Ubuntu-Systeme nutzen zunehmend systemd.timer Units als Cron-Ersatz — mehr Logging, genauere Zeitsteuerung, Dependencies möglich. Cron bleibt aber das universelle Standardwerkzeug, das überall funktioniert.
02

Syntax & Felder

Jede Zeile in einer Crontab folgt demselben Schema: fünf Zeitfelder, gefolgt vom auszuführenden Befehl. Die Reihenfolge ist unveränderlich und muss auswendig sitzen — sie ist das A und O der Cron-Nutzung.

* Minute 0–59
* Stunde 0–23
* Tag (Monat) 1–31
* Monat 1–12
* Wochentag 0–7 (0=So)
/pfad/befehl Befehl / Script absoluter Pfad empfohlen
⚠️
Merkhilfe: Minute · Hour · Day · Month · Weekday → "Make Hell, Do More Work" oder einfach: m h dom mon dow wie in crontab -e angezeigt.
FeldNameWertebereichBesonderheit
1 Minute 0–59 0 = genau zur vollen Minute
2 Stunde 0–23 0 = Mitternacht
3 Day of Month 1–31 Achtung bei Monaten mit <31 Tagen
4 Month 1–12 Auch Namen: jandec
5 Day of Week 0–7 0 und 7 = Sonntag; auch monsun
⚠️
Fallstrick: Wenn sowohl dom als auch dow angegeben sind (beide nicht *), führt Cron den Job aus, wenn einer der beiden Bedingungen erfüllt ist — ODER-Logik, nicht UND. Das ist kontraintuitiv und ein häufige Fehlerquelle.
03

Sonderzeichen

Die fünf Zeitfelder unterstützen Sonderzeichen für flexible Zeitangaben. Kombiniert ermöglichen sie nahezu jedes denkbare Intervall.

ZeichenBedeutungBeispielErklärung
* Wildcard / Jeder Wert * * * * * Jede Minute
, Liste / Mehrere Werte 0 8,12,18 * * * Um 8:00, 12:00 und 18:00 Uhr
- Bereich 0 9-17 * * * Stündlich von 9 bis 17 Uhr
/ Schrittweite */15 * * * * Alle 15 Minuten
@reboot Beim Systemstart @reboot /pfad/script.sh Einmalig nach jedem Boot
@hourly Stündlich @hourly /pfad/script.sh Äquivalent zu 0 * * * *
@daily Täglich Mitternacht @daily /pfad/script.sh Äquivalent zu 0 0 * * *
@weekly Wöchentlich @weekly /pfad/script.sh Äquivalent zu 0 0 * * 0 (Sonntag)
@monthly Monatlich @monthly /pfad/script.sh Äquivalent zu 0 0 1 * *
@yearly Jährlich @yearly /pfad/script.sh Äquivalent zu 0 0 1 1 *

Kombination von Sonderzeichen

CRON — Komplexe Ausdrücke # Alle 5 Minuten zwischen 9 und 18 Uhr, Mo–Fr */5 9-18 * * 1-5 /opt/check.sh # Am 1. und 15. jeden Monats um 3:30 Uhr 30 3 1,15 * * /opt/backup.sh # Jeden Werktag um 7:45 Uhr 45 7 * * 1-5 /opt/morning.sh

Tipp: Online-Tools

Cron-Ausdrücke lassen sich schnell mit Tools wie crontab.guru validieren — gibt den Ausdruck in Klartext aus und zeigt die nächsten Ausführungszeitpunkte.

crontab.guru — de facto Standard für Cron-Expression-Testing. Kostenfrei, keine Anmeldung.
04

crontab verwalten

Jeder Linux-User hat seine eigene Crontab, die unabhängig von anderen Usern läuft. Der crontab-Befehl ist das einzige empfohlene Interface dafür — direkte Dateibearbeitung in /var/spool/cron/crontabs/ wird nicht empfohlen, weil Cron die Datei cachen kann.

BASH — crontab Befehle # Crontab des aktuellen Users im Editor öffnen crontab -e # Öffnet $EDITOR (meist nano oder vi) mit der aktuellen Crontab # Crontab des aktuellen Users anzeigen crontab -l # Crontab eines bestimmten Users anzeigen (nur root) sudo crontab -u www-data -l # Crontab eines bestimmten Users bearbeiten (nur root) sudo crontab -u www-data -e # Aktuelle Crontab löschen (Vorsicht!) crontab -r # Crontab aus Datei importieren crontab /pfad/zur/meiner_crontab.txt # Aktuelle Crontab in Datei exportieren (Backup) crontab -l > ~/crontab_backup.txt
⚠️
Kein sudo in der User-Crontab: Die User-Crontab läuft mit den Rechten des Users. Braucht ein Job Root-Rechte, muss er in die Root-Crontab (sudo crontab -e) oder via sudo in einem Script aufgerufen werden — wobei NOPASSWD in /etc/sudoers nötig ist, da kein interaktives Terminal vorhanden ist.

Editor konfigurieren

BASH — Standard-Editor setzen # Für die aktuelle Shell-Session export EDITOR=nano # Dauerhaft in ~/.bashrc oder ~/.profile eintragen echo 'export EDITOR=nano' >> ~/.bashrc # Alternativ: select-editor (Debian/Ubuntu) select-editor
05

Praxisbeispiele

Cronjobs decken ein breites Spektrum ab — von simplen Backup-Skripten bis hin zu komplexen Wartungsroutinen. Hier die wichtigsten Anwendungsfälle mit vollständigen Einträgen.

Backup-Aufgaben

CRONTAB — Backup-Beispiele # Täglich um 2:00 Uhr: MySQL-Dump mit Datum im Dateinamen 0 2 * * * mysqldump -u root -pPASSWORD mydb > /backup/db_$(date +\%Y\%m\%d).sql # Wichtig: % muss mit \ escaped werden in Crontabs! # Alternativ: Script aufrufen (sauberer) 0 2 * * * /opt/scripts/backup_db.sh # Stündliches rsync-Backup von /var/www auf externen Pfad 0 * * * * rsync -az --delete /var/www/ /mnt/backup/www/ # Alte Backups löschen (älter als 30 Tage) 0 3 * * * find /backup/ -name "*.sql" -mtime +30 -delete

System-Wartung

CRONTAB — Wartungsroutinen # Jeden Sonntag um 4:00 Uhr: apt upgrade (Ubuntu/Debian) 0 4 * * 0 apt-get update -qq && apt-get upgrade -y -qq # Logrotation manuell anstoßen (normalerweise via anacron) 0 6 * * * /usr/sbin/logrotate /etc/logrotate.conf # Temp-Dateien älter als 7 Tage löschen 0 1 * * * find /tmp -type f -mtime +7 -delete # Disk-Usage überwachen und bei >90% E-Mail senden */30 * * * * /opt/scripts/check_disk.sh

Web-Anwendungen / Laravel

CRONTAB — Laravel Scheduler # Laravel Scheduler: jede Minute aufrufen, der Rest läuft intern * * * * * cd /var/www/myapp && php artisan schedule:run >> /dev/null 2>&1 # Laravel Queue Worker (als Alternative zu supervisor) @reboot cd /var/www/myapp && php artisan queue:work --daemon >> /var/log/queue.log 2>&1 & # Cache jeden Tag um Mitternacht leeren 0 0 * * * cd /var/www/myapp && php artisan cache:clear

Monitoring & Benachrichtigungen

CRONTAB — Monitoring # Alle 5 Minuten: Website-Erreichbarkeit prüfen */5 * * * * curl -sf https://example.com > /dev/null || echo "SITE DOWN" | mail -s "Alert" [email protected] # Täglich: System-Report generieren und versenden 0 7 * * * /opt/scripts/daily_report.sh | mail -s "Daily Report $(date +\%Y-\%m-\%d)" [email protected]
⚠️
Prozent-Zeichen escapen: In Crontab-Befehlen wird % als Zeilenumbruch interpretiert. Für date +%Y muss es als date +\%Y geschrieben werden — oder das ganze Script in eine separate Datei auslagern, wo % normal funktioniert.
06

Umgebungsvariablen

Einer der häufigsten Fehlerquellen bei Cronjobs: Das Script funktioniert im Terminal, schlägt aber als Cronjob fehl. Der Grund ist fast immer die abgespeckte Cron-Umgebung. Cron startet Jobs mit einer minimalen Shell-Umgebung — kein ~/.bashrc, kein ~/.profile, minimaler $PATH.

CRONTAB — Umgebungsvariablen definieren # Am Anfang der Crontab: Variablen setzen SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin [email protected] HOME=/home/doz # Danach folgen die eigentlichen Cron-Einträge 0 2 * * * /opt/scripts/backup.sh
VariableFunktionTypischer Wert
SHELL Shell für Befehlsausführung /bin/bash
PATH Suchpfad für ausführbare Dateien /usr/local/bin:/usr/bin:/bin
MAILTO Empfänger für Cron-Output (leer = kein Mail) [email protected] oder ""
HOME Home-Verzeichnis des Users /home/username
LANG Spracheinstellung / Zeichensatz de_DE.UTF-8

Debugging-Tipp: Umgebung prüfen

BASH — Cron-Umgebung ausgeben lassen # Temporären Job eintragen, der Umgebung in Datei schreibt * * * * * env > /tmp/cron_environment.txt # Nach 1 Minute Datei prüfen cat /tmp/cron_environment.txt # Danach Zeile wieder entfernen
Best Practice: Immer absolute Pfade für alle Befehle und Scripts verwenden (/usr/bin/php statt php), auch wenn $PATH gesetzt ist. Damit sind Cronjobs unabhängig von der Umgebungskonfiguration.
07

Ausgabe & Logging

Standardmäßig sendet Cron die Ausgabe eines Jobs per E-Mail an den ausführenden User. Auf Servern ohne Mailserver landet das im System-Maillog und kann sich aufstauen. Sauberes Output-Handling ist daher essenziell.

CRONTAB — Output-Umleitung # Alle Ausgaben (stdout + stderr) verwerfen 0 2 * * * /opt/backup.sh > /dev/null 2>&1 # Nur Fehler (stderr) in Logdatei schreiben, stdout verwerfen 0 2 * * * /opt/backup.sh > /dev/null 2>> /var/log/cron_errors.log # Alles in Logdatei schreiben (überschreiben bei jedem Lauf) 0 2 * * * /opt/backup.sh > /var/log/backup.log 2>&1 # Alles anhängen (kumulativ) — Achtung: Datei wächst unbegrenzt! 0 2 * * * /opt/backup.sh >> /var/log/backup.log 2>&1 # Mit Timestamp versehen (nützlich für Debugging) 0 2 * * * echo "[$(date)] Starting backup" >> /var/log/backup.log && /opt/backup.sh >> /var/log/backup.log 2>&1

System-Cron-Log prüfen

BASH — Cron-Aktivität überwachen # Cron-Einträge im Syslog (Ubuntu/Debian) grep CRON /var/log/syslog | tail -20 # Dediziertes Cron-Log (falls vorhanden) cat /var/log/cron.log # Mit journald (systemd-Systeme) journalctl -u cron --since "1 hour ago" # Live-Monitoring tail -f /var/log/syslog | grep CRON
ℹ️
MAILTO="" deaktiviert E-Mails komplett für alle Jobs in der Crontab. Alternativ kann MAILTO="" auch als Inline-Variable vor einem einzelnen Job gesetzt werden, um nur diesen Job stumm zu schalten.
08

System-Crontabs

Neben den User-Crontabs gibt es systemweite Cron-Konfigurationen, die von Root verwaltet werden und spezielle Strukturen bieten.

/etc/crontab

Die systemweite Crontab mit einem zusätzlichen User-Feld nach den Zeitfeldern. Hier wird explizit angegeben, als welcher User der Job läuft.

FORMAT — /etc/crontab # m h dom mon dow USER cmd 0 6 * * * root /opt/system_check.sh 30 7 * * 1 www-data /opt/weekly_report.sh

/etc/cron.d/

Verzeichnis für zusätzliche Crontab-Dateien. Gleiche Syntax wie /etc/crontab mit User-Feld. Wird von Paketen genutzt (z.B. legt php dort eigene Einträge ab).

BASH — cron.d Dateien ls /etc/cron.d/ php postfix logrotate cat /etc/cron.d/php

Drop-In-Verzeichnisse

VerzeichnisAusführungZweck
/etc/cron.hourly/ Stündlich Scripts werden stündlich ausgeführt (via run-parts)
/etc/cron.daily/ Täglich Tägliche Maintenance-Scripts (logrotate, etc.)
/etc/cron.weekly/ Wöchentlich Wöchentliche Bereinigungen und Reports
/etc/cron.monthly/ Monatlich Monatliche Archivierung und Statistiken
ℹ️
run-parts: Cron ruft diese Verzeichnisse über run-parts auf. Dabei werden nur ausführbare Dateien ohne Dateiendung oder mit spezifisch erlaubten Endungen ausgeführt. Dateien mit einem Punkt im Namen (z.B. backup.sh) werden von einigen run-parts-Versionen ignoriert — Dateinamen ohne .sh sind sicherer.
09

Anacron

Anacron ist die Lösung für das zentrale Problem von Cron: Wenn ein Rechner zum geplanten Zeitpunkt ausgeschaltet ist, verfällt der Job einfach. Anacron merkt sich, wann ein Job zuletzt ausgeführt wurde, und holt ihn beim nächsten Start nach — ideal für Laptops, Desktop-PCs und Systeme ohne 24/7-Uptime.

FILE — /etc/anacrontab # Format: Periode Delay(min) Job-ID Befehl # Periode: 1=täglich, 7=wöchentlich, 30=monatlich, @monthly SHELL=/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root # Täglich, 5 Minuten nach Start: cron.daily ausführen 1 5 cron.daily run-parts /etc/cron.daily # Wöchentlich, 10 Minuten nach Start: cron.weekly ausführen 7 10 cron.weekly run-parts /etc/cron.weekly # Monatlich, 15 Minuten nach Start: cron.monthly ausführen @monthly 15 cron.monthly run-parts /etc/cron.monthly

Anacron vs. Cron

EigenschaftCronAnacron
Sub-Tages-Intervalle✔ Ja✘ Nein
Nachholung verpasster Jobs✘ Nein✔ Ja
Läuft als User✔ JaNur root
Minutengenaue Planung✔ Ja✘ Nein

Anacron Status prüfen

BASH — Anacron # Installiert? which anacron /usr/sbin/anacron # Letzte Ausführungen ls -la /var/spool/anacron/ # Manuell ausführen (Testlauf) anacron -n -d
10

Fehlerdiagnose

Cronjobs schweigen standardmäßig — kein Fenster, kein Feedback, kein Fehler-Popup. Debugging erfordert systematisches Vorgehen.

SCHRITT 1 — Log prüfen: grep CRON /var/log/syslog | tail -30 zeigt, ob der Job überhaupt gestartet wurde. "CMD" = gestartet, kein Eintrag = Zeitausdruck falsch oder Cron läuft nicht.
SCHRITT 2 — Script manuell testen: Script direkt als der User ausführen, der in der Crontab definiert ist. Funktioniert das? Dann weiter zu Schritt 3.
SCHRITT 3 — Cron-Umgebung simulieren: env -i HOME=/root SHELL=/bin/bash /pfad/script.sh simuliert die minimale Cron-Umgebung. Schlägt das fehl? → PATH oder fehlende Variablen.
SCHRITT 4 — Output umleiten: Temporär >> /tmp/debug.log 2>&1 anhängen und Log nach dem nächsten Run prüfen.
SCHRITT 5 — Berechtigungen prüfen: Script muss ausführbar sein: chmod +x /pfad/script.sh. User muss Leserecht auf alle benötigten Dateien haben.

Häufige Fehlerquellen

ProblemUrsacheLösung
Job läuft nie Zeitausdruck falsch Ausdruck auf crontab.guru prüfen
command not found $PATH zu kurz Absolute Pfade verwenden (/usr/bin/php)
Script schlägt fehl Umgebungsvariablen fehlen Variablen im Script oder Crontab-Kopf setzen
Permission denied Script nicht ausführbar chmod +x script.sh
Relative Pfade scheitern Arbeitsverzeichnis = $HOME, nicht Script-Dir cd /pfad/zum/script && ./script.sh
% im Befehl bricht ab % ist Sonderzeichen in Crontab \% escapen oder in Script auslagern
Cron startet nie Cron-Daemon nicht aktiv systemctl start cron
BASH — Cron-Daemon prüfen # Status des Cron-Daemons systemctl status cron ● cron.service - Regular background program processing daemon Loaded: loaded (/lib/systemd/system/cron.service; enabled) Active: active (running) since ... # Cron starten/neustarten sudo systemctl start cron sudo systemctl restart cron # Autostart bei Boot aktivieren sudo systemctl enable cron
11

Sicherheit

Cronjobs laufen unbeaufsichtigt — eine unsichere Konfiguration ist schwerer zu entdecken als bei interaktiven Prozessen. Besonders Root-Cronjobs und World-Writable-Scripts sind kritische Angriffsvektoren.

Minimale Rechte

Jobs immer mit dem User ausführen, der die minimal nötigen Rechte hat. Root-Crontabs nur wenn zwingend erforderlich.

Script-Permissions

Scripts in Crontabs dürfen nicht world-writable sein. Angreifer könnten sonst fremden Code einschleusen, der als Root läuft.

Absolute Pfade

Immer absolute Pfade verwenden — verhindert PATH-Hijacking-Angriffe, bei denen ein böswilliger bash-Binary im $PATH landet.

Zugriffsbeschränkung

/etc/cron.allow und /etc/cron.deny steuern, welche User Crontabs anlegen dürfen.

BASH — Sicherheits-Checks # Script-Permissions prüfen: Nicht world-writable? ls -la /opt/scripts/backup.sh -rwxr-x--- 1 root root 542 May 5 12:00 backup.sh # Richtig: nur Owner (root) hat Schreibrecht # Crontab-Zugriff einschränken: nur bestimmte User erlauben echo "doz" | sudo tee /etc/cron.allow # Wenn cron.allow existiert, dürfen NUR die genannten User crontab nutzen # Alle aktiven Crontabs anzeigen (als root) for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l 2>/dev/null && echo "--- $user ---"; done
🚨
Privilege Escalation via Cron: Ein klassischer Angriffspunkt in CTF-Challenges und realen Compromises: Root-Cronjob ruft ein Script auf, das world-writable ist → Angreifer ersetzt Script-Inhalt → nächster Cron-Lauf führt beliebigen Code als Root aus. Alle von Root aufgerufenen Scripts und deren Verzeichnisse müssen chmod 700 oder 750 haben.

cron.allow / cron.deny Logik

ZustandVerhalten
/etc/cron.allow existiert Nur User in dieser Datei dürfen crontab nutzen
/etc/cron.deny existiert (kein allow) Alle User außer den genannten dürfen crontab nutzen
Keine Datei existiert Alle User dürfen crontab nutzen (Default auf Ubuntu)
Beide Dateien existieren cron.allow hat Vorrang, cron.deny wird ignoriert