Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Linux 02.06.2026 · 7 min Lesezeit

systemd-Service selbst erstellen und verwalten

Eigenen systemd-Service anlegen, aktivieren und überwachen – von der Unit-Datei bis zu journalctl und Autostart.

Linux-Terminal mit systemctl-Befehlen zur Service-Verwaltung

systemd-Services ermöglichen es dir, eigene Programme und Skripte zuverlässig als Hintergrunddienst zu betreiben – mit automatischem Start beim Systemboot, Neustart bei Absturz und zentralem Logging im Journal. Diese Anleitung zeigt dir Schritt für Schritt, wie du eine eigene Unit-Datei erstellst, den Dienst verwaltest und Logs auswertest. Das Wissen gilt für alle modernen Linux-Distributionen, die systemd nutzen (Debian, Ubuntu, RHEL, Fedora, openSUSE u. a.).

Kurzfassung: Unit-Datei nach /etc/systemd/system/myapp.service schreiben, sudo systemctl daemon-reload ausführen, dann sudo systemctl enable --now myapp.service. Logs zeigt journalctl -u myapp.service -f.

Voraussetzungen

  1. Linux-System mit systemd (ab Debian 8, Ubuntu 16.04, RHEL/CentOS 7 oder neuer)
  2. Root-Zugang oder sudo-Berechtigung
  3. Das Programm oder Skript, das als Dienst laufen soll, ist bereits vorhanden und ausführbar
  4. Grundlegende Kenntnisse im Umgang mit der Linux-Kommandozeile

Schritt 1: Aufbau einer systemd-Unit-Datei verstehen

Eine Service-Unit-Datei besteht aus drei Sektionen. Du musst alle drei kennen, bevor du mit dem Schreiben anfängst:

  1. [Unit] – Metadaten und Abhängigkeiten: Beschreibung des Dienstes, Reihenfolge- und Abhängigkeitsangaben gegenüber anderen Units.
  2. [Service] – Kernkonfiguration: Welches Programm gestartet wird, unter welchem Benutzer, wie Neustarts funktionieren.
  3. [Install] – Autostart-Verhalten: Legt fest, in welchem Systemzustand (Target) der Dienst aktiv ist.

Wichtige Direktiven in [Unit]:

  1. Description= – Kurzbeschreibung, erscheint in systemctl status
  2. After= – Startreihenfolge: dieser Service startet nach den genannten Units (aber ohne harte Abhängigkeit)
  3. Wants= – Weiche Abhängigkeit: genannte Units werden mitgestartet, aber Fehler dort stoppen diesen Service nicht
  4. Requires= – Harte Abhängigkeit: Scheitert die genannte Unit, startet dieser Service nicht

Wichtige Direktiven in [Service]:

  1. Type=simple – Standard: systemd hält den Prozess für gestartet, sobald ExecStart läuft
  2. Type=oneshot – systemd wartet auf den Exit des Prozesses (z. B. für Skripte)
  3. Type=forking – für klassische Daemons, die sich nach dem Start forken
  4. ExecStart= – Hauptbefehl (zwingend absoluter Pfad)
  5. ExecStartPre= / ExecStartPost= – Befehle vor und nach dem Start
  6. User= / Group= – Benutzer und Gruppe, unter der der Prozess läuft (Standard: root)
  7. WorkingDirectory= – Arbeitsverzeichnis
  8. Restart=on-failure – Neustart nur bei Fehler (empfohlen); always startet auch nach manuellem Stop neu
  9. RestartSec=5s – Wartezeit vor dem Neustart
  10. StandardOutput=journal / StandardError=journal – Ausgaben ins systemd-Journal

Wichtige Direktive in [Install]:

  1. WantedBy=multi-user.target – Service wird beim normalen Systemstart aktiviert (Standard für Server-Dienste)

Schritt 2: Unit-Datei erstellen

Öffne einen Editor und lege die Unit-Datei an. Der Dateiname bestimmt den Service-Namen:

sudo nano /etc/systemd/system/myapp.service

Trage folgenden Inhalt ein – passe Pfade, Benutzer und Beschreibung an dein Programm an:

[Unit]
Description=Meine eigene Anwendung
After=network.target
Wants=network.target

[Service]
Type=simple
User=myappuser
Group=myappuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/myapp --config /etc/myapp/config.yaml
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Ein paar Hinweise zu diesem Beispiel:

  1. After=network.target stellt sicher, dass der Netzwerkstack verfügbar ist, bevor der Dienst startet – sinnvoll für Netzwerkanwendungen.
  2. User=myappuser lässt den Dienst unter einem dedizierten, unprivilegierten Benutzer laufen – sicherer als root.
  3. Restart=on-failure startet den Dienst neu, wenn er mit einem Fehler-Exit-Code beendet wurde, aber nicht nach einem bewussten systemctl stop.
  4. Der Pfad bei ExecStart muss immer absolut sein – relative Pfade werden nicht erkannt.

