Systemd ist das Standard-Init-System moderner Linux-Distributionen. Es startet Dienste, verwaltet Abhängigkeiten und überwacht Prozesse. Hier lernen Sie, eigene Services zu erstellen.
Systemd-Grundlagen
Wichtige Verzeichnisse
/etc/systemd/system/ # Eigene Services (höchste Priorität)
/run/systemd/system/ # Runtime-Services
/lib/systemd/system/ # Distributions-Services
Unit-Typen
| Typ | Endung | Verwendung |
|---|
| Service | .service | Daemon/Dienst |
| Socket | .socket | Socket-Aktivierung |
| Timer | .timer | Geplante Aufgaben |
| Mount | .mount | Dateisysteme |
| Target | .target | Gruppierung |
Service erstellen
Einfacher Service
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=network.target
[Service]
Type=simple
User=myuser
Group=mygroup
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/start.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target
Service aktivieren
# Systemd neu laden
systemctl daemon-reload
# Service aktivieren (Autostart)
systemctl enable myapp
# Service starten
systemctl start myapp
# Status prüfen
systemctl status myapp
Service-Typen
Type=simple (Standard)
[Service]
Type=simple
ExecStart=/usr/bin/myapp
# Prozess bleibt im Vordergrund
Type=forking
[Service]
Type=forking
PIDFile=/var/run/myapp.pid
ExecStart=/usr/bin/myapp --daemon
# Prozess forkt sich selbst
Type=oneshot
[Service]
Type=oneshot
ExecStart=/usr/local/bin/cleanup.sh
RemainAfterExit=yes
# Für einmalige Tasks
Type=notify
[Service]
Type=notify
ExecStart=/usr/bin/myapp
# Prozess sendet sd_notify() wenn bereit
Konfigurationsoptionen
[Unit] Section
[Unit]
# Beschreibung
Description=My Application Service
# Dokumentation
Documentation=https://example.com/docs
# Abhängigkeiten
After=network.target mysql.service
Requires=mysql.service
Wants=redis.service
# Konflikte
Conflicts=other.service
[Service] Section
[Service]
# Prozess-Typ
Type=simple
# Benutzer/Gruppe
User=www-data
Group=www-data
# Arbeitsverzeichnis
WorkingDirectory=/opt/myapp
# Befehle
ExecStartPre=/opt/myapp/pre-start.sh
ExecStart=/opt/myapp/start.sh
ExecStartPost=/opt/myapp/post-start.sh
ExecStop=/opt/myapp/stop.sh
ExecReload=/bin/kill -HUP $MAINPID
# Umgebungsvariablen
Environment="NODE_ENV=production"
Environment="PORT=3000"
EnvironmentFile=/etc/myapp/env
# Neustart-Verhalten
Restart=always
RestartSec=5
StartLimitInterval=60
StartLimitBurst=3
# Timeouts
TimeoutStartSec=30
TimeoutStopSec=30
# Ressourcenlimits
LimitNOFILE=65535
LimitNPROC=4096
[Install] Section
[Install]
# Wann starten
WantedBy=multi-user.target
# Aliase
Alias=myapp.service
Restart-Optionen
Restart-Verhalten
| Wert | Beschreibung |
|---|
| no | Nie neu starten |
| always | Immer neu starten |
| on-failure | Bei Fehler (Exit != 0) |
| on-abnormal | Bei Signal/Timeout |
| on-abort | Bei Signal |
| on-success | Bei Exit = 0 |
Beispiel mit Limits
[Service]
Restart=on-failure
RestartSec=10
StartLimitInterval=300
StartLimitBurst=5
# Max 5 Neustarts in 5 Minuten
Umgebungsvariablen
Direkt in Service
[Service]
Environment="NODE_ENV=production"
Environment="PORT=3000"
Environment="DB_HOST=localhost"
Aus Datei
[Service]
EnvironmentFile=/etc/myapp/myapp.env
# /etc/myapp/myapp.env
NODE_ENV=production
PORT=3000
DB_HOST=localhost
Praktische Beispiele
Node.js Application
# /etc/systemd/system/nodeapp.service
[Unit]
Description=Node.js Application
After=network.target
[Service]
Type=simple
User=nodeapp
WorkingDirectory=/opt/nodeapp
ExecStart=/usr/bin/node /opt/nodeapp/server.js
Restart=on-failure
RestartSec=10
Environment=NODE_ENV=production
Environment=PORT=3000
# Graceful shutdown
KillMode=mixed
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
Python-Anwendung
# /etc/systemd/system/pythonapp.service
[Unit]
Description=Python Application
After=network.target
[Service]
Type=simple
User=pythonapp
Group=pythonapp
WorkingDirectory=/opt/pythonapp
ExecStart=/opt/pythonapp/venv/bin/python app.py
Restart=always
RestartSec=5
Environment="PYTHONUNBUFFERED=1"
[Install]
WantedBy=multi-user.target
Gunicorn/Django
# /etc/systemd/system/gunicorn.service
[Unit]
Description=Gunicorn Daemon
After=network.target
[Service]
Type=notify
User=www-data
Group=www-data
WorkingDirectory=/opt/django-app
ExecStart=/opt/django-app/venv/bin/gunicorn \
--workers 4 \
--bind unix:/run/gunicorn.sock \
--access-logfile /var/log/gunicorn/access.log \
--error-logfile /var/log/gunicorn/error.log \
myproject.wsgi:application
ExecReload=/bin/kill -s HUP $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
Java-Anwendung
# /etc/systemd/system/javaapp.service
[Unit]
Description=Java Application
After=network.target
[Service]
Type=simple
User=javaapp
WorkingDirectory=/opt/javaapp
ExecStart=/usr/bin/java -jar /opt/javaapp/app.jar
Restart=on-failure
RestartSec=10
Environment="JAVA_OPTS=-Xms256m -Xmx512m"
SuccessExitStatus=143
TimeoutStopSec=10
[Install]
WantedBy=multi-user.target
Sicherheitsoptionen
Hardening
[Service]
# Minimale Rechte
User=myuser
Group=mygroup
NoNewPrivileges=true
# Dateisystem einschränken
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadOnlyPaths=/etc
ReadWritePaths=/var/lib/myapp /var/log/myapp
# Netzwerk einschränken
PrivateNetwork=false
RestrictAddressFamilies=AF_INET AF_INET6
# Capabilities
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
Timer (Ersatz für Cron)
Timer-Unit
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily Backup Timer
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Zugehöriger Service
# /etc/systemd/system/backup.service
[Unit]
Description=Backup Service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
Timer aktivieren
systemctl enable --now backup.timer
systemctl list-timers
Timer-Syntax
# Täglich um 2:00
OnCalendar=*-*-* 02:00:00
# Stündlich
OnCalendar=hourly
OnCalendar=*-*-* *:00:00
# Montags um 9:00
OnCalendar=Mon *-*-* 09:00:00
# Alle 15 Minuten
OnCalendar=*:0/15
Verwaltungsbefehle
Service-Verwaltung
# Starten/Stoppen
systemctl start myapp
systemctl stop myapp
systemctl restart myapp
systemctl reload myapp
# Aktivieren/Deaktivieren
systemctl enable myapp
systemctl disable myapp
# Status
systemctl status myapp
systemctl is-active myapp
systemctl is-enabled myapp
Logs anzeigen
# Journal-Logs
journalctl -u myapp
# Live-Logs
journalctl -u myapp -f
# Seit Zeitpunkt
journalctl -u myapp --since "1 hour ago"
# Letzte 100 Zeilen
journalctl -u myapp -n 100
Debugging
# Service-Konfiguration prüfen
systemctl cat myapp
# Unit-Datei validieren
systemd-analyze verify myapp.service
# Boot-Analyse
systemd-analyze blame
Zusammenfassung
| Befehl | Funktion |
|---|
systemctl start | Starten |
systemctl stop | Stoppen |
systemctl restart | Neu starten |
systemctl enable | Autostart aktivieren |
systemctl status | Status anzeigen |
systemctl daemon-reload | Config neu laden |
journalctl -u service | Logs anzeigen |
Fazit
Systemd-Services bieten robuste Prozessverwaltung mit automatischem Neustart, Logging und Sicherheitsfeatures. Erstellen Sie für jede Anwendung einen eigenen Service mit angemessenen Restart-Optionen und Berechtigungen. Nutzen Sie Timer statt Cronjobs für bessere Integration und verwenden Sie Journalctl für zentralisiertes Logging.