Cron Jobs unter Linux – Aufgaben automatisieren mit crontab

Cron Jobs erstellen, planen und verwalten: crontab-Syntax vollständig erklärt, praktische Beispiele für Backups und Monitoring, Logs debuggen und systemd Timer als Alternative.

7 min Lesezeit

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

War dieser Artikel hilfreich?