Systemd Services – Unit-Files, Timer & Socket Activation (Artikel 007)
Der definitive Guide zu Systemd. Von einfachen Service-Units über Timer (Cron-Ersatz) bis hin zu fortgeschrittener Socket Activation und Dependency Management.
# Systemd Deep Dive: Mehr als nur systemctl start
TL;DR / Management Summary Systemd ist das Herzstück moderner Linux-Distributionen (Init-System PID 1). Es verwaltet nicht nur Dienste, sondern auch Timer (Cron-Ersatz), Mount-Points und Log-Dateien. Wer Systemd meistert, kann komplexe Abhängigkeiten definieren (“Starte Datenbank erst nach Netzwerk und Mount”), Services automatisch neu starten lassen (Self-Healing) und Ressourcen (CPU/RAM) limitieren.
# 1. Einführung & Architektur
Warum Systemd gewonnen hat.
Systemd parallelisiert den Boot-Vorgang massiv und startet Dienste “on-demand”.
# Unit-Typen Übersicht
- .service: Der Klassiker. Startet einen Dämon (z.B. Nginx).
- .timer: Zeitgesteuerte Ausführung (ersetzt Cron).
- .socket: Lauscht auf einem Port und startet den Service erst bei eingehendem Traffic.
- .target: Gruppierung von Units (z.B.
multi-user.targetentspricht Runlevel 3).
graph TD
A[System Boot] --> B[sysinit.target]
B --> C[basic.target]
C --> D[multi-user.target]
D --> E[nginx.service]
D --> F[postgresql.service]
E -.->|Depends on| G[network-online.target]
# 2. Der perfekte Service: Unit-File Anatomie
Wie man einen Dämon sauber definiert.
Unit-Files liegen in /etc/systemd/system/.
# Beispiel: Eigener Python-Webservice
Erstellen Sie /etc/systemd/system/myapp.service:
[Unit]
Description=My Python App
After=network.target postgresql.service
Wants=postgresql.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/python3 /var/www/myapp/server.py
Restart=always
RestartSec=5s
# Security Hardening (Optional aber empfohlen)
ProtectSystem=full
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Wichtig: Nach jeder Änderung an einer Unit-Datei müssen Sie systemctl daemon-reload ausführen, damit Systemd die Änderungen einliest.
# 3. Timer: Der bessere Cron
Warum Cron ausgedient hat.
Systemd Timer sind mächtiger als Cronjobs: Sie können Abhängigkeiten haben, loggen sauber ins Journal und können auf “Boot-Zeit” reagieren.
Schritt 1: Der Service (backup.service)
Definiert was getan wird (ohne [Install] Sektion!).
[Unit]
Description=Daily Backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
Schritt 2: Der Timer (backup.timer) Definiert wann es getan wird.
[Unit]
Description=Run backup daily
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
Starten mit: systemctl enable --now backup.timer.
# 4. Socket Activation: Ressourcen sparen
Starten nur bei Bedarf.
Idee: Systemd hält Port 8080 offen. Erst wenn ein Paket ankommt, wird der Webserver gestartet und übernimmt den Socket.
Schritt 1: Der Socket (myapp.socket)
[Socket]
ListenStream=8080
[Install]
WantedBy=sockets.target
Der Service (myapp.service) braucht dann keine Port-Konfiguration mehr, da er den File-Descriptor (FD) von Systemd erbt.
# 5. Day-2 Operations: Management & Limits
Kontrolle behalten.
# Resource Control (Cgroups)
Sie können verhindern, dass ein Dienst den Server lahmlegt.
# Temporär setzen
systemctl set-property myapp.service CPUQuota=50% MemoryMax=512M
# Oder permanent im [Service] Block:
# CPUQuota=50%
# MemoryMax=512M
# Dependency Analyse
Warum dauert der Boot so lange?
systemd-analyze blame
systemd-analyze critical-chain
# 6. Troubleshooting & “War Stories”
Wenn der Dienst nicht hochkommt.
# Story 1: “Der Exit-Code Loop”
Symptom: Status ist “activating (auto-restart)”.
Ursache: Das Skript stürzt sofort ab (Exit Code != 0), Systemd startet es neu (wegen Restart=always).
Lösung: journalctl -u myapp.service -f nutzen, um den Python/Bash Fehler zu sehen. Oft fehlen Umgebungsvariablen (EnvironmentFile=/etc/default/myapp).
# Story 2: “Timeout beim Boot”
Symptom: Boot hängt 90s bei “A start job is running for…”.
Ursache: Ein Service wartet auf das Netzwerk, aber das Netzwerk kommt nicht (z.B. falsche IP).
Lösung: Prüfen, ob Type=forking genutzt wird, obwohl der Prozess nicht forkt. Oft ist Type=simple die sicherere Wahl.
# 7. Fazit & Empfehlung
- Schreiben Sie eigene Unit-Files für alles, was dauerhaft laufen soll (keine
screenodernohupSessions!). - Nutzen Sie Timer statt Cron für komplexe Aufgaben.
- Härten Sie Services mit
ProtectSystemundUser, um die Sicherheit zu erhöhen.
# Anhang: Cheatsheet
| Aufgabe | Befehl |
|---|---|
| Service Status | systemctl status <name> |
| Logs ansehen | journalctl -u <name> -f |
| Boot-Analyse | systemd-analyze |
| Fehlgeschlagene Units | systemctl --failed |
| Änderungen laden | systemctl daemon-reload |