systemd verstehen: Units, Journal & Timer (statt Cron)
Dienste starten, Logs lesen, Aufgaben planen: Dieser Grundlagen-Guide erklärt systemd an echten Befehlen – inklusive eigenem Dienst und Timer statt Cron.
Inhaltsverzeichnis
Jeder Dienst auf deinem Server – SSH, Docker, die Firewall – wird von systemd gestartet, überwacht und protokolliert. Wer systemd versteht, kann Ausfälle diagnostizieren, eigene Hintergrundjobs anlegen und geplante Aufgaben sauber automatisieren. Dieser Guide macht dich damit vertraut.
Was bauen wir?
Kein Dienst, sondern das Werkzeug, mit dem alle Dienste laufen: systemd (hier v257 auf Debian 13). Am Ende kannst du Dienste starten, stoppen und beim Booten aktivieren, ihre Logs mit journalctl lesen, einen eigenen Dienst als Unit-Datei anlegen und einen Timer bauen, der Cron ersetzt – mit dem entscheidenden Vorteil, dass er verpasste Läufe nachholen kann.
Voraussetzungen
- Ein Linux-Server mit systemd (jedes moderne Debian/Ubuntu – dein netcup-VPS)
- Root- oder
sudo-Zugang (siehe Benutzer & Rechte) - Vertrautheit mit den wichtigsten Terminal-Befehlen
VPS 1000 G12
4 vCore · 8 GB RAM · 256 GB NVMe
ab 10,36 €/Monat
Die Befehle sind auf jedem systemd-Linux gleich – jeder Server genügt.
💶 5 € Gutschein für netcup-Neukunden:36nc17844976032
(nur Neukunden, keine Domains)
Schritt für Schritt
Schritt 1: Units – das Grundkonzept
systemd verwaltet alles als Units. Die wichtigste Art ist der Service (.service) – ein Hintergrunddienst. Daneben gibt es u. a. Timer (.timer, geplante Ausführung), Sockets und Targets (Gruppen, grob vergleichbar mit Runlevels). Prüfe zuerst, welche Version läuft:
systemctl --versionsystemd 257 (257.13-1~deb13u1)Alle laufenden Dienste zeigt dir systemctl:
systemctl list-units --type=service --state=running containerd.service loaded active running containerd container runtime
cron.service loaded active running Regular background program processing daemon
docker.service loaded active running Docker Application Container Engine
fail2ban.service loaded active running Fail2Ban Service
ssh.service loaded active running OpenBSD Secure Shell serverJede Zeile ist eine Unit mit Ladezustand (loaded), Aktivzustand (active) und Unterzustand (running).
Schritt 2: Dienste steuern
Der wichtigste Befehl ist systemctl status. Er zeigt dir alles über einen Dienst – am Beispiel Docker:
systemctl status docker● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: enabled)
Active: active (running) since Sun 2026-07-19 21:34:42 CEST; 4 days ago
Main PID: 53379 (dockerd)
Tasks: 93
Memory: 282.8M (peak: 334.6M)Zwei Zeilen sind entscheidend: Active: (läuft der Dienst gerade?) und in der Loaded:-Zeile das Wort enabled (startet er beim Booten automatisch?). Das sind zwei unabhängige Dinge – ein Dienst kann laufen, aber nicht beim Boot starten, und umgekehrt. Für Skripte fragst du beides knapp ab:
systemctl is-active docker
systemctl is-enabled dockeractive
enabledDie vier Befehle für den Alltag: systemctl start DIENST (jetzt starten), stop (jetzt anhalten), restart (neu starten, z. B. nach Konfigänderung) und reload (Konfiguration neu einlesen, ohne den Dienst zu unterbrechen – sofern er das unterstützt). Wichtig: start/stop wirken nur bis zum nächsten Reboot. Damit ein Dienst dauerhaft beim Booten startet, brauchst du enable:
systemctl enable --now DIENSTenable schaltet den Autostart ein, --now startet den Dienst zusätzlich sofort – so sparst du dir den separaten start.
Schritt 3: Logs lesen mit journalctl
systemd sammelt die Ausgaben aller Dienste zentral im Journal. Statt in verstreuten Log-Dateien zu suchen, fragst du gezielt einen Dienst ab:
journalctl -u docker -n 20-u wählt die Unit, -n 20 zeigt die letzten 20 Zeilen. Die nützlichsten Varianten:
journalctl -u DIENST -f– live mitverfolgen (wietail -f), ideal beim Debuggen.journalctl -u DIENST --since "1 hour ago"– zeitlich eingrenzen.journalctl -p err -b– nur Fehler seit dem letzten Boot (-b= aktueller Boot).
Genau das ist der erste Griff, wenn ein Dienst nicht startet: systemctl status DIENST für den Überblick, dann journalctl -u DIENST für die Details.
Schritt 4: Einen eigenen Dienst anlegen
Jetzt baust du selbst eine Unit. Beispiel: ein Backup-Skript, das systemd ausführen soll. Unit-Dateien für eigene Dienste liegen in /etc/systemd/system/. Lege backup-demo.service an:
[Unit]
Description=Demo-Backup-Job
[Service]
Type=oneshot
ExecStart=/usr/bin/bash -c 'echo "Backup lief am $(date)" >> /var/log/backup-demo.log'Der Abschnitt [Unit] beschreibt die Unit, [Service] sagt, was laufen soll. Type=oneshot ist der Typ für einmalige Aufgaben, die starten, ihre Arbeit tun und sich beenden (im Gegensatz zu Dauerdiensten wie docker). Nach dem Anlegen einer neuen Unit muss systemd sie einlesen:
systemctl daemon-reload
systemctl start backup-demo.servicePrüfe das Ergebnis – oneshot-Dienste stehen nach getaner Arbeit korrekterweise auf inactive (dead):
systemctl status backup-demo.service○ backup-demo.service - Demo-Backup-Job
Loaded: loaded (/etc/systemd/system/backup-demo.service; static)
Active: inactive (dead)
systemd[1]: Starting backup-demo.service - Demo-Backup-Job...
systemd[1]: backup-demo.service: Deactivated successfully.
systemd[1]: Finished backup-demo.service - Demo-Backup-Job.Schritt 5: Timer statt Cron
Damit der Job regelmäßig läuft, koppelst du ihn an einen Timer – die systemd-Alternative zu Cron. Lege backup-demo.timer an (gleicher Name wie der Service, andere Endung):
[Unit]
Description=Startet den Demo-Backup täglich
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.targetOnCalendar bestimmt den Zeitplan (hier: täglich um 03:00 Uhr). Persistent=true ist der entscheidende Vorteil gegenüber Cron: War der Server zur geplanten Zeit aus, holt systemd den Lauf beim nächsten Start nach – ein verpasstes Backup fällt so nicht einfach aus. Aktiviere den Timer:
systemctl daemon-reload
systemctl enable --now backup-demo.timerAlle aktiven Timer und ihre nächste Ausführung zeigt:
systemctl list-timersNEXT LEFT UNIT ACTIVATES
Sat 2026-07-25 03:00:00 CEST 7h backup-demo.timer backup-demo.serviceOnCalendar-Ausdrücke testen
systemd-analyze calendar "Mon *-*-* 09:00:00" – das zeigt dir die nächsten Ausführungszeitpunkte, ohne etwas zu starten. So vermeidest du Timer, die nie oder zur falschen Zeit feuern.Genau dieses Muster – ein oneshot-Service plus Timer – nutzen die Restic-Backups der Serverküche. Du hast damit das Werkzeug für jede wiederkehrende Wartungsaufgabe in der Hand.
Wenn es nicht funktioniert
systemctl start schlägt fehl, der Dienst ist sofort wieder dead. Lies die Details mit journalctl -u DIENST -n 30. Bei eigenen Units ist die häufigste Ursache ein falscher Pfad in ExecStart – der Befehl muss mit absolutem Pfad stehen (/usr/bin/bash, nicht bash).
„Unit changed on disk, run daemon-reload". Du hast eine Unit-Datei bearbeitet, aber systemd liest Änderungen nicht automatisch. Nach jeder Änderung an /etc/systemd/system/ gilt: systemctl daemon-reload.
Der Timer taucht in list-timers nicht auf. Er wurde nicht aktiviert. systemctl enable --now DIENST.timer – und daran denken, dass der Timer den Service auslöst, du also beide Dateien brauchst (.service und .timer).
enable meldet „static". Der Unit fehlt der Abschnitt [Install] mit WantedBy=. Ohne ihn weiß systemd nicht, wann die Unit automatisch starten soll – bei Timern gehört WantedBy=timers.target hinein.
Das Journal ist riesig / frisst Platz. Standardmäßig wächst es begrenzt, aber du kannst es beschneiden: journalctl --vacuum-time=14d löscht Einträge älter als 14 Tage, journalctl --disk-usage zeigt den Verbrauch.
Wartung & Backups
- Eigene Units gehören ins Backup. Alles unter
/etc/systemd/system/ist deine eigene Konfiguration und sollte im Restic-Backup liegen. Nach einem Server-Neuaufbau stellst du damit deine Dienste und Timer sofort wieder her (danach einmaldaemon-reloadund die Timer neuenablen). - Timer statt eigener Cron-Jobs. Wenn du ohnehin systemd nutzt, sind Timer die konsistentere Wahl: Sie laufen im Journal auf, holen verpasste Läufe nach (
Persistent=true) und lassen sich mitsystemctl status DIENSTgenauso überwachen wie jeder andere Dienst. - Failed-Units im Blick behalten.
systemctl --failedlistet Dienste, die abgestürzt sind – ein schneller Gesundheitscheck fürs System. Für echte Alarmierung meldet dir Uptime Kuma den Ausfall des Servers, währendsystemctl --faileddie Ursache auf dem Host zeigt.
Feedback per E-Mail: feedback@serverkueche.de
Das könnte dir auch schmecken

Linux-Benutzer, Gruppen & Dateirechte verstehen
Wer darf was auf deinem Server? Dieser Grundlagen-Guide erklärt Benutzer, Gruppen und Dateirechte an echten Befehlen – …

Docker-Netzwerke verstehen: bridge, internes DNS & das proxy-Netz
Warum deklariert jedes App-Rezept ein proxy-Netz? Dieser Guide erklärt Docker-Netzwerke, das interne DNS und …

Erste Schritte mit einem netcup VPS
Vom bestellten Server zum einsatzbereiten System: SSH-Login, Updates, ein sudo-Benutzer und die wichtigsten Handgriffe …