Cronjobs und systemd-Timer
Aufgaben regelmäßig ausführen: crontab-Grundlagen, systemd-Timer und Beispiele.
5 Min. Lesezeit
Auf dieser Seite
Für alles, was regelmäßig laufen soll (Backups, Aufräumen, ein Skript jede Stunde), gibt es zwei Wege: cron, den Klassiker, und systemd-Timer, die mehr können und ihre Ausgabe im Journal ablegen.
Gilt für Debian 12 und 13, Ubuntu 22.04 und 24.04, AlmaLinux 9 und Rocky Linux 9. Alle Befehle laufen als root, wenn nichts anderes dasteht.
cron
Installiert?
command -v crontab || echo fehltFehlt es:
apt install -y cron && systemctl enable --now cron # Debian und Ubuntu
dnf install -y cronie && systemctl enable --now crond # AlmaLinux und Rocky LinuxDie crontab bearbeiten
crontab -eDas öffnet die crontab des aktuellen Benutzers im Editor. Jede Zeile ist eine Aufgabe:
# Minute Stunde Tag Monat Wochentag Befehl
30 3 * * * /usr/local/bin/backup.sh| Feld | Werte |
|---|---|
| Minute | 0–59 |
| Stunde | 0–23 |
| Tag im Monat | 1–31 |
| Monat | 1–12 |
| Wochentag | 0–7 (0 und 7 sind Sonntag) |
* heißt „jeder“, */15 „alle 15“, 1-5 „von 1 bis 5“, 1,15 „am 1. und 15.“.
Beispiele
# Jeden Tag um 3:30 Uhr
30 3 * * * /usr/local/bin/backup.sh
# Alle 15 Minuten
*/15 * * * * /usr/local/bin/check.sh
# Montag bis Freitag um 8 Uhr
0 8 * * 1-5 /usr/local/bin/bericht.sh
# Am 1. jedes Monats um Mitternacht
0 0 1 * * /usr/local/bin/monatlich.sh
# Nach jedem Neustart
@reboot /usr/local/bin/beim-start.sh
# WordPress-Cron alle 5 Minuten als Webserver-Benutzer (Debian/Ubuntu)
*/5 * * * * sudo -u www-data php /var/www/example.de/wp-cron.php > /dev/null 2>&1Eine Aufgabe für einen anderen Benutzer legst du mit crontab -u www-data -e an. Dann brauchst du kein sudo -u in der Zeile.
Worauf du achten musst
- cron kennt kaum Umgebungsvariablen.
PATHist sehr kurz. Schreib Befehle mit vollem Pfad (/usr/bin/php,/usr/local/bin/…), oder setz oben in die crontabPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin. - Ausgabe landet sonst im Nichts. cron will sie per Mail schicken; ohne Mailserver geht sie verloren. Leite sie in eine Datei:
… >> /var/log/meinjob.log 2>&1. %hat in der crontab eine eigene Bedeutung (Zeilenumbruch). In Befehlen wiedate +%Fmusst du es als\%schreiben, oder du packst den Befehl in ein Skript.- Zeitzone. cron nutzt die Zeitzone des Servers.
timedatectlzeigt sie,timedatectl set-timezone Europe/Berlinstellt sie um.
Prüfen, ob es geklappt hat
crontab -lzeigt deine Aufgaben. Ob ein Lauf stattgefunden hat:
journalctl -u cron --since today # Debian und Ubuntu
journalctl -u crond --since today # AlmaLinux und Rocky Linuxsystemd-Timer
Ein Timer besteht aus zwei Dateien: einem Service, der sagt, was läuft, und einem Timer, der sagt, wann. Vorteile gegenüber cron: Die Ausgabe steht im Journal, verpasste Läufe werden auf Wunsch nachgeholt, und zwei Läufe überlappen sich nie.
Beispiel: Aufräumskript jede Nacht
/etc/systemd/system/aufraeumen.service:
[Unit]
Description=Alte Dateien in /var/tmp/uploads löschen
[Service]
Type=oneshot
ExecStart=/usr/bin/find /var/tmp/uploads -type f -mtime +7 -delete/etc/systemd/system/aufraeumen.timer:
[Unit]
Description=Jede Nacht aufräumen
[Timer]
OnCalendar=*-*-* 04:00:00
Persistent=true
[Install]
WantedBy=timers.targetEinschalten:
systemctl daemon-reload
systemctl enable --now aufraeumen.timerLäuft der Dienst als anderer Benutzer, ergänz unter [Service] die Zeile User=www-data.
Zeitangaben für OnCalendar
| Angabe | Bedeutung |
|---|---|
hourly | jede volle Stunde |
daily | jeden Tag um 0 Uhr |
weekly | montags um 0 Uhr |
*-*-* 03:30:00 | jeden Tag um 3:30 Uhr |
Mon..Fri 08:00 | werktags um 8 Uhr |
*:0/15 | alle 15 Minuten |
*-*-01 00:00:00 | am 1. jedes Monats |
Ob eine Angabe stimmt und wann sie das nächste Mal greift, zeigt:
systemd-analyze calendar "Mon..Fri 08:00"Statt einer Uhrzeit geht auch ein Abstand, z. B. OnBootSec=5min und OnUnitActiveSec=1h für „5 Minuten nach dem Start, danach stündlich“.
Prüfen, ob es geklappt hat
systemctl list-timerszeigt alle Timer mit letztem und nächstem Lauf. Ausgabe und Fehler des letzten Laufs:
journalctl -u aufraeumen.service -n 50 --no-pagerSofort einmal von Hand ausführen, ohne auf den Timer zu warten:
systemctl start aufraeumen.serviceHäufige Fehler
- Der Befehl klappt im Terminal, aber nicht in cron. Fast immer
PATHoder ein relativer Pfad. Volle Pfade nehmen und im Skript mitcdin den richtigen Ordner wechseln. - Cron-Skript läuft gar nicht. Ist es ausführbar?
chmod +x /usr/local/bin/backup.sh. Hat es eine erste Zeile wie#!/bin/bash? - Der Timer steht nicht in
list-timers.systemctl daemon-reloadvergessen oder den Timer nicht mitenable --noweingeschaltet. Failed to start … Unit … not found. Service und Timer müssen gleich heißen (aufraeumen.serviceundaufraeumen.timer), sonst braucht der Timer eine ZeileUnit=unter[Timer].- Aufgabe läuft zur falschen Zeit. Zeitzone des Servers prüfen (
timedatectl).
Wie es weitergeht
- Ein tägliches Backup als Timer: Backups einrichten.
Kommst du nicht weiter, schreib uns ein Ticket.