Zum Inhalt springen
Alle Artikel
SystemdLinux-AdministrationService Units

Systemd Service Units: Linux-Dienste richtig verwalten

Lerne, wie du mit Systemd eigene Service Units erstellst, Linux-Dienste verwaltest und automatisch überwachst – mit praktischen Beispielen für Webentwickler.

17. März 20267 Min. Lesezeit

Wer einen Linux-Server betreibt – sei es für eine Node.js-App, einen Python-Webservice oder eine einfache Hintergrundaufgabe – kommt an Systemd nicht vorbei. Es ist das Init-System nahezu aller modernen Linux-Distributionen und bestimmt, welche Dienste beim Booten starten, wie sie überwacht werden und was bei einem Absturz passiert. Trotzdem schreiben viele Entwickler ihre Prozesse noch immer in screen- oder nohup-Sessions – ein fragiler Ansatz, der spätestens beim nächsten Serverneustart zum Problem wird. In diesem Artikel lernst du, wie du Systemd Service Units richtig erstellst, verwaltest und für den produktiven Einsatz absicherst.

Was ist Systemd und warum solltest du es nutzen?

Systemd ist weit mehr als ein Prozess-Starter. Es ist ein vollständiges System- und Service-Management-Framework, das unter anderem folgende Aufgaben übernimmt:

  • Prozessüberwachung: Automatischer Neustart bei Absturz
  • Abhängigkeitsmanagement: Dienste in der richtigen Reihenfolge starten
  • Logging: Zentralisierte Logs über journalctl
  • Ressourcenkontrolle: CPU- und Speicherlimits per Cgroup-Integration
  • Socket-Aktivierung: Dienste erst bei eingehender Verbindung starten

Für Webentwickler bedeutet das: Kein pm2, kein supervisor, kein forever als zusätzliche Abhängigkeit – das Betriebssystem bringt alles mit, was du brauchst.

Aufbau einer Service Unit-Datei

Eine Service Unit ist eine einfache INI-Datei mit der Endung .service, die im Verzeichnis /etc/systemd/system/ abgelegt wird. Sie besteht aus drei zentralen Sektionen:

Die Struktur im Überblick

[Unit]
Description=Beschreibung des Dienstes
After=network.target

[Service]
Type=simple
ExecStart=/pfad/zum/programm
Restart=on-failure

[Install]
WantedBy=multi-user.target
  • [Unit]: Metadaten und Abhängigkeiten. After=network.target stellt sicher, dass das Netzwerk verfügbar ist, bevor der Dienst startet.
  • [Service]: Die eigentliche Dienstkonfiguration – was gestartet wird, unter welchem Benutzer, wie bei Fehlern reagiert wird.
  • [Install]: Definiert, in welchem Boot-Target der Dienst aktiviert wird. multi-user.target entspricht dem klassischen Runlevel 3 (Mehrbenutzerbetrieb ohne GUI).

Praxisbeispiel 1: Node.js-Anwendung als Systemd Service

Angenommen, du hast eine Express-App unter /var/www/myapp, die auf Port 3000 lauscht. So erstellst du die passende Service Unit:

sudo nano /etc/systemd/system/myapp.service
[Unit]
Description=My Node.js Web Application
Documentation=https://github.com/deinuser/myapp
After=network.target

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/node /var/www/myapp/server.js
Restart=on-failure
RestartSec=5
StartLimitIntervalSec=60
StartLimitBurst=5
Environment=NODE_ENV=production
Environment=PORT=3000

[Install]
WantedBy=multi-user.target

Den Dienst aktivieren und starten

Nach dem Erstellen der Datei muss Systemd die neue Unit einlesen:

# Systemd-Konfiguration neu laden
sudo systemctl daemon-reload

# Dienst beim Booten automatisch starten
sudo systemctl enable myapp.service

# Dienst sofort starten
sudo systemctl start myapp.service

# Status prüfen
sudo systemctl status myapp.service

Die Ausgabe von status zeigt dir den aktuellen Zustand, die PID, den Speicherverbrauch und die letzten Log-Zeilen – alles auf einen Blick.

Praxisbeispiel 2: Python-FastAPI mit virtuellem Environment

Für Python-Anwendungen mit einem virtualenv sieht die Unit etwas anders aus:

[Unit]
Description=FastAPI Backend Service
After=network.target postgresql.service
Requires=postgresql.service

[Service]
Type=simple
User=appuser
Group=appuser
WorkingDirectory=/opt/api-backend
ExecStart=/opt/api-backend/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000
Restart=always
RestartSec=3
StandardOutput=journal
StandardError=journal
SyslogIdentifier=api-backend

# Sicherheitshärtung
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/api-backend/data

[Install]
WantedBy=multi-user.target

Beachte hier zwei wichtige Details:

  • Requires=postgresql.service erzwingt, dass PostgreSQL läuft. Fällt die Datenbank aus, wird auch der API-Dienst gestoppt.
  • Die Sicherheitsoptionen am Ende schränken den Dateisystemzugriff ein – ein wichtiger Schritt für produktive Server.

