
Und dann kamen SystemD Services...
« | 07 Apr 2024 | »systemd ist die Zukunft. Alle neuen Linux Dienste nutzen diesen Standard um sich im System zu registrieren.
Auch falsch! (Langsam zeichnet sich ein Muster ab.)
Mir bleibt wirklich gar nichts erspart, und somit kommen jetzt
(beruflich wie privat) auch noch .service
Dateien in meine Welt.
Eigentlich ist systemd
der ausgereifteste Ansatz, wie man Dienste verwalten
kann. Denn hier werden nicht lose Scripts irgendwie ausgeführt, sondern ein
verwalteter und definierter Hauptdienst startet und verwaltet alles Andere.
Init-Scripts sind quasi selbstverantwortlich, wie sie ihre zugehörigen
Prozesse starten. Ob hier 1x oder 2x gefork()
t wird, ob man den Account
wechselt, das ist alles ein Script-Geheimnis.
systemd
versucht uns alle Optionen als Konfiguration zur Verfügung zu
stellen, so dass wir einfach nur noch Variablen (bzw. Einstellungen) setzen
und kein selbstgeschriebener Code mehr notwendig ist.
Man legt quasi eine INI-Datei,
als “Service-Unit” im Verzeichnis /etc/systemd/system/
an, deren Inhalt
beschreibt, wie der Daemon gestartet werden soll.
Beispiel: /etc/systemd/system/myserviced.service
[Unit]
Description=MyService Daemon
Requires=other_daemon1,other_daemon2
[Service]
Type=exec
ExecStart=/usr/bin/myserviced
[Install]
WantedBy=multi-user.target
Der exec Typ
Es gibt mehrere “Typen” von Diensten, und exec
ist (neben dem ähnlich Typ simple
)
der einfachste, weil sich hier systemd
um die gesamte Laufzeit kümmert.
Es startet den Prozess im Hintergrund und überwacht ihn. Wird von außen die
Beendigung eingefordert, schickt systemd
die notwendigen Standard-Signale an
den Prozess.
Der oneshot Typ
Manchmal bedeutet “Dienst” auch nur “eine-Aktion-und-fertig”.
Genau dafür ist der oneshot
-Typ erschaffen worden. Das ausgeführte Programm
darf sich nämlich nach seiner “Aktion” beenden, aber systemd
behandelt den
Dienst weiter als “laufend”, obwohl gar kein Prozess mehr am Arbeiten ist.
Das hilft einem vor allem bei Abhängigkeiten, wenn ein Dienst einen anderen
braucht. Wird nämlich ein Dienst beendet, beendet systemd
auch alle von
ihm abhängigen Dienste.
Mit oneshot
lässt sich so eine Kette von Aufgaben bilden, die
hintereinander ausgeführt werden, die sich aber nach ihrem Ende nicht
gegenseitig abbrechen.
Der forking Typ
Viele alte Init-Script Daemons haben sich selbst verwaltet, also sich selbst
gefork()
t, und für solche Fälle ist dieser Typ gut geeignet.
Hier kann man dann eine PID-Datei und eine Beendigungsroutine konfigurieren,
um geforkte Dienste zu beenden:
[Unit]
Description=MyService Daemon
Requires=other_daemon1,other_daemon2
[Service]
Type=forking
ExecStart=/usr/bin/myserviced --start-me
ExecStop=/usr/bin/myserviced --kill-me
PIDFile=/var/run/myserviced.pid
[Install]
WantedBy=multi-user.target
Und vieles mehr
Dann gibt es da noch diverse andere Typen, die über dbus
mit ihrem Prozess
kommunizieren, aber die sind für meine Zwecke zu komplex.
Außerdem lassen sich in systemd
Service Dateien jede Menge Sonderfälle
spezifizieren wie:
- Wiederhole den Start X mal, wenn sich der Prozess beendet/aufhängt.
- Interpretiere/Ignoriere den Exit-Code eines Prozesses anders.
- Führe ein anderes Programm/Script vor oder nach dem Daemon-Prozess aus.
- Definiere Timeouts, wie lange Einzelschritte dauern dürfen.
- Festlegung, ob oder welche Kindprozesse mitüberwacht und mitverwaltet werden sollen.
- Wechsele den Account, das Verzeichnis oder das Environment
- Definition von Abhängigkeiten, was vor oder nach wem gestartet wird, und was automatisch wieder beendet werden soll, wenn der eigene Dienst terminiert.
- usw., siehe: systemd.service
Nutzung von systemctl
Das Zentrale Tool zur Verwaltung ist systemctl
.
Ist eine .service
Datei angelegt, werden mit systemctl daemon-reload
alle Service-Dateien eingelesen und integriert.
systemctl enable myserviced.service
aktiviert das Service für den
automatischen Start.
Mit systemctl start|stop|status myserviced
lässt sich wie mit klassischen
Init-Scripts ein Daemon starten, stoppen oder dessen aktueller Status ausgeben.
Fazit
Tja, wie schon mal gesagt:
systemd
ist super, aber…
Ich werde also künftig .service
Dateien mit Typ forking
anlegen,
die aber auf meine alten Init-Scripts verweisen.
Der Grund dafür: Docker
Leider ist systemd
nicht ohen Workarounds in Docker-Containern nutzbar,
Init-Scripts funktionieren dort aber wie gehabt.
Es macht für mich also Sinn, das “neue” System mit meiner “alten” Technik zu verbinden.
Aber gäbe es die Container-Einschränkung nicht, wäre systemd
vermutlich
genau das, was ich in Linux immer vermisst habe und was in Windows seit NT 4
Standard ist:
Nämlich eine ordentliche Instanz zur zentralen und einheitlichen
Verwaltung von System-Diensten.