Schritt 3: Dateirechte setzen und Konfiguration laden

Die Unit-Datei soll les-, aber nicht ausführbar sein. Setze die Rechte und informiere systemd über die neue Datei:

sudo chmod 644 /etc/systemd/system/myapp.service
sudo systemctl daemon-reload

Wichtig: daemon-reload muss nach jeder Änderung an einer Unit-Datei ausgeführt werden. Ohne diesen Schritt arbeitet systemd noch mit der alten Konfiguration. Du kannst die Syntax der Datei vorab prüfen:

systemd-analyze verify /etc/systemd/system/myapp.service

Erscheint keine Ausgabe, ist die Syntax in Ordnung. Fehlermeldungen zeigen dir genau, welche Zeile das Problem verursacht.

Schritt 4: Dienst starten und Autostart einrichten

Jetzt kannst du den Dienst aktivieren und starten. enable richtet den Autostart ein, start startet den Dienst sofort:

sudo systemctl enable myapp.service
sudo systemctl start myapp.service

Alternativ in einem Schritt:

sudo systemctl enable --now myapp.service

Prüfe danach den Status:

sudo systemctl status myapp.service

Die Ausgabe zeigt dir den aktuellen Zustand (active (running) ist das Ziel), die PID, die letzten Logzeilen und ob Autostart aktiv ist (enabled).

Schritt 5: Dienst im laufenden Betrieb verwalten

Die wichtigsten Verwaltungsbefehle im Überblick:

# Dienst stoppen
sudo systemctl stop myapp.service

# Dienst neustarten
sudo systemctl restart myapp.service

# Nur Konfiguration neu laden (ohne Neustart, wenn die App das unterstützt)
sudo systemctl reload myapp.service

# Autostart deaktivieren
sudo systemctl disable myapp.service

# Prüfen, ob Autostart aktiv ist
sudo systemctl is-enabled myapp.service

# Alle aktiven Services auflisten
sudo systemctl list-units --type=service

Um alle Eigenschaften einer Unit anzuzeigen (nützlich zur Fehlersuche):

sudo systemctl show myapp.service

Schritt 6: Logs mit journalctl auslesen

systemd schreibt alle Ausgaben des Dienstes ins zentrale Journal. Mit journalctl -u filterst du gezielt nach deinem Service:

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

# Live-Ansicht (wie tail -f)
journalctl -u myapp.service -f

# Letzte 50 Zeilen
journalctl -u myapp.service -n 50

# Ausgabe ohne Pager (z. B. für Skripte)
journalctl -u myapp.service --no-pager

Tipp: Kombiniere -n und -f für eine Live-Ansicht mit einem begrenzten Anfangspuffer – praktisch beim Testen nach einer Konfigurationsänderung:

journalctl -u myapp.service -n 20 -f

Beende die Live-Ansicht mit Strg+C.

Schritt 7: Ausblick – systemd-Timer als Cron-Alternative

Wenn du einen Dienst nicht dauerhaft laufen lassen, sondern zu bestimmten Zeiten ausführen möchtest, bietet systemd eine elegante Alternative zu Cron: systemd-Timer. Ein Timer besteht aus zwei Unit-Dateien: dem bekannten .service (was ausgeführt wird) und einer .timer-Datei (wann).

Beispiel: täglicher Backup-Job. Erstelle zunächst den Service (ohne [Install], da der Timer ihn auslöst):

# /etc/systemd/system/backupjob.service
[Unit]
Description=Täglicher Backup-Job

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup.sh

Dann die Timer-Unit:

# /etc/systemd/system/backupjob.timer
[Unit]
Description=Backupjob täglich um 02:00 Uhr

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

[Install]
WantedBy=timers.target

Timer laden, aktivieren und starten:

sudo systemctl daemon-reload
sudo systemctl enable --now backupjob.timer

# Status und nächste Ausführung prüfen
systemctl list-timers
systemctl status backupjob.timer

# Logs der vom Timer ausgelösten Service
journalctl -u backupjob.service

Persistent=true sorgt dafür, dass ein verpasster Lauf (z. B. durch Systemabschaltung) beim nächsten Bootvorgang nachgeholt wird – das kann Cron von Haus aus nicht.

Troubleshooting

  1. daemon-reload vergessen: Nach jeder Änderung an der Unit-Datei zwingend sudo systemctl daemon-reload ausführen, sonst arbeitet systemd mit der alten Konfiguration.
  2. Service startet nicht – Unit not found: Dateiname und Service-Name müssen übereinstimmen. Tippfehler im Pfad prüfen.
  3. ExecStart schlägt fehl: Stelle sicher, dass der Pfad absolut ist und die Datei ausführbar ist (chmod +x /pfad/zur/app).
  4. Berechtigungsfehler: Wenn User= gesetzt ist, muss dieser Benutzer Lesezugriff auf alle Dateien haben, die der Dienst benötigt (Programm, Konfiguration, Logs).
  5. Restart=always stoppt nicht mehr: systemctl stop startet den Dienst bei Restart=always sofort neu. Für normalen Betrieb Restart=on-failure bevorzugen.
  6. RestartSec=0 führt zu CPU-Schleife: Mindestens RestartSec=1s setzen, um eine Absturz-Neustart-Schleife zu verhindern.
  7. Start request repeated too quickly: systemd schützt sich vor Neustart-Schleifen. StartLimitBurst und StartLimitIntervalSec in [Unit] anpassen oder die Ursache des Absturzes beheben.
  8. Fehler nur in stderr, nicht im Journal: Beide Direktiven setzen: StandardOutput=journal und StandardError=journal.
  9. Timer läuft nicht: OnCalendar-Syntax prüfen (Format: DayOfWeek Year-Month-Day Hour:Minute:Second). Mit systemd-analyze calendar testen: systemd-analyze calendar daily.

Häufige Fragen

Muss ich nach jedem Start des Systems daemon-reload ausführen?

Nein. daemon-reload ist nur nach Änderungen an Unit-Dateien nötig. systemd liest beim Bootvorgang automatisch alle Unit-Dateien aus den Standardpfaden ein.

Was ist der Unterschied zwischen enable und start?

enable richtet den Autostart ein (erstellt einen symbolischen Link), startet den Dienst aber nicht sofort. start startet den Dienst nur für die aktuelle Session. Für beides zusammen: systemctl enable --now myapp.service.

Wie führe ich einen Service als bestimmter Benutzer aus?

Setze User=benutzername und Group=gruppenname in der [Service]-Sektion. Der Benutzer muss auf dem System existieren. Für systemweite Services empfiehlt es sich, einen dedizierten System-Benutzer ohne Login-Shell anzulegen: sudo useradd -r -s /usr/sbin/nologin myappuser.

Kann ich mehrere ExecStart-Direktiven verwenden?

Bei Type=simple ist nur ein ExecStart erlaubt. Für mehrere Befehle nutze ExecStartPre= für vorbereitende Schritte oder verwende Type=oneshot, bei dem mehrere ExecStart-Zeilen möglich sind.

Wo liegen User-Services (ohne sudo)?

User-spezifische Services ohne Root-Rechte gehören nach ~/.config/systemd/user/ und werden mit systemctl --user verwaltet. WantedBy=multi-user.target gilt dort nicht – stattdessen WantedBy=default.target verwenden.

Wie unterscheidet sich ein systemd-Timer von einem Cron-Job?

systemd-Timer protokollieren alle Ausführungen vollständig im Journal (aufrufbar via journalctl -u dienstname.service), können verpasste Ausführungen nachholen (Persistent=true) und sind in die Abhängigkeitsverwaltung von systemd integriert. Cron ist einfacher einzurichten, bietet aber weniger Kontrolle und Transparenz. Für neue Linux-Setups sind Timer die modernere Wahl. Mehr dazu in der Anleitung zu Cron und Crontab – Grundlagen für Linux.

Fazit

Mit einer gut strukturierten Unit-Datei und den grundlegenden systemctl-Befehlen hast du volle Kontrolle über eigene Dienste auf Linux-Systemen. Die drei Sektionen [Unit], [Service] und [Install] decken alle wichtigen Konfigurationspunkte ab. Denke immer daran: nach jeder Änderung an der Unit-Datei kommt daemon-reload. journalctl -u ist dein erstes Werkzeug bei der Fehlersuche. Und wenn du periodische Aufgaben benötigst, sind systemd-Timer eine saubere, gut protokollierte Alternative zu klassischen Cron-Jobs.

Weiterführende Anleitungen und Quellen

  1. Cron und Crontab – Grundlagen für Linux – Zeitgesteuerte Aufgaben mit Cron einrichten und mit systemd-Timern vergleichen
  2. Linux-Benutzer, Gruppen und Rechte – chmod, chown, sudo – Berechtigungen richtig setzen für Service-Benutzer und Programmpfade
  3. SSH-Key-Authentifizierung einrichten (Linux & Windows) – Sicherer Remote-Zugriff für die Administration deiner Server
  4. Alle Linux-Anleitungen auf s-edv.com
  5. Offizielle Dokumentation: systemd.service(5) – Linux manual page
  6. Offizielle Dokumentation: systemd.exec(5) – Linux manual page