Cron Jobs unter Linux – Aufgaben automatisieren mit crontab
Backups um Mitternacht, Logs wöchentlich archivieren, API-Daten stündlich abrufen – all das erledigt cron automatisch. Der Cron-Daemon ist auf jedem Linux-System vorhanden und führt Befehle zu festgelegten Zeitpunkten aus.
Wie Cron funktioniert
Der crond-Daemon (cron daemon) läuft im Hintergrund und prüft jede Minute, ob Jobs ausgeführt werden sollen. Die Zeitpläne werden in crontab-Dateien (cron table) gespeichert.
# Cron-Status prüfen
sudo systemctl status cron # Ubuntu/Debian
sudo systemctl status crond # Fedora/RHEL
# Falls nicht aktiv:
sudo systemctl enable --now cron # Ubuntu/Debian
sudo systemctl enable --now crond # Fedora/RHEL
Crontab-Dateien
| Pfad | Zweck |
|---|---|
crontab -e |
Benutzer-eigene crontab |
/etc/crontab |
System-crontab (mit Benutzer-Feld) |
/etc/cron.d/ |
Einzelne crontab-Dateien (Pakete) |
/etc/cron.hourly/ |
Stündlich ausgeführte Skripte |
/etc/cron.daily/ |
Täglich ausgeführte Skripte |
/etc/cron.weekly/ |
Wöchentlich ausgeführte Skripte |
/etc/cron.monthly/ |
Monatlich ausgeführte Skripte |
crontab-Syntax vollständig erklärt
┌───────── Minute (0–59)
│ ┌─────── Stunde (0–23)
│ │ ┌───── Tag des Monats (1–31)
│ │ │ ┌─── Monat (1–12 oder Jan–Dec)
│ │ │ │ ┌─ Wochentag (0–7, 0 und 7 = Sonntag, oder Sun–Sat)
│ │ │ │ │
* * * * * Befehl
Spezialzeichen
| Zeichen | Bedeutung | Beispiel |
|---|---|---|
* |
Jeder Wert | * * * * * = jede Minute |
, |
Liste | 0,15,30,45 = alle 15 Min |
- |
Bereich | 9-17 = Stunden 9 bis 17 |
/ |
Schritt | */5 = alle 5 Einheiten |
Zeitplan-Beispiele
# Jede Minute
* * * * *
# Täglich um 02:30 Uhr
30 2 * * *
# Montag bis Freitag um 09:00
0 9 * * 1-5
# Jeden ersten des Monats um Mitternacht
0 0 1 * *
# Alle 5 Minuten
*/5 * * * *
# Stündlich (jede volle Stunde)
0 * * * *
# Alle 6 Stunden
0 */6 * * *
# Sonntags um 03:00 Uhr
0 3 * * 0
# Jeden 15. und 30. des Monats um 12:00
0 12 15,30 * *
Kurzformen
@reboot Einmal beim Systemstart
@hourly 0 * * * *
@daily 0 0 * * *
@weekly 0 0 * * 0
@monthly 0 0 1 * *
@yearly 0 0 1 1 *
Tipp: crontab.guru ist ein kostenloses Online-Tool zum Testen von Cron-Ausdrücken.
crontab bearbeiten und verwalten
# Crontab des aktuellen Benutzers bearbeiten
crontab -e
# Crontab anzeigen (ohne zu bearbeiten)
crontab -l
# Crontab löschen (VORSICHT: ohne Bestätigung!)
crontab -r
# Crontab eines anderen Benutzers bearbeiten (als root)
sudo crontab -u max -e
# Crontab-Datei importieren
crontab meine-jobs.txt
# Crontab sichern
crontab -l > ~/crontab-backup-$(date +%Y%m%d).txt
Standard-Editor festlegen
# EDITOR-Variable setzen (für crontab -e)
export EDITOR=nano
# oder dauerhaft in ~/.bashrc:
echo 'export EDITOR=nano' >> ~/.bashrc
Praktische Beispiele
Backup täglich um 02:00
# Crontab-Eintrag:
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
#!/bin/bash
# /usr/local/bin/backup.sh
DATUM=$(date +%Y-%m-%d)
QUELLE="/var/www/meine-app"
ZIEL="/backup/meine-app-${DATUM}.tar.gz"
tar -czf "$ZIEL" "$QUELLE"
echo "$(date): Backup erstellt: $ZIEL"
# Alte Backups löschen (älter als 30 Tage)
find /backup -name "*.tar.gz" -mtime +30 -delete
echo "$(date): Alte Backups bereinigt"
chmod +x /usr/local/bin/backup.sh
Logs täglich komprimieren
0 3 * * * find /var/log/meine-app -name "*.log" -mtime +1 -exec gzip {} \;
Datenbank-Dump
# PostgreSQL Dump täglich
0 1 * * * pg_dump -U postgres meine_db | gzip > /backup/db-$(date +\%Y\%m\%d).sql.gz
# MySQL/MariaDB Dump
0 1 * * * mysqldump -u root -pPASSWORT meine_db | gzip > /backup/db-$(date +\%Y\%m\%d).sql.gz
Wichtig:
%in Cron hat eine Sonderbedeutung (Zeilenumbruch). Im Befehl mit\%escapen!
Festplattenauslastung überwachen
# Alle 6 Stunden: Warnung wenn >80%
0 */6 * * * df -h | awk '$5+0 > 80 {print "WARNUNG: " $0}' | mail -s "Disk Alert" admin@beispiel.de
Skript beim Neustart ausführen
# Beim Boot
@reboot /opt/meine-app/start.sh
# Beim Boot mit Verzögerung (60 Sekunden warten)
@reboot sleep 60 && /opt/meine-app/start.sh
Let's Encrypt Zertifikate erneuern
# Certbot bietet das automatisch an, aber manuell:
0 2 * * 1 certbot renew --quiet && systemctl reload nginx
Ausgabe und Fehler behandeln
Standardmäßig sendet Cron die Ausgabe per E-Mail an den Benutzer. Das ist auf den meisten Servern nicht erwünscht.
Ausgabe in Log-Datei umleiten
# stdout und stderr in Log-Datei
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
# stdout in Log, stderr ignorieren
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>/dev/null
# Alles unterdrücken (keine Ausgabe, keine Mail)
0 2 * * * /usr/local/bin/backup.sh > /dev/null 2>&1
Mit Zeitstempel loggen
# In der crontab:
0 2 * * * echo "[$(date '+%Y-%m-%d %H:%M:%S')] Start" >> /var/log/job.log && \
/usr/local/bin/mein-job.sh >> /var/log/job.log 2>&1 && \
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Ende" >> /var/log/job.log
MAILTO: E-Mail konfigurieren
# Am Anfang der crontab:
# E-Mail-Adresse für Ausgaben
MAILTO="admin@beispiel.de"
# E-Mail komplett deaktivieren
MAILTO=""
Umgebungsvariablen in Cron
Cron startet mit einer minimalen Umgebung (kein ~/.bashrc):
# In der crontab explizit setzen:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME=/home/andre
SHELL=/bin/bash
# Oder im Skript selbst laden:
#!/bin/bash
source /home/andre/.bashrc
System-Cron in /etc/cron.*
Für systemweite Jobs gibt es vorgefertigte Verzeichnisse. Einfach ausführbares Skript hineinlegen:
# Täglich ausgeführt (von root)
sudo cp mein-job.sh /etc/cron.daily/
sudo chmod 755 /etc/cron.daily/mein-job.sh
# Wöchentlich
sudo cp mein-job.sh /etc/cron.weekly/
# Manuell testen
sudo run-parts /etc/cron.daily
Regeln für Skripte in /etc/cron.*:
- Keine Dateiendung (kein
.sh!) auf manchen Systemen - Ausführbar (
chmod +x) - Als root ausgeführt
- Ausgabe geht an root-E-Mail
/etc/crontab (System-crontab)
sudo nano /etc/crontab
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.daily ; }
# Eigener Eintrag mit Benutzer-Feld:
0 2 * * * deploy /opt/meine-app/backup.sh
Cron debuggen
Cron-Logs prüfen
# Ubuntu/Debian: syslog
grep CRON /var/log/syslog | tail -20
# Oder journalctl
journalctl -u cron --since "1 hour ago"
journalctl -u crond --since today # Fedora
# Alle Cron-Aktivitäten heute
journalctl -u cron --since today | grep -E "CMD|session"
Skript manuell testen
# Direkt als der Benutzer ausführen (prüft Berechtigungen)
sudo -u andre /usr/local/bin/mein-skript.sh
# Mit der Cron-Umgebung simulieren (minimale env)
env -i HOME=/home/andre LOGNAME=andre USER=andre SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin /bin/bash -l -c '/usr/local/bin/mein-skript.sh'
Häufige Debug-Schritte
# 1. Skript manuell ausführbar?
bash /usr/local/bin/backup.sh
# 2. Cron-Daemon läuft?
sudo systemctl status cron
# 3. Crontab korrekt?
crontab -l
# 4. Log-Ausgabe prüfen
tail -f /var/log/backup.log
# 5. Skript in 2 Minuten ausführen lassen (Test)
# Aktuelle Zeit + 2 Minuten in crontab eintragen:
date # Aktuelle Zeit notieren
# crontab -e → z.B. 35 14 * * * /usr/local/bin/test.sh >> /tmp/test.log 2>&1
systemd Timer als Alternative
Für neue Projekte sind systemd Timer oft die bessere Wahl:
| Kriterium | Cron | systemd Timer |
|---|---|---|
| Verfügbarkeit | überall | nur systemd-Systeme |
| Logging | syslog (begrenzt) | journald (vollständig) |
| Abhängigkeiten | keine | ja (After=, Requires=) |
| Verpasste Jobs | nein | ja (Persistent=true) |
| Komplexität | einfach | höher |
| Granularität | 1 Minute | beliebig (ms) |
# Beispiel-Timer (täglich um 02:00)
# /etc/systemd/system/backup.timer
[Unit]
Description=Tägliches Backup
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true # Nachholen wenn System aus war
[Install]
WantedBy=timers.target
→ Vollständige Erklärung: systemd verstehen – Services, Timer und Logs
Häufige Fehler
Job läuft nicht zur geplanten Zeit
# Cron aktiv?
sudo systemctl status cron
# Syntax-Check mit crontab.guru
# Zeitzone prüfen (Cron nutzt Systemzeit)
timedatectl
date
Befehl funktioniert im Terminal, nicht in Cron
Ursache: Cron hat minimale Umgebung (kein $PATH, kein $HOME).
# Absolute Pfade nutzen statt relative
0 2 * * * /usr/bin/python3 /opt/meine-app/job.py
# PATH explizit setzen
PATH=/usr/local/bin:/usr/bin:/bin
0 2 * * * mein-befehl
% im Befehl wird zu Zeilenumbruch
# Falsch:
0 0 * * * echo "Datum: $(date +%Y-%m-%d)"
# Richtig (% escapen):
0 0 * * * echo "Datum: $(date +\%Y-\%m-\%d)"
# Oder: Skript nutzen statt direkten Befehl
Kein Mail-Agent vorhanden
Wenn Cron Output produziert und kein MTA installiert ist, erscheint:
(CRON) info (No MTA installed, discarding output)
Lösung: > /dev/null 2>&1 am Ende jedes Jobs oder MAILTO="" setzen.
Fazit
Cron ist ein unverzichtbares Werkzeug für jede Linux-Administration. Die Syntax ist kompakt, aber nach kurzer Eingewöhnung intuitiv.
Kurzreferenz:
crontab -e # Jobs bearbeiten
crontab -l # Jobs anzeigen
crontab -l > backup # Jobs sichern
# Syntax: Min Std Tag Mon Wtag Befehl
*/5 * * * * /pfad/zu/skript.sh >> /var/log/job.log 2>&1