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

systemd-Service selbst erstellen und verwalten

systemd-Service sauber erstellen und verwalten: Unit-Datei verstehen, Dienst starten, Status prüfen, Logs lesen und jeden Schritt direkt verifizieren.

systemd-Service selbst erstellen und verwalten

systemd-Services sind die Grundlage dafür, dass Programme unter Linux zuverlässig im Hintergrund laufen, beim Systemstart automatisch starten und sauber überwacht werden können. Wenn du einen eigenen Dienst betreiben willst, etwa ein Skript, eine kleine Anwendung oder einen internen Helferprozess, landest du auf modernen Linux-Systemen fast immer bei systemd.

Wichtig ist dabei: Ein systemd-Service ist nicht einfach nur "ein Befehl, der gestartet wird". systemd merkt sich, ob der Dienst läuft, ob er abgestürzt ist, ob er automatisch starten soll und welche Logs er geschrieben hat. Genau deshalb lohnt es sich, das einmal sauber zu verstehen. In dieser Anleitung gehen wir Schritt für Schritt vor und prüfen nach jedem wichtigen Punkt, ob dein Service wirklich das tut, was er soll.

Voraussetzungen

  • Ein Linux-System mit systemd, zum Beispiel Debian, Ubuntu, RHEL, Rocky, Fedora oder openSUSE
  • Ein Benutzer mit sudo-Rechten oder direkter Root-Zugang
  • Grundlegender Umgang mit dem Terminal
  • Ein Testsystem oder eine unkritische Umgebung, damit du das Verhalten gefahrlos üben kannst

Wichtig vorab: Baue den ersten eigenen Service nicht direkt um eine produktive Anwendung herum. Für das Verständnis ist ein bewusst einfaches Demo-Beispiel besser, weil du damit Status, Logs und Startverhalten isoliert testen kannst.

Schritt 1: Eine kleine Demo-Anwendung anlegen

Damit du systemd nicht nur theoretisch anschaust, erzeugen wir zuerst ein minimales Skript, das dauerhaft läuft und regelmäßig eine Zeile ausgibt. Genau so lässt sich später gut prüfen, ob der Dienst wirklich gestartet wurde und ob Logs im Journal ankommen.

sudo mkdir -p /opt/myapp/bin
sudo nano /opt/myapp/bin/myapp.sh

Trage in die Datei diesen Inhalt ein:

#!/bin/bash
while true; do
  echo "myapp läuft: $(date '+%F %T')"
  sleep 30
done

Danach machst du das Skript ausführbar:

sudo chmod 755 /opt/myapp/bin/myapp.sh

Verifizieren: Der Schritt ist erfolgreich, wenn die Datei existiert und ausführbar ist. Prüfe das mit:

ls -l /opt/myapp/bin/myapp.sh

Erwartung: Die Ausgabe beginnt bei der Datei mit -rwxr-xr-x oder zeigt zumindest ein Execute-Bit für den Besitzer. Wenn dort kein x steht, kann systemd das Skript später nicht sauber starten.

Schritt 2: Verstehen, wie [Unit], [Service] und [Install] zusammenarbeiten

Bevor du die Unit-Datei schreibst, solltest du wissen, wofür die drei Bereiche da sind:

  • [Unit] beschreibt den Dienst und seine Beziehungen zu anderen Units
  • [Service] enthält die eigentliche Laufzeitkonfiguration
  • [Install] steuert, ob und wann der Dienst automatisch eingebunden wird

Die wichtigsten Direktiven für den Einstieg sind:

DirektiveBedeutung
Description=Freitext-Beschreibung des Dienstes
After=Startreihenfolge, zum Beispiel nach dem Netzwerk
Type=simpleStandard für Prozesse, die direkt im Vordergrund laufen
ExecStart=Der eigentliche Startbefehl mit absolutem Pfad
Restart=on-failureNeustart bei Fehlern, aber nicht nach bewusstem Stop
WorkingDirectory=Arbeitsverzeichnis des Dienstes
User= / Group=Unter welchem Benutzer und welcher Gruppe der Dienst läuft
WantedBy=multi-user.targetAutostart beim normalen Systemstart

Für den ersten systemd-Service brauchst du nicht jede Spezialoption. Entscheidend ist, dass du den Ablauf verstehst: systemd liest die Unit-Datei, kennt dann deinen Startbefehl, überwacht den Prozess und kann ihn auf Wunsch beim Boot automatisch starten.

Verifizieren: Du hast diesen Schritt verstanden, wenn du die drei Abschnitte so zusammenfassen kannst: [Unit] erklärt den Rahmen, [Service] definiert das Laufverhalten, [Install] kümmert sich um den Autostart.

Schritt 3: Eigene Unit-Datei unter /etc/systemd/system/ erstellen

Jetzt legst du den eigentlichen Service an. Der Dateiname bestimmt auch den späteren Servicenamen.

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

Füge diesen Inhalt ein:

[Unit]
Description=Meine Demo-Anwendung mit systemd
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/myapp.sh
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Warum genau diese Fassung?

  • Type=simple passt hier, weil das Skript direkt im Vordergrund läuft
  • ExecStart= nutzt einen absoluten Pfad, was bei systemd Pflicht ist
  • Restart=on-failure ist ein guter Standard, weil Abstürze abgefangen werden, ein bewusstes stop aber respektiert wird
  • StandardOutput=journal und StandardError=journal sorgen dafür, dass du die Ausgaben später sauber mit journalctl lesen kannst

Verifizieren: Prüfe direkt, ob die Datei am richtigen Ort liegt:

ls -l /etc/systemd/system/myapp.service

Erwartung: Die Datei wird angezeigt. Wenn du sie versehentlich unter /etc/systemd/system/myapp ohne .service oder in einem falschen Pfad angelegt hast, findet systemd sie später nicht als Service.

Schritt 4: systemd neu laden und Syntax prüfen

systemd liest neue oder geänderte Unit-Dateien nicht automatisch sofort ein. Genau dafür gibt es daemon-reload.

sudo systemctl daemon-reload
systemd-analyze verify /etc/systemd/system/myapp.service

Wenn systemd-analyze verify keine Ausgabe zeigt, ist das ein gutes Zeichen. Bei Fehlern bekommst du normalerweise eine konkrete Zeile oder eine Direktive genannt.

Verifizieren: Dieser Schritt ist erfolgreich, wenn daemon-reload ohne Fehler durchläuft und systemd-analyze verify keine Fehlermeldung ausgibt. Wenn du hier schon Fehler siehst, gehst du noch nicht zum Starten über.

Schritt 5: Dienst starten und Status lesen

Jetzt startest du den Dienst zum ersten Mal bewusst manuell. Das ist wichtig, weil du so erst das Laufverhalten prüfst, bevor du den Autostart aktivierst.

sudo systemctl start myapp.service
sudo systemctl status myapp.service

Bei einem korrekt laufenden Dienst solltest du im Status etwas wie active (running) sehen. Dort findest du auch die PID, den Startzeitpunkt und die letzten Logzeilen.

Verifizieren: Der Schritt ist erfolgreich, wenn systemctl status myapp.service den Status active (running) zeigt. Wenn dort failed oder activating (auto-restart) steht, ist der Dienst noch nicht sauber gestartet und du gehst zuerst zu den Logs in Schritt 8.

Schritt 6: Autostart aktivieren und prüfen

Erst wenn der Dienst manuell sauber läuft, aktivierst du den Autostart.

sudo systemctl enable myapp.service
sudo systemctl is-enabled myapp.service

Du kannst Start und Aktivierung auch kombinieren:

sudo systemctl enable --now myapp.service

Wichtig ist die Unterscheidung:

  • start = läuft jetzt
  • enable = startet auch bei künftigen Boots

Verifizieren: Der Schritt ist erfolgreich, wenn systemctl is-enabled myapp.service mit enabled antwortet. Wenn der Dienst läuft, aber hier disabled steht, startet er beim nächsten Reboot nicht automatisch.

Schritt 7: Dienst im Alltag verwalten

Im Alltag arbeitest du meist mit diesen Befehlen:

sudo systemctl stop myapp.service
sudo systemctl start myapp.service
sudo systemctl restart myapp.service
sudo systemctl disable myapp.service
sudo systemctl reload myapp.service
sudo systemctl show myapp.service

reload funktioniert nur dann sinnvoll, wenn die Anwendung selbst ein Nachladen ihrer Konfiguration unterstützt. Wenn nicht, bleibt meist nur restart.

Verifizieren: Teste bewusst einmal stop und danach status. Erwartung: Der Dienst steht dann nicht mehr auf active (running). Danach startest du ihn wieder und prüfst erneut auf active (running). So merkst du sofort, ob du die Steuerbefehle wirklich richtig einsetzt.

Schritt 8: Logs mit journalctl auswerten

Die Logs sind bei systemd oft der schnellste Weg zur Ursache. Weil unser Demo-Skript regelmäßig Text ausgibt, solltest du jetzt auch etwas im Journal sehen.

journalctl -u myapp.service -n 20
journalctl -u myapp.service -f

Die erste Variante zeigt die letzten 20 Zeilen, die zweite bleibt live dran. Eine Live-Ansicht beendest du mit Strg+C.

Verifizieren: Dieser Schritt ist erfolgreich, wenn du im Journal Zeilen wie myapp läuft: mit Zeitstempel siehst. Wenn der Dienst laut status läuft, aber im Journal gar nichts erscheint, fehlen oft sinnvolle Ausgaben der Anwendung oder die Ausgabe wird nicht im Journal erfasst.

Schritt 9: systemd-Timer als nächster Ausbauschritt

Nicht jede Aufgabe muss als dauerhaft laufender Dienst betrieben werden. Für periodische Aufgaben ist ein systemd-Timer oft die modernere Alternative zu Cron. Das Prinzip ist einfach: Eine .service-Datei beschreibt, was ausgeführt wird, und eine .timer-Datei beschreibt, wann es passieren soll.

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

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /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
sudo systemctl daemon-reload
sudo systemctl enable --now backupjob.timer
systemctl list-timers
systemctl status backupjob.timer

Verifizieren: Ein Timer ist sauber eingerichtet, wenn er in systemctl list-timers auftaucht und dir dort eine nächste Ausführung angezeigt wird. Für die eigentliche Logprüfung schaust du später in die zugehörige .service-Unit, nicht nur in den Timer selbst.

Troubleshooting

  • Service startet nicht ? Unit not found: Dateiname und Servicename stimmen nicht zusammen oder die Datei liegt nicht unter /etc/systemd/system/.
  • daemon-reload vergessen: Nach jeder Änderung an der Unit-Datei musst du sudo systemctl daemon-reload ausführen.
  • ExecStart schlägt fehl: Der Pfad ist nicht absolut oder das Skript ist nicht ausführbar.
  • status zeigt failed: Direkt mit journalctl -u dienstname.service -n 50 nachsehen, was die Anwendung wirklich gemeldet hat.
  • Der Dienst läuft als falscher Benutzer: Prüfe User= und Group= in der Unit-Datei und gleiche das mit den Dateirechten deiner Anwendung ab.
  • restart-Schleife: Wenn ein Dienst sofort wieder abstürzt und systemd ständig neu startet, ist meist die eigentliche Anwendung kaputt, nicht systemd selbst.
  • reload funktioniert nicht: Viele Anwendungen unterstützen kein Nachladen. Dann brauchst du statt reload einen echten restart.
  • Timer läuft nicht: Mit systemd-analyze calendar kannst du den Zeitplan prüfen, zum Beispiel systemd-analyze calendar '*-*-* 02:00:00'.

Häufige Fragen

Was ist der Unterschied zwischen start und enable?

start startet den Dienst sofort. enable sorgt dafür, dass er auch beim nächsten Systemstart automatisch startet. Beides ist nicht dasselbe.

Muss ich nach jeder Änderung daemon-reload ausführen?

Ja, nach jeder Änderung an einer Unit-Datei. Sonst arbeitet systemd weiter mit der alten Version.

Warum brauche ich einen absoluten Pfad bei ExecStart?

Weil systemd keine Shell ist, die erst deinen aktuellen Pfadkontext errät. Der Startbefehl muss eindeutig und vollständig angegeben werden.

Wann nutze ich User= und Group=?

Immer dann, wenn der Dienst nicht als root laufen soll oder darf. Für echte Anwendungen ist ein eigener Dienstbenutzer oft die sauberere und sicherere Wahl.

Wo sehe ich die Fehler meines Dienstes?

Fast immer zuerst in systemctl status und danach im Detail mit journalctl -u dienstname.service.

Wann ist ein Timer besser als Cron?

Wenn du bessere Integration in systemd, saubere Logs im Journal und eine nachvollziehbare Verwaltung über dieselben Werkzeuge willst. Für neue Linux-Setups ist das oft die modernere Wahl.

Fazit

Ein eigener systemd-Service ist viel weniger magisch, wenn du den Ablauf einmal sauber durchgehst: Skript oder Programm anlegen, Unit-Datei schreiben, daemon-reload, Dienst starten, Status prüfen, Logs lesen, erst danach den Autostart aktivieren. Genau diese Reihenfolge verhindert die meisten typischen Fehler und macht die Fehlersuche deutlich einfacher.

Als nächster passender Grundlagenbaustein eignet sich unsere Anleitung zu Linux-Benutzern, Gruppen und Rechten, weil viele Dienste nicht an systemd selbst, sondern an falschen Besitzern, Gruppen oder Dateirechten scheitern. Danach passt je nach Ziel entweder Cron oder die Anleitung zur SSH-Key-Authentifizierung.

Weiterführende Anleitungen und Quellen

Quellen: systemd.service(5) ? man7.org, systemctl(1) ? man7.org, journalctl(1) ? man7.org, systemd.timer(5) ? man7.org.