Articles

Erstellen eines Linux-Dienstes mit systemd

Posted on
Basteln your own services – Photo by Jeff Sheldon on Unsplash

Während des Schreibens von Webanwendungen, muss ich oft rechenintensive Aufgaben an ein asynchrones Worker-Skript auslagern, Aufgaben für später planen oder sogar einen Daemon schreiben, der auf einen Socket hört, um direkt mit Clients zu kommunizieren.

Auch wenn es manchmal bessere Werkzeuge für diese Aufgabe gibt – denken Sie immer daran, zuerst bestehende Software zu verwenden, wie z.B. einen Task-Queue-Server -, kann das Schreiben eines eigenen Dienstes Ihnen ein Maß an Flexibilität bieten, das Sie nie erhalten werden, wenn Sie an die Einschränkungen von Software von Drittanbietern gebunden sind.

Das Coole daran ist, dass es ziemlich einfach ist, einen Linux-Dienst zu erstellen: Verwenden Sie Ihre bevorzugte Programmiersprache, um ein langlaufendes Programm zu schreiben, und verwandeln Sie es mit systemd in einen Dienst.

Lassen Sie uns einen kleinen Server mit PHP erstellen. Ich sehe schon, wie sich Ihre Augenbrauen heben, aber es funktioniert erstaunlich gut. Wir werden den UDP-Port 10000 abhören und jede empfangene Nachricht mit einer ROT13-Transformation zurückgeben:

Lassen Sie uns ihn starten:

$ php server.php

Und testen Sie es in einem anderen Terminal:

$ nc -u 127.0.0.1 10000
Hello, world!
Uryyb, jbeyq!

Cool, es funktioniert. Jetzt wollen wir, dass dieses Skript immer läuft, im Falle eines Fehlers (unerwarteter Exit) neu gestartet wird und sogar Server-Neustarts überlebt. An dieser Stelle kommt systemd ins Spiel.

In einen Dienst verwandeln

Lassen Sie uns eine Datei mit dem Namen /etc/systemd/system/rot13.service erstellen:


Description=ROT13 demo service
After=network.target
StartLimitIntervalSec=0
Type=simple
Restart=always
RestartSec=1
User=centos
ExecStart=/usr/bin/env php /path/to/server.php

WantedBy=multi-user.target

Sie müssen Folgendes tun:

  • Setzen Sie Ihren aktuellen Benutzernamen nach User=
  • Setzen Sie den richtigen Pfad zu Ihrem Skript in ExecStart=

Das war’s. Jetzt können wir den Dienst starten:

$ systemctl start rot13

Und dafür sorgen, dass er beim Booten automatisch startet:

$ systemctl enable rot13

Weiter geht’s

Nun, da Ihr Dienst (hoffentlich) funktioniert, kann es wichtig sein, ein wenig tiefer in die Konfigurationsoptionen einzutauchen, um sicherzustellen, dass er immer so funktioniert, wie Sie es erwarten.

In der richtigen Reihenfolge starten

Sie haben sich vielleicht gefragt, was die After= Direktive bedeutet. Sie bedeutet einfach, dass Ihr Dienst gestartet werden muss, nachdem das Netzwerk bereit ist. Wenn Ihr Programm erwartet, dass der MySQL-Server betriebsbereit ist, sollten Sie hinzufügen:

After=mysqld.service

Neustart beim Beenden

Standardmäßig startet systemd Ihren Dienst nicht neu, wenn das Programm aus irgendeinem Grund beendet wird. Das ist normalerweise nicht das, was Sie für einen Dienst wollen, der immer verfügbar sein muss, also weisen wir ihn an, beim Beenden immer neu zu starten:

Restart=always

Sie könnten auch on-failure verwenden, um nur neu zu starten, wenn der Exit-Status nicht 0 ist.

Standardmäßig versucht systemd nach 100ms einen Neustart. Sie können die Anzahl der Sekunden, die gewartet werden soll, bevor ein Neustart versucht wird, festlegen:

RestartSec=1

Die Falle vermeiden: das Startlimit

Ich persönlich bin mehr als einmal in diese Falle getappt. Standardmäßig, wenn Sie Restart=always so konfigurieren, wie wir es getan haben, gibt systemd den Neustart des Dienstes auf, wenn er mehr als 5 Mal innerhalb eines Intervalls von 10 Sekunden nicht gestartet wird. Für immer.

Dafür sind zwei Konfigurationsoptionen verantwortlich:

StartLimitBurst=5
StartLimitIntervalSec=10

Die RestartSecDirektive hat ebenfalls einen Einfluss auf das Ergebnis: Wenn Sie einstellen, dass der Dienst nach 3 Sekunden neu gestartet wird, können Sie niemals 5 fehlgeschlagene Wiederholungsversuche innerhalb von 10 Sekunden erreichen.

Die einfache Lösung, die immer funktioniert, ist, StartLimitIntervalSec=0 zu setzen. Auf diese Weise wird systemd immer versuchen, den Dienst neu zu starten.

Es ist jedoch eine gute Idee, RestartSec auf mindestens 1 Sekunde zu setzen, um Ihren Server nicht zu sehr zu belasten, wenn die Dinge schief laufen.

Als Alternative können Sie die Standardeinstellungen belassen und systemd mit StartLimitAction=reboot bitten, Ihren Server neu zu starten, wenn das Startlimit erreicht ist.

Ist das wirklich alles?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.