Zum Inhalt springen
sw
en

Tippe um zu suchen

Linux

systemd – Dienste unter Linux verwalten

systemd ist das Init-System moderner Linux-Distributionen. Lerne systemctl, journalctl, eigene Service-Units und Troubleshooting im IT-Alltag.

10 Min Lesezeit Fortgeschritten Zuletzt aktualisiert:

Was ist systemd?

systemd ist das Init-System und der Service-Manager, der auf praktisch allen modernen Linux-Distributionen läuft – Ubuntu, Debian, RHEL, Fedora, openSUSE, Arch und viele mehr. Es ist der erste Prozess, den der Kernel startet (PID 1), und damit zuständig für alles, was danach kommt: Dienste hochfahren, Mounts einrichten, Logs sammeln und das System in einen definierten Zustand bringen.

Vor systemd gab es SysVinit mit Shell-Skripten in /etc/init.d/. systemd hat das weitgehend abgelöst und bringt einige klare Vorteile mit:

MerkmalSysVinitsystemd
ParallelisierungKaum (sequenziell)Vollständig parallel
AbhängigkeitenManuell in SkriptenDeklarativ in Unit-Dateien
LoggingSyslog / Textdateienjournald (strukturiert, durchsuchbar)
Restart-LogikExternes Skript nötigEingebaut (Restart=on-failure)
AktivierungsartenBeim BootenBoot, Socket, Pfad, Timer, D-Bus

Unit-Typen verstehen

systemd verwaltet sogenannte Units – das sind Konfigurationsdateien, die beschreiben, was systemd managen soll. Der Dateityp ergibt sich aus der Endung:

EndungZweck
.serviceDienste und Daemons (nginx, sshd, postgresql, …)
.targetSynchronisationspunkte / Systemzustände (entspricht alten Runleveln)
.timerZeitgesteuerte Ausloesungen (Alternative zu cron)
.socketSocket-Aktivierung (Dienst startet erst bei eingehender Verbindung)
.mountEinhaengepunkte im Dateisystem
.pathDatei- oder Verzeichnisueberwachung
.sliceRessourcengruppen (cgroups)

Im IT-Alltag wirst du fast immer mit .service und gelegentlich mit .timer zu tun haben.

Unit-Dateien liegen an diesen Orten (Prioritaet von oben nach unten):

/etc/systemd/system/          # Eigene / Administrator-Units (hoechste Prioritaet)
/run/systemd/system/          # Laufzeit-generierte Units
/usr/lib/systemd/system/      # Vom Paketmanager installierte Units

Willst du eine Paket-Unit anpassen, ohne sie zu ueberschreiben (damit Updates sie nicht zuruecksetzen), nutze Drop-in-Dateien:

# Erstellt automatisch ein Drop-in-Verzeichnis
sudo systemctl edit nginx.service
# Oeffnet Editor → schreibe nur die zu ueberschreibenden Sektionen
# Datei landet in: /etc/systemd/system/nginx.service.d/override.conf

Dienste verwalten mit systemctl

systemctl ist das zentrale Werkzeug fuer alles rund um systemd-Dienste.

Status und Zustand pruefen

# Detaillierter Status inkl. letzter Log-Zeilen
systemctl status nginx

# Kurze Abfragen (Exit-Code 0 = aktiv/enabled, 1 = nicht)
systemctl is-active nginx
systemctl is-enabled nginx
systemctl is-failed nginx

# Alle Services anzeigen
systemctl list-units --type=service

# Nur fehlgeschlagene
systemctl list-units --type=service --state=failed

# Alle Units inkl. inaktiver
systemctl list-units --type=service --all

Die Ausgabe von systemctl status nginx zeigt dir sofort den wichtigsten Kontext:

● nginx.service - A high performance web server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2026-06-23 08:12:33 UTC; 2h 14min ago
    Process: 1234 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
   Main PID: 1238 (nginx)
      Tasks: 3 (limit: 4678)
     Memory: 6.1M
        CPU: 89ms
     CGroup: /system.slice/nginx.service
             ├─1238 nginx: master process
             └─1239 nginx: worker process

Starten, Stoppen, Neustarten

# Starten / Stoppen
sudo systemctl start nginx
sudo systemctl stop nginx

# Neustart (stop + start)
sudo systemctl restart nginx

# Konfiguration neu laden – ohne Unterbrechung (wenn der Dienst das unterstuetzt)
sudo systemctl reload nginx

# Reload wenn moeglich, sonst restart
sudo systemctl reload-or-restart nginx

Autostart beim Booten steuern

# Autostart aktivieren (symlink nach /etc/systemd/system/)
sudo systemctl enable nginx

# Autostart aktivieren UND sofort starten (der Normalfall beim Einrichten)
sudo systemctl enable --now nginx

# Autostart deaktivieren
sudo systemctl disable nginx

# Dienst sperren – kann nicht gestartet werden (auch nicht als Abhaengigkeit)
sudo systemctl mask nginx
sudo systemctl unmask nginx

Targets – die Ersatz-Runlevel

Targets sind Synchronisationspunkte, die einen bestimmten Systemzustand repraesentieren:

TargetEntsprichtBedeutung
poweroff.targetRunlevel 0System herunterfahren
rescue.targetRunlevel 1Single-User / Rettungsmodus
multi-user.targetRunlevel 3Mehrbenutzerbetrieb ohne GUI
graphical.targetRunlevel 5Mehrbenutzerbetrieb mit GUI
reboot.targetRunlevel 6Neustart
# Standard-Target anzeigen
systemctl get-default

# Standard-Target setzen (Server: meist multi-user.target)
sudo systemctl set-default multi-user.target

# In ein Target wechseln (sofort, ohne Neustart)
sudo systemctl isolate rescue.target

Logs mit journalctl lesen

systemd protokolliert alle Dienst-Ausgaben in journald – einem strukturierten, binaeren Log-System. Das Werkzeug dafuer ist journalctl.

Grundlegende Abfragen

# Alle Logs (beginnt am Anfang – oft sehr viel)
journalctl

# Logs eines bestimmten Dienstes
journalctl -u nginx

# Live-Ausgabe (wie tail -f)
journalctl -u nginx -f

# Letzter Boot
journalctl -b

# Vorletzter Boot
journalctl -b -1

# Alle verfuegbaren Boots auflisten
journalctl --list-boots

Zeitbasiertes Filtern

# Letzte Stunde
journalctl -u nginx --since "1 hour ago"

# Zeitraum angeben
journalctl -u nginx --since "2026-06-23 08:00" --until "2026-06-23 10:00"

# Heute
journalctl -u nginx --since today

# Letzte 50 Zeilen
journalctl -u nginx -n 50

Nach Prioritaet filtern

# Nur Fehler und schlimmer (emerg, alert, crit, err)
journalctl -p err

# Nur Warnungen und schlimmer
journalctl -p warning

# Kernel-Meldungen
journalctl -k

Ausgabeformat anpassen

# Kompakte Ausgabe (eine Zeile pro Eintrag)
journalctl -u nginx -o short

# JSON (maschinell lesbar)
journalctl -u nginx -o json-pretty

# Nur die Nachricht
journalctl -u nginx -o cat

# Nach Text suchen (grep-aehnlich)
journalctl -u nginx -g "error"

Speicherplatz verwalten

# Aktuelle Groesse des Journals
journalctl --disk-usage

# Altes Journal loeschen (aelter als 2 Wochen)
sudo journalctl --vacuum-time=2weeks

# Journal auf maximale Groesse begrenzen
sudo journalctl --vacuum-size=500M

Eigenen Dienst erstellen

Das ist eine der nuetzlichsten Faehigkeiten im Linux-Betrieb: Eigene Skripte oder Applikationen als systemd-Dienst verwalten. Damit laeuft deine App beim Booten automatisch, startet bei Absturz neu und schreibt Logs direkt ins Journal.

Schritt-fuer-Schritt-Anleitung

1. Service-Datei erstellen:

sudo nano /etc/systemd/system/mein-dienst.service

2. Inhalt der Unit-Datei:

[Unit]
Description=Meine Node.js-Applikation
Documentation=https://wiki.firma.ch
# Erst starten wenn Netzwerk verfuegbar und PostgreSQL laeuft
After=network.target postgresql.service
Wants=postgresql.service

[Service]
Type=simple
# Als welcher User soll der Dienst laufen? NIE root, ausser zwingend noetig
User=nodeapp
Group=nodeapp
WorkingDirectory=/opt/nodeapp
# Umgebungsvariablen direkt oder aus Datei
Environment=NODE_ENV=production
EnvironmentFile=/etc/nodeapp/env

# Der eigentliche Startbefehl
ExecStart=/usr/bin/node /opt/nodeapp/server.js
# Optional: Vor dem Start pruefen (z.B. Konfigtest)
# ExecStartPre=/opt/nodeapp/check-config.sh

# Neustart bei Fehler (nicht bei bewusstem Stop)
Restart=on-failure
RestartSec=5s
# Nicht mehr als 3 Neustarts in 60 Sekunden (Crash-Loop verhindern)
StartLimitBurst=3
StartLimitIntervalSec=60s

# Haertungsoptionen (Security Hardening)
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/nodeapp /var/log/nodeapp

[Install]
WantedBy=multi-user.target

3. Dienst aktivieren:

# systemd informieren dass neue Unit-Dateien vorhanden sind
sudo systemctl daemon-reload

# Aktivieren und starten
sudo systemctl enable --now mein-dienst

# Pruefen ob alles laeuft
systemctl status mein-dienst
journalctl -u mein-dienst -f

Unit-Sektionen im Ueberblick

[Unit] – Metadaten und Abhaengigkeiten:

OptionBedeutung
Description=Beschreibung (erscheint in systemctl status)
After=Erst starten nach diesen Units (Reihenfolge)
Wants=Weiche Abhaengigkeit (Unit fehlt → kein Fehler)
Requires=Harte Abhaengigkeit (Unit fehlt → Fehler)
ConditionPathExists=Nur starten wenn Pfad existiert

[Service] – Wie der Dienst laeuft:

OptionBedeutung
Type=simpleProzess laeuft im Vordergrund (Standard)
Type=forkingProzess forkt sich selbst (alte Daemons)
Type=oneshotEinmaliger Befehl (z.B. Startup-Skript)
Type=notifyDienst meldet Bereitschaft aktiv (sd_notify)
ExecStart=Startbefehl (absoluter Pfad!)
ExecStop=Expliziter Stop-Befehl (sonst SIGTERM)
Restart=no, always, on-failure, on-abnormal
RestartSec=Wartezeit vor Neustart
TimeoutStartSec=Maximale Startzeit
StandardOutput=Wohin geht stdout (journal, null, file:/pfad)

[Install] – Wann wird die Unit aktiv:

OptionBedeutung
WantedBy=multi-user.targetNormaler Serverbetrieb (Standard fuer die meisten Dienste)
WantedBy=graphical.targetNur mit GUI

systemd Timer als Cron-Ersatz

systemd-Timer sind eine leistungsstaerkere Alternative zu Cron-Jobs. Sie sind praeziser, haben bessere Logging-Integration und koennen mit anderen Units abhaengig gemacht werden.

Beispiel: Taeglich um 02:00 Uhr ein Backup-Skript ausfuehren

# 1. Service-Unit erstellen (die eigentliche Aktion)
sudo nano /etc/systemd/system/backup-daily.service
[Unit]
Description=Taeglich Backup ausfuehren

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup.sh
# 2. Timer-Unit erstellen
sudo nano /etc/systemd/system/backup-daily.timer
[Unit]
Description=Backup taeglich um 02:00 Uhr

[Timer]
OnCalendar=*-*-* 02:00:00
# Nachholen wenn System zu dem Zeitpunkt aus war
Persistent=true

[Install]
WantedBy=timers.target
# 3. Timer aktivieren (nicht den Service!)
sudo systemctl daemon-reload
sudo systemctl enable --now backup-daily.timer

# Alle Timer und naechste Ausfuehrung anzeigen
systemctl list-timers

Troubleshooting – wenn Dienste nicht starten

Systematische Fehlersuche

# 1. Exakter Fehlerstatus
systemctl status mein-dienst

# 2. Vollstaendige Logs seit letztem Start
journalctl -u mein-dienst -b --no-pager

# 3. Nur Fehler des Dienstes
journalctl -u mein-dienst -p err

# 4. Syntaxpruefung der Unit-Datei
systemd-analyze verify /etc/systemd/system/mein-dienst.service

# 5. Abhaengigkeiten anzeigen
systemctl list-dependencies mein-dienst

# 6. Was haelt einen Dienst zurueck?
systemctl show mein-dienst | grep -E "ExecStart|Restart|User|WorkingDir"

Haeufige Fehler und Loesungen

Dienst startet nicht nach Aenderung der Unit-Datei:

# Vergessen, daemon-reload zu machen
sudo systemctl daemon-reload
sudo systemctl restart mein-dienst

“Failed to start: Unit not found”:

# Unit-Datei existiert nicht oder hat Tippfehler im Namen
ls /etc/systemd/system/*.service
systemctl list-unit-files | grep mein

“Permission denied” im Journal:

# Falscher User oder fehlende Berechtigungen auf Verzeichnisse
# Pruefen: Laeuft der Dienst unter dem richtigen User?
systemctl show mein-dienst | grep User
# Verzeichnis-Rechte pruefen
ls -la /opt/mein-app/

Dienst startet in Crash-Loop (staendig restart):

# Logs der fehlgeschlagenen Versuche anzeigen
journalctl -u mein-dienst --since "10 minutes ago"
# StartLimitBurst erreicht? Reset mit:
sudo systemctl reset-failed mein-dienst

Dienst wird mit systemctl start gestartet aber laeuft nicht weiter:

# Moeglicherweise Type=forking obwohl Prozess im Vordergrund laeuft
# oder ExecStart-Befehl endet sofort
# Teste den Befehl manuell im Terminal und schau was passiert

Systemd im KMU-Alltag: Praxisbeispiele

Samba/NFS nach Netzwerk starten

[Unit]
After=network-online.target
Wants=network-online.target

network-online.target ist staerker als network.target – es wartet bis das Netzwerk tatsaechlich erreichbar ist, nicht nur konfiguriert.

Monitoring-Check mit One-Shot

# /etc/systemd/system/check-disk.service
[Unit]
Description=Festplattenplatz pruefen

[Service]
Type=oneshot
ExecStart=/usr/local/bin/check-disk.sh
# /etc/systemd/system/check-disk.timer
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target

SSH nach Konfigurations-Aenderung sicher neu laden

# Konfiguration pruefen (kein Typo der sshd abschiessen wuerde)
sudo sshd -t

# Nur wenn Test erfolgreich war, reload
sudo systemctl reload sshd

Verwandt: Mehr zu SSH-Absicherung unter SSH – Grundlagen.

Wenn du noch nicht mit den Linux-Grundbefehlen vertraut bist, lies zuerst Linux – Grundbefehle fuer IT-Allrounder. Fuer zeitgesteuerte Aufgaben unter Linux findest du die cron-basierte Alternative unter Cron Jobs. Auf Windows-Servern uebernimmt der Task Scheduler eine aehnliche Rolle. Wer Docker-Container mit systemd verwalten will (z.B. als Podman-Integration), findet die Container-Grundlagen unter Docker – Container Grundlagen.

Weiterlernen

Videos

YouTube
systemd on Linux 1: Intro and Unit Files

Kommentare

Frage, Verbesserungsvorschlag oder eigene Erfahrung zu diesem Artikel? Schreib einen Kommentar. Neue Beiträge erscheinen nach kurzer Moderation.

  • Lade Kommentare …
Kommentar schreiben