Cron Jobs – Automatisierung unter Linux
Cron ist der Standard-Aufgabenplaner unter Linux. Lerne Syntax, Praxisbeispiele, Logging und Troubleshooting für den IT-Allrounder-Alltag.
Was ist Cron?
Cron ist der klassische Aufgabenplaner unter Linux – das Gegenstück zum Windows Task Scheduler. Er wird als Daemon (crond bzw. cron) im Hintergrund ausgeführt und prüft jede Minute, ob ein geplanter Job ausgeführt werden muss.
Typische Anwendungsfälle in einem KMU:
- Nächtliche Backups auf NAS oder Cloud
- Log-Rotation und Bereinigung alter Dateien
- Überwachungsskripte (Festplattenplatz, Dienste prüfen)
- Berichte automatisch generieren und per Mail verschicken
- Datenbank-Dumps vor Updates
- Zertifikate erneuern (z.B. Let’s Encrypt via Certbot)
Cron ist auf praktisch jeder Linux-Distribution vorinstalliert. Auf modernen Systemen gibt es daneben auch systemd-Timer als Alternative – aber Cron ist einfacher, breiter bekannt und für die meisten Aufgaben mehr als ausreichend.
Crontab bearbeiten
Jeder Linux-User hat seine eigene Crontab (Cron-Tabelle). Die zentrale Anlaufstelle ist der Befehl crontab:
crontab -e # Eigene Crontab im Editor öffnen (erstellt sie, falls nicht vorhanden)
crontab -l # Aktuelle Crontab anzeigen
crontab -r # Eigene Crontab löschen (Vorsicht – ohne Rückfrage!)
sudo crontab -e # Root-Crontab bearbeiten
crontab -u seya -l # Crontab eines bestimmten Users anzeigen (als Root)
Beim ersten Aufruf von crontab -e wirst du nach einem Editor gefragt. nano ist für Einsteiger am bequemsten.
Die Crontab-Syntax
Der wichtigste Teil: Das Zeitformat. Jede Zeile in der Crontab hat diese Struktur:
* * * * * /pfad/zum/befehl
│ │ │ │ │
│ │ │ │ └── Wochentag (0–7, 0 und 7 = Sonntag)
│ │ │ └──── Monat (1–12)
│ │ └────── Tag im Monat (1–31)
│ └──────── Stunde (0–23)
└────────── Minute (0–59)
Sonderzeichen
| Zeichen | Bedeutung | Beispiel |
|---|---|---|
* | Jeder Wert | * * * * * = jede Minute |
*/n | Alle n Einheiten | */15 = alle 15 Minuten |
n-m | Bereich | 8-17 = 08:00 bis 17:00 |
n,m,k | Liste | 1,15,30 = um Minute 1, 15 und 30 |
Praktische Beispiele
# Täglich um 02:00 Uhr Backup-Skript ausführen
0 2 * * * /opt/scripts/backup.sh
# Jeden Montag um 08:00 Wochenbericht erstellen
0 8 * * 1 /opt/scripts/wochenbericht.sh
# Alle 5 Minuten einen Monitoring-Check
*/5 * * * * /opt/scripts/check-dienste.sh
# Stündlich (immer zur vollen Stunde)
0 * * * * /opt/scripts/cleanup-tmp.sh
# Jeden Werktag (Mo–Fr) um 07:30
30 7 * * 1-5 /opt/scripts/tageskonfiguration.sh
# Am 1. jeden Monats um 03:00
0 3 1 * * /opt/scripts/monatsbericht.sh
# Jeden Sonntag um 22:00 den Server neu starten
0 22 * * 0 /sbin/reboot
# Beim Systemstart (nach Reboot)
@reboot /opt/scripts/startup.sh
Kurzformen mit @
Cron kennt auch sprechende Kurzformen:
| Kurzform | Entspricht | Bedeutung |
|---|---|---|
@reboot | — | Einmal beim Systemstart |
@hourly | 0 * * * * | Jede Stunde |
@daily / @midnight | 0 0 * * * | Täglich um Mitternacht |
@weekly | 0 0 * * 0 | Wöchentlich, Sonntag Mitternacht |
@monthly | 0 0 1 * * | Monatlich, 1. des Monats |
@yearly / @annually | 0 0 1 1 * | Jährlich, 1. Januar |
CRON_TZ – Zeitzone pro Job steuern
Standardmässig laufen alle Jobs in der Zeitzone des Systems (timedatectl zeigt sie an). Bei Servern mit UTC-Systemzeit oder wenn du Jobs für Kunden in anderen Zeitzonen planst, brauchst du mehr Kontrolle. Moderne Cron-Implementierungen (Vixie-Cron/cronie, wie sie auf praktisch allen aktuellen Linux-Distributionen laufen) unterstützen dafür die Variable CRON_TZ.
CRON_TZ wird wie MAILTO oder PATH als Zuweisung in der Crontab gesetzt und gilt ab dort für alle folgenden Zeilen – bis sie erneut gesetzt wird. Damit lässt sich pro Job-Block effektiv eine eigene Zeitzone definieren:
# Bericht für die Schweizer Zentrale
CRON_TZ=Europe/Zurich
0 8 * * * /opt/scripts/bericht-ch.sh
# Ab hier gilt eine andere Zeitzone für die US-Niederlassung
CRON_TZ=America/New_York
30 9 * * * /opt/scripts/bericht-us.sh
Wichtig zu verstehen: CRON_TZ beeinflusst nur, wann der Job ausgelöst wird – nicht, welche Zeitzone das Skript selbst sieht. Ein date-Aufruf im Skript liefert weiterhin die Systemzeitzone. Willst du auch das steuern, setzt du TZ direkt vor dem Befehl (funktioniert, weil Cron den Befehl über /bin/sh -c ausführt und die Shell diese Inline-Zuweisung unterstützt):
0 8 * * * TZ=Europe/Zurich /opt/scripts/bericht-ch.sh
Systemweite Cron-Verzeichnisse
Neben den persönlichen Crontabs gibt es systemweite Verzeichnisse. Skripte, die du dort ablegst, werden automatisch zur entsprechenden Zeit ausgeführt – ohne expliziten Cron-Eintrag:
/etc/cron.hourly/ # Stündlich
/etc/cron.daily/ # Täglich
/etc/cron.weekly/ # Wöchentlich
/etc/cron.monthly/ # Monatlich
Skripte in diesen Verzeichnissen brauchen keinen Shebang-Zeitplan, müssen aber ausführbar sein:
# Skript ablegen und ausführbar machen
sudo cp mein-cleanup.sh /etc/cron.daily/
sudo chmod +x /etc/cron.daily/mein-cleanup.sh
Die systemweite Crontab /etc/crontab hat eine zusätzliche Spalte für den ausführenden User:
# /etc/crontab – Systemweite Crontab
# m h dom mon dow user command
0 2 * * * root /opt/scripts/backup.sh
30 6 * * 1-5 deploy /opt/app/deploy-check.sh
cron.allow und cron.deny – Wer darf Cron überhaupt nutzen?
Auf Mehrbenutzer-Systemen willst du eventuell steuern, welche User überhaupt eigene Crontabs anlegen dürfen – etwa damit Praktikanten- oder Service-Accounts keine eigenen Jobs einrichten können. Dafür prüft der Befehl crontab beim Aufruf zwei Dateien:
| Situation | Wer darf crontab benutzen |
|---|---|
Nur /etc/cron.allow existiert | Nur die dort gelisteten User (root immer) |
Nur /etc/cron.deny existiert | Alle ausser den dort gelisteten Usern |
| Beide Dateien existieren | cron.allow gewinnt, cron.deny wird ignoriert |
| Keine der beiden Dateien existiert | Distro-abhängig – siehe Hinweis unten |
Format ist simpel: ein Username pro Zeile.
# /etc/cron.allow
seya
deploy
backup-service
# /etc/cron.deny
praktikant
gast-account
Auf einem restriktiven System reicht meist eine cron.allow mit den paar Accounts, die tatsächlich eigene Jobs brauchen:
echo -e "seya\ndeploy\nbackup-service" | sudo tee /etc/cron.allow
Wichtig: cron.allow/cron.deny steuern nur, wer den Befehl crontab benutzen darf. Sie verhindern nicht, dass bereits eingetragene Jobs in /etc/crontab oder /etc/cron.d/ laufen – diese Dateien darf ohnehin nur root bearbeiten.
Output, Logging und Mail
Standardmässig sendet Cron die Ausgabe jedes Jobs per E-Mail an den ausführenden User – was auf Servern ohne Mail-Daemon zu Fehlern führt. Besser: Output explizit umleiten.
# Ausgabe (stdout + stderr) in Logdatei schreiben
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
# Fehler separat loggen
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>> /var/log/backup-errors.log
# Komplett unterdrücken (nur wenn du sicher bist, dass nichts schiefgeht)
0 2 * * * /opt/scripts/backup.sh > /dev/null 2>&1
MAILTO: Mail-Benachrichtigungen steuern
Am Anfang der Crontab kannst du das Verhalten für alle Jobs steuern:
# Alle Mails unterdrücken
MAILTO=""
# Mails an eine bestimmte Adresse senden
MAILTO="admin@firma.ch"
Umgebungsvariablen in Cron
Das ist der häufigste Stolperstein: Cron startet Jobs mit einer minimalen Umgebung. Deine ~/.bashrc oder ~/.profile wird nicht geladen. Das bedeutet:
PATHist auf/usr/bin:/binbeschränkt- Keine eigenen Aliases oder Funktionen
- Keine Umgebungsvariablen aus deiner Shell-Konfiguration
Lösung 1: Absolute Pfade in jedem Job verwenden:
# Schlecht (findet python3 eventuell nicht)
*/5 * * * * python3 /opt/scripts/check.py
# Gut (absoluter Pfad)
*/5 * * * * /usr/bin/python3 /opt/scripts/check.py
Lösung 2: PATH und Variablen am Anfang der Crontab definieren:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LANG=de_CH.UTF-8
HOME=/home/seya
# Jetzt greifen die Variablen für alle nachfolgenden Jobs
0 2 * * * backup.sh
Lösung 3: Im Skript selbst auf die richtige Umgebung laden:
#!/bin/bash
source /home/seya/.profile
# ... Rest des Skripts
Overlap-Schutz mit flock
Ein unterschätztes Problem: Läuft ein Job länger als sein eigenes Intervall, startet Cron die nächste Instanz trotzdem – die beiden Läufe überlappen sich. Bei einem Backup-Skript, das gleichzeitig zweimal auf dieselbe Datenbank zugreift, oder einem Sync-Job, der sich selbst die Quelldateien unter den Füssen wegzieht, führt das zu Datenkorruption oder doppelten Ergebnissen.
Die einfachste und robusteste Lösung ist flock (aus dem util-linux-Paket, auf praktisch jeder Distribution vorhanden). flock legt eine Lock-Datei an und startet den eigentlichen Befehl nur, wenn er die Sperre bekommt:
# Non-blocking: überspringt den Lauf, falls der vorherige noch aktiv ist
*/5 * * * * /usr/bin/flock -n /var/lock/mein-job.lock /opt/scripts/mein-job.sh
# Blockierend mit Timeout: wartet maximal 60 Sekunden auf die Sperre
*/5 * * * * /usr/bin/flock -w 60 /var/lock/mein-job.lock /opt/scripts/mein-job.sh
-n(--nonblock): Bricht sofort ab, wenn die Sperre bereits gehalten wird (Exit-Code 1)-w N(--wait N): Wartet bis zu N Sekunden, dann bricht es ab- Die Lock-Datei muss nicht vorher existieren,
flocklegt sie bei Bedarf an
Alternativ lässt sich die Sperre auch direkt im Skript setzen, was nützlich ist, wenn du zusätzlich beim Scheitern loggen willst:
#!/bin/bash
# /opt/scripts/mein-job.sh
exec 200>/var/lock/mein-job.lock
flock -n 200 || { echo "Vorheriger Lauf noch aktiv, breche ab." >> /var/log/mein-job.log; exit 1; }
# ... eigentliche Arbeit hier ...
Exit-Code-basiertes Alerting
Ein Skript, das im Hintergrund lautlos fehlschlägt, ist der Klassiker unter den Cron-Problemen: Niemand merkt es, bis das Backup drei Wochen alt ist. Jeder ordentlich geschriebene Bash-Befehl gibt einen Exit-Code zurück (0 = Erfolg, alles andere = Fehler). Diesen Code kannst du direkt für Benachrichtigungen nutzen.
Per Mail
0 2 * * * /opt/scripts/backup.sh || echo "Backup fehlgeschlagen auf $(hostname)" | mail -s "FEHLER: Backup" admin@firma.ch
Per Webhook (Slack, Microsoft Teams, generisches System)
#!/bin/bash
# /opt/scripts/backup-mit-alert.sh
WEBHOOK_URL="https://hooks.example.com/services/xxx"
/opt/scripts/backup.sh
EXIT_CODE=$?
if [ "$EXIT_CODE" -ne 0 ]; then
curl -fsS -X POST -H "Content-Type: application/json" \
-d "{\"text\":\"Backup auf $(hostname) fehlgeschlagen (Exit-Code $EXIT_CODE)\"}" \
"$WEBHOOK_URL"
fi
exit "$EXIT_CODE"
Per ntfy.sh (leichtgewichtige Push-Benachrichtigung)
Für schnelle Warnungen aufs Handy eignet sich ntfy.sh (Open Source, selbst hostbar oder als gehosteter Dienst nutzbar):
/opt/scripts/backup.sh || curl -d "Backup auf $(hostname) fehlgeschlagen!" ntfy.sh/firma-alerts
Dead-Man’s-Switch-Monitoring (Healthchecks.io, Cronitor)
Ein Dead-Man’s-Switch dreht das Prinzip um: Statt dass dein Skript im Fehlerfall aktiv Alarm schlägt, meldet es sich bei jedem erfolgreichen Lauf bei einem externen Wächter-Dienst. Bleibt diese Meldung (“Ping”) länger aus als erwartet, schlägt der Dienst Alarm – egal, ob der Job abgestürzt ist, der Server nicht gebootet hat oder Cron selbst nicht mehr läuft. Das deckt genau die Lücke ab, die reines Exit-Code-Alerting offen lässt.
Zwei verbreitete Dienste dafür sind Healthchecks.io (Open Source, auch selbst hostbar) und Cronitor (kommerziell, mit fertigen CLI-Wrappern). Das Prinzip ist bei beiden fast identisch.
Einfaches Beispiel mit Healthchecks.io
Für jeden zu überwachenden Job legst du im Dashboard einen Check an und bekommst eine eindeutige URL (https://hc-ping.com/<uuid>). Ein einfacher Ping nach erfolgreichem Lauf reicht für die Basis-Absicherung:
30 2 * * * /opt/scripts/backup.sh && curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/dein-uuid-hier
-m 10: Timeout nach 10 Sekunden, falls der Wächter-Dienst nicht erreichbar ist--retry 5: Bis zu 5 Wiederholungsversuche bei Netzwerkfehlern-o /dev/null: Antwort verwerfen, nur der HTTP-Request zählt
Start- und Fehlersignale getrennt melden
Für mehr Detail (inklusive gemessener Laufzeit und explizitem Fehlerstatus) signalisierst du Start und Ergebnis separat:
#!/bin/bash
# /opt/scripts/backup-mit-healthcheck.sh
HC_URL="https://hc-ping.com/dein-uuid-hier"
curl -fsS -m 10 --retry 3 "$HC_URL/start" -o /dev/null
/opt/scripts/backup.sh
EXIT_CODE=$?
if [ "$EXIT_CODE" -eq 0 ]; then
curl -fsS -m 10 --retry 3 "$HC_URL" -o /dev/null
else
curl -fsS -m 10 --retry 3 "$HC_URL/fail" -o /dev/null
fi
exit "$EXIT_CODE"
Im Dashboard konfigurierst du zusätzlich eine Grace Period (Kulanzzeit): Läuft dein Backup normalerweise 15–25 Minuten und die Kulanzzeit ist auf 30 Minuten gesetzt, schlägt der Dienst erst Alarm, wenn 30 Minuten nach dem erwarteten Zeitpunkt kein Ping eingetroffen ist – so vermeidest du Fehlalarme bei normalen Laufzeitschwankungen.
Praxisbeispiel: Backup-Skript mit Cron
Ein typisches Szenario: Täglich um 02:30 Uhr wichtige Verzeichnisse auf ein Netzwerklaufwerk sichern, alte Backups bereinigen, Overlap verhindern und den Erfolg extern melden.
#!/bin/bash
# /opt/scripts/backup-daily.sh
DATUM=$(date +%Y-%m-%d)
BACKUP_QUELLE="/var/www /etc /home/seya"
BACKUP_ZIEL="/mnt/nas/backups"
LOG="/var/log/backup-daily.log"
echo "=== Backup gestartet: $(date) ===" >> "$LOG"
for QUELLE in $BACKUP_QUELLE; do
ZIEL="$BACKUP_ZIEL/$(basename $QUELLE)-$DATUM.tar.gz"
tar -czf "$ZIEL" "$QUELLE" 2>> "$LOG"
if [ $? -eq 0 ]; then
echo "OK: $QUELLE -> $ZIEL" >> "$LOG"
else
echo "FEHLER: $QUELLE konnte nicht gesichert werden!" >> "$LOG"
fi
done
# Backups aelter als 30 Tage loeschen
find "$BACKUP_ZIEL" -name "*.tar.gz" -mtime +30 -delete
echo "Alte Backups bereinigt." >> "$LOG"
echo "=== Backup beendet: $(date) ===" >> "$LOG"
Crontab-Eintrag mit Overlap-Schutz (flock) und Dead-Man’s-Switch-Ping in einer Zeile:
30 2 * * * /usr/bin/flock -n /var/lock/backup-daily.lock /opt/scripts/backup-daily.sh && curl -fsS -m 10 -o /dev/null https://hc-ping.com/dein-uuid-hier
Skript ausführbar machen:
chmod +x /opt/scripts/backup-daily.sh
Praxisbeispiel: Festplattenplatz überwachen
#!/bin/bash
# /opt/scripts/check-disk.sh
# Warnung per Mail wenn Festplatte ueber 80% voll
SCHWELLWERT=80
EMPFAENGER="admin@firma.ch"
df -h | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{print $5 " " $1}' | while read AUSLASTUNG FS; do
PROZENT=${AUSLASTUNG%%%}
if [ "$PROZENT" -ge "$SCHWELLWERT" ]; then
echo "WARNUNG: $FS ist zu ${AUSLASTUNG} voll!" | mail -s "Festplatten-Warnung auf $(hostname)" "$EMPFAENGER"
fi
done
# Alle 30 Minuten prüfen
*/30 * * * * /opt/scripts/check-disk.sh
Anacron: Für Systeme, die nicht immer laufen
Cron hat ein Problem: Wenn der Rechner zum geplanten Zeitpunkt ausgeschaltet war, wird der Job einfach übersprungen. Für Notebooks oder Server mit Wartungsfenstern gibt es Anacron.
Anacron prüft nicht die Uhrzeit, sondern wie lange ein Job zuletzt ausgeführt wurde. Wenn er zu lange nicht gelaufen ist, holt er ihn beim nächsten Start nach.
# /etc/anacrontab
# Periode Verzögerung Job-ID Befehl
1 5 cron.daily run-parts /etc/cron.daily
7 10 cron.weekly run-parts /etc/cron.weekly
@monthly 15 cron.monthly run-parts /etc/cron.monthly
- Periode: Tage zwischen den Ausführungen
- Verzögerung: Minuten Wartezeit nach Systemstart (verhindert, dass alle Jobs gleichzeitig starten)
- Job-ID: Eindeutiger Name für die Timestamp-Datei
Anacron ist auf Ubuntu/Debian standardmässig installiert und kümmert sich automatisch um /etc/cron.daily, /etc/cron.weekly und /etc/cron.monthly.
Cron in Docker-Containern
Ein häufiger Stolperstein bei der Migration in Docker-Umgebungen: Der klassische cron-Dämon in einem Container “einfach so” starten funktioniert oft nicht wie erwartet. Die Gründe:
- Cron dämonisiert sich standardmässig – es forkt sich in den Hintergrund und der Elternprozess beendet sich. Ist
cronaber der PID-1-Prozess eines Containers, beendet sich damit der ganze Container sofort wieder. - Cron leert die Umgebungsvariablen der Jobs, bevor es sie startet – ein Sicherheitsfeature auf Mehrbenutzer-Systemen, das in Containern aber genau die Konfiguration zerstört, die du typischerweise per
docker run -eoder Compose-environment:hineinreichst. - Minimal-Images (Alpine, Debian-Slim) haben oft gar kein
cron-Paket installiert, und Logs landen standardmässig in Dateien statt aufstdout/stderr, wo Docker sie erwartet.
Lösung 1: Cron im Vordergrund laufen lassen
Für einfache Fälle reicht es, cron im Vordergrund zu starten, sodass es PID 1 bleiben kann:
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y cron && rm -rf /var/lib/apt/lists/*
COPY crontab /etc/cron.d/mein-job
RUN chmod 0644 /etc/cron.d/mein-job && crontab /etc/cron.d/mein-job
CMD ["cron", "-f"]
Das Umgebungsvariablen-Problem bleibt damit aber bestehen – du musst Variablen explizit in die Crontab schreiben oder beim Container-Start in eine Datei exportieren, die die Jobs dann sourcen.
Lösung 2: supercronic (empfohlen für Container)
supercronic ist ein für Container entwickelter, crontab-kompatibler Job-Runner. Er läuft dauerhaft im Vordergrund, leert die Umgebung nicht und schreibt Job-Output direkt auf stdout/stderr – genau das Verhalten, das man in einem Container erwartet:
FROM alpine:3.20
ARG SUPERCRONIC_VERSION
RUN apk add --no-cache curl && \
curl -fsSLo /usr/local/bin/supercronic \
"https://github.com/aptible/supercronic/releases/download/${SUPERCRONIC_VERSION}/supercronic-linux-amd64" && \
chmod +x /usr/local/bin/supercronic
COPY crontab /app/crontab
CMD ["supercronic", "/app/crontab"]
Die passende SUPERCRONIC_VERSION findest du jeweils aktuell auf der Releases-Seite des Projekts. Wichtige Einschränkung: supercronic kann Jobs nicht wie root-Cron unter einem anderen User ausführen – das steuerst du stattdessen über die USER-Anweisung im Dockerfile.
Troubleshooting
Cron-Job läuft nicht – Checkliste
1. Ist cron überhaupt aktiv?
systemctl status cron # Debian/Ubuntu
systemctl status crond # RHEL/CentOS/Fedora
2. Cron-Logs einsehen
# Systemd-basierte Systeme
journalctl -u cron --since "1 hour ago"
journalctl -u cron | grep CRON
# Ältere Systeme (syslog)
grep CRON /var/log/syslog
grep CRON /var/log/cron
3. Skript manuell als gleicher User testen
# Genau so wie Cron es ausführen würde (minimale Umgebung)
env -i HOME=/home/seya /bin/bash /opt/scripts/mein-job.sh
4. Ausführbarkeit prüfen
ls -la /opt/scripts/mein-job.sh
# rwxr-xr-x muss gesetzt sein
chmod +x /opt/scripts/mein-job.sh
5. Shebang korrekt?
# Erste Zeile des Skripts muss sein:
#!/bin/bash
# oder
#!/usr/bin/env bash
6. Absolute Pfade verwenden?
Schau im Skript nach: Alle Befehle wie rsync, python3, mysqldump etc. mit vollem Pfad (/usr/bin/rsync) angeben oder PATH in der Crontab setzen.
7. Darf der User überhaupt Cron nutzen?
Falls crontab -e mit “You (username) are not allowed to use this program” quittiert wird, steht der User weder in /etc/cron.allow (falls vorhanden) oder er steht in /etc/cron.deny – siehe Abschnitt weiter oben.
Häufige Fehler
| Problem | Ursache | Lösung |
|---|---|---|
| Job startet nie | Fehlende ausführbare Rechte | chmod +x skript.sh |
command not found | PATH zu kurz | Absolute Pfade verwenden |
| Skript funktioniert manuell, nicht via Cron | Umgebungsvariablen fehlen | source ~/.profile im Skript oder Vars in Crontab |
| Datum/Uhrzeit falsch | Zeitzone des Servers | timedatectl prüfen, /etc/timezone, ggf. CRON_TZ |
| Jobs überlappen sich | Skript läuft länger als Intervall | flock-Lockfile einbauen |
% im Befehl zerschiesst Job | Sonderbedeutung in Crontab | Mit \% escapen oder in Skript auslagern |
| ”not allowed to use this program” | User fehlt in cron.allow / steht in cron.deny | Berechtigungsdateien anpassen |
| Cron-Container beendet sich sofort | cron dämonisiert sich, war PID 1 | cron -f im Vordergrund oder supercronic verwenden |
| Fehler bleibt tagelang unbemerkt | Kein Alerting eingerichtet | Exit-Code-Alerting oder Dead-Man’s-Switch ergänzen |
Cron vs. systemd-Timer
Seit systemd auf praktisch allen modernen Distributionen Standard ist, gibt es eine Alternative zu Cron: systemd-Timer. Hier ein kurzer Vergleich:
| Merkmal | Cron | systemd-Timer |
|---|---|---|
| Einfachheit | Sehr simpel, eine Zeile | Zwei Dateien nötig (.service + .timer) |
| Logging | Eigenes Logfile nötig | Automatisch in journald |
| Abhängigkeiten | Keine | Kann auf andere Units warten |
| Missed Jobs | Werden übersprungen | Können nachgeholt werden (Persistent=true) |
| Overlap-Schutz | Manuell via flock | Eingebaut (kein Parallel-Start derselben Unit) |
| Verbreitung | Überall vorhanden | Nur auf systemd-Systemen |
Für einfache, regelmässige Tasks ist Cron nach wie vor die erste Wahl. Für komplexere Anforderungen (Abhängigkeiten, detailliertes Logging, eingebauter Overlap-Schutz, Retries) lohnt sich ein Blick auf systemd-Timer.
Mehr zu Linux-Grundbefehlen findest du unter Linux – Grundbefehle, SSH-Automatisierung unter SSH – Grundlagen.
Weiterlernen
- Ubuntu Users Wiki – Cron – Ausführliche deutsche Dokumentation mit Syntax-Details
- crontab.guru – Interaktiver Cron-Ausdruck-Tester (englisch, aber selbsterklärend)
- man 5 crontab – Offizielle Manpage mit allen Details
- bin-bash.de – Cron Jobs – Praxisnaher deutschsprachiger Artikel mit Troubleshooting
- Hostinger – Was ist ein Cron-Job – Einsteiger-freundliche Erklärung auf Deutsch
- man 8 cron – Dokumentation des Cron-Daemon selbst
- man 1 flock – Offizielle Manpage zum Lock-Mechanismus
- Healthchecks.io – Monitoring Cron Jobs – Offizielle Anleitung zum Dead-Man’s-Switch-Pattern
- supercronic auf GitHub – Cron-kompatibler Job-Runner für Container
Kommentare
Frage, Verbesserungsvorschlag oder eigene Erfahrung zu diesem Artikel? Schreib einen Kommentar. Neue Beiträge erscheinen nach kurzer Moderation.
- Lade Kommentare …