Wichtige systemctl-Befehle im Alltag

Diese Befehle wirst du als Entwickler und Admin ständig brauchen:

# Dienst starten / stoppen / neustarten
sudo systemctl start myapp
sudo systemctl stop myapp
sudo systemctl restart myapp

# Sanfter Reload (falls die App SIGHUP unterstützt)
sudo systemctl reload myapp

# Autostart aktivieren / deaktivieren
sudo systemctl enable myapp
sudo systemctl disable myapp

# Alle laufenden Services auflisten
systemctl list-units --type=service --state=running

# Fehlgeschlagene Services finden
systemctl --failed

Logs mit journalctl auswerten

Systemd leitet alle Ausgaben deines Dienstes automatisch an das Journal weiter. Das macht separate Log-Dateien in vielen Fällen überflüssig:

# Alle Logs eines Dienstes anzeigen
journalctl -u myapp.service

# Nur die letzten 50 Zeilen, live aktualisiert
journalctl -u myapp.service -n 50 -f

# Logs seit dem letzten Boot
journalctl -u myapp.service -b

# Logs eines bestimmten Zeitraums
journalctl -u myapp.service --since "2024-01-15 10:00" --until "2024-01-15 12:00"

# Nur Fehler und Warnungen
journalctl -u myapp.service -p err

Der Vorteil gegenüber klassischen Log-Dateien: Das Journal rotiert automatisch, ist indexiert und lässt sich nach Priorität, Zeitraum und Unit filtern.

Fortgeschrittene Konfiguration

Restart-Verhalten feintunen

Die Restart-Direktiven in Systemd sind mächtig und lassen sich präzise konfigurieren:

Direktive Bedeutung
Restart=no Kein automatischer Neustart (Standard)
Restart=on-failure Neustart nur bei Fehler (Exit-Code ≠ 0)
Restart=always Neustart immer, außer bei systemctl stop
RestartSec=5 5 Sekunden Pause vor dem Neustart
StartLimitBurst=5 Maximal 5 Neustarts...
StartLimitIntervalSec=60 ...innerhalb von 60 Sekunden

Ressourcenlimits setzen

Du kannst direkt in der Service Unit Grenzen für CPU und Speicher definieren:

[Service]
MemoryMax=512M
CPUQuota=50%
TasksMax=100

Das ist besonders nützlich auf Shared-Servern, um zu verhindern, dass ein einzelner Dienst alle Ressourcen beansprucht.

Timer statt Cronjob

Wusstest du, dass Systemd auch Cronjobs ersetzen kann? Mit Timer Units lassen sich zeitgesteuerte Aufgaben deutlich flexibler konfigurieren:

# /etc/systemd/system/backup.timer
[Unit]
Description=Tägliches Datenbank-Backup

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target
# /etc/systemd/system/backup.service
[Unit]
Description=Datenbank-Backup ausführen

[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh
User=backup
sudo systemctl enable --now backup.timer
systemctl list-timers

Persistent=true sorgt dafür, dass ein verpasster Lauf (z. B. weil der Server ausgeschaltet war) beim nächsten Boot nachgeholt wird – etwas, das Cron nicht bietet.

Häufige Fehler und Troubleshooting

Wenn ein Dienst nicht startet, helfen diese Schritte:

# Detaillierter Status mit Fehlermeldung
sudo systemctl status myapp.service -l

# Unit-Datei auf Syntaxfehler prüfen
sudo systemd-analyze verify /etc/systemd/system/myapp.service

# Alle Eigenschaften des Dienstes anzeigen
systemctl show myapp.service

Typische Stolperfallen:

  • Fehlende absolute Pfade: ExecStart erwartet immer den vollständigen Pfad zur Binary – node server.js funktioniert nicht, es muss /usr/bin/node server.js heißen.
  • Falsche Berechtigungen: Läuft der Dienst als www-data, muss dieser Benutzer auch Leserechte auf alle benötigten Dateien haben.
  • daemon-reload vergessen: Nach jeder Änderung an einer Unit-Datei muss sudo systemctl daemon-reload ausgeführt werden.
  • Environment-Variablen: Shell-Expansionen wie $HOME funktionieren in Unit-Dateien nicht. Nutze Environment= oder eine EnvironmentFile=/etc/myapp/env.

Fazit

Systemd Service Units sind das Rückgrat der Linux-Dienstverwaltung und ein Werkzeug, das jeder Webentwickler beherrschen sollte, der eigene Server betreibt. Die Einstiegshürde ist gering – eine einfache Unit-Datei besteht aus weniger als 15 Zeilen – und der Gewinn an Zuverlässigkeit ist enorm. Dein Dienst startet automatisch nach einem Reboot, wird bei Abstürzen neu gestartet und liefert saubere, zentrale Logs über journalctl. Kombiniert mit den Sicherheits- und Ressourcenoptionen, die Systemd mitbringt, ergibt sich ein Setup, das den meisten Third-Party-Prozessmanagern überlegen ist. Leg dir ein kleines Repository mit deinen bewährten Unit-Templates an – du wirst sie bei jedem neuen Projekt wieder brauchen.