
Ich möchte meine eigenen Unit-Dateien schreiben, systemd
um wirklich lang laufende Befehle 1 (in der Größenordnung von Stunden) zu verwalten. Beim Betrachten derArchWiki-Artikel zu systemdheißt es zur Wahl des Starttyps:
Type=simple
(Standard): systemd betrachtet den Dienst als sofort gestartet.Der Prozess darf sich nicht verzweigen. Verwenden Sie diesen Typ nicht, wenn andere Dienste über diesen Dienst bestellt werden müssen, es sei denn, er ist Socket-aktiviert.
Warum darf der Prozess überhaupt nicht verzweigt werden? Ist damit eine Verzweigung im Stil des Daemon-Beschwörungsprozesses gemeint (übergeordneter Prozess verzweigt, dann beendet) oder irgendeine andere Art der Verzweigung?
1 Ich möchte tmux/screen nicht, da ich eine elegantere Möglichkeit zum Überprüfen des Status und Neustarten des Dienstes möchte, ohne auf zurückgreifen zu müssen tmux send-keys
.
Antwort1
Der Dienst darf den fork
Systemaufruf ausführen. Systemd wird dies nicht verhindern oder es überhaupt bemerken, wenn es dies tut. Dieser Satz bezieht sich speziell auf die Praxis des Forkings am Anfang eines Daemons, um den Daemon von seinem übergeordneten Prozess zu isolieren. „Der Prozess darf nicht forken [und den übergeordneten Prozess verlassen, während der Dienst in einem untergeordneten Prozess ausgeführt wird]“.
Dermanpageerklärt dies ausführlicher und mit einer Formulierung, die nicht zu dieser besonderen Verwirrung führt.
Viele Programme, die als Daemons verwendet werden sollen, haben einen Modus (oft der Standardmodus), in dem sie sich beim Start von ihrem übergeordneten Prozess isolieren. Der Daemon startet, ruft auf fork()
und der übergeordnete Prozess wird beendet. Der untergeordnete Prozess ruft auf setsid()
, sodass er in seiner eigenen Prozessgruppe und Sitzung ausgeführt wird und den Dienst ausführt. Der Zweck besteht darin, dass der Daemon, wenn er von einer Shell-Befehlszeile aus aufgerufen wird, kein Signal vom Kernel oder von der Shell empfängt, selbst wenn etwas mit dem Terminal passiert, z. B. das Schließen des Terminals (in diesem Fall sendet die Shell SIGHUP an alle ihr bekannten Prozessgruppen). Dies führt auch dazu, dass der Wartungsprozess von init übernommen wird, das ihn beim Beenden abruft und so einenZombiewenn der Daemon von etwas gestartet wurde, das nicht wait()
für ihn vorgesehen wäre (dies würde nicht passieren, wenn der Daemon von einer Shell gestartet würde).
Wenn ein Daemon von einem Überwachungsprozess wie systemd gestartet wird, ist Forking kontraproduktiv. Der Überwachungsprozess soll den Dienst neu starten, wenn er abstürzt, also muss er wissen, ob der Dienst beendet wird, und das ist schwierig, wenn der Dienst kein direktes Kind des Überwachungsprozesses ist. Der Überwachungsprozess soll nie sterben und hat kein Kontrollterminal, also gibt es keine Bedenken hinsichtlich unerwünschter Signale oder Ernten. Es gibt also keinen Grund, warum der Dienstprozess kein Kind des Monitors sein sollte, und es gibt einen guten Grund dafür.
Antwort2
Ignorieren Sie diese Arch-Wiki-Seite.
In Bezug auf das Setting ist vieles falsch dargestellt Type
. Dies beschränkt sich nicht nur auf die Beschreibungen von simple
. Auch die Aussagen über forking
sind falsch.
Die richtigen Empfehlungen für diese Art von Dingen gibt es schon seit Jahrzehnten, länger als systemd selbst existiert, und reichen mindestens bis in die frühen 1990er Jahre zurück. Wie ich bereits erwähntehttps://unix.stackexchange.com/a/476608/5132, in der systemd-Dokumentation gibt es eine nachträglich aktualisierte Version der Empfehlungen für Dæmons, die im Wesentlichen wiederholt, was Daemontools-Benutzer, IBM, Benutzer inittab
und … nun ja … ich seit Jahrzehnten sagen. (Das war schon eine häufig gegebene Antwort, als ich sie 2001 als solche verfasste.)
Wiederholen:
Wenn Ihr Programm einen „Dämonisierungs“-Mechanismus besitzt, der insbesondere einen Kindprozess aufspaltet und den Elternprozess beendet,schalte es ausUndbenutze es nicht. Dank Daemontools und anderen, wo dies schon lange eine Voraussetzung ist, haben viele Programme die Fähigkeit entwickelt,nicht habenSolche Mechanismen wurden in den letzten mehr als 20 Jahren entwickelt, und andere wiederum sind von vornherein nicht auf die „Dämonisierung“ ausgelegt und können deshalb in ihrem Standardbetriebsmodus verwendet werden.
Service-Management-Subsysteme starten Serviceprozesseim Dæmon-Kontext bereits. Diese Prozesse müssen nicht „dämonisieren“. (Tatsächlich ist es bei vielen modernen Betriebssystemen ein Irrtum zu glauben, dass Programme überhauptdürfen"dämonisieren" aus einem Login-Sitzungskontext, worum es bei "dämonisieren" eigentlich geht.) Sie haben bereits die Umgebungswerte und offenen Dateideskriptoren, die für den Dämon-Kontext geeignet sind, und die verschiedenen Dinge, die durch "dämonisieren" tatsächlich erledigt werdenvereitelneinige der herkömmlichen Dinge, die von Service-Managern regelmäßig mit Daemons erledigt werden (z. B. das Erfassen ihrer Standardausgaben/-fehler in einem Protokoll).
Bevorzugen Sie Type=simple
, mit frühzeitiger Socket-Öffnung (wobei die Dienstverwaltung Server-Sockets öffnet und sie als bereits geöffnete Dateideskriptoren an das Serviceprogramm übergibt) oder Type=notify
.
Type=simple
behandelt den Dienst als bereit (sodass die angeforderten Dienste gestartet/gestoppt werden können), sobald der Dienstprozess beginnt, wobei beim frühen Öffnen des Sockets Socket-Verbindungssemantik eingesetzt wird, um Dienstclients an den Punkten zu verzögern, an denen sie versuchen, eine Verbindung zu Servern für den Dienst herzustellen, bis die Server tatsächlich bereit sind.Type=notify
hat den Nachteil, dass es systemd und Linux eigen ist (neben den Problemen, dass es bei kurzlebigen Prozessen wie dem Erzeugen einer Shell nicht funktionsfähig istsystemd-notify
und dass das Parsen von menschenlesbaren Formen in maschinenlesbare Formen in einem privilegierten Prozess erfolgt, bei dem Parserprobleme auftreten).Schon passiertin der Vergangenheit), hat aber den Vorteil, dass es eine feinere Kontrolle (aus Sicht des Serviceprogramms) darüber bietet, wann der Service tatsächlich als bereit betrachtet wird. Es ermöglicht auch eine gewisse Anpassung der Statusausgabe.
Serviceprogramme beider Typen können sich verzweigen. Es ist das Verzweigenund anschließendes Beenden des ursprünglichen ProzessesDas ist das Problem.
(Es sollte angemerkt werden, dass dies sowohl beim Ausführen von Programmen aus Shells als auch aus Service-Managern ein Problem darstellt, da Benutzer sehen, wie Programme beendet werden und fast sofort eine weitere Shell-Eingabeaufforderung verursachen. Tatsächlich hat gerade heute wieder jemand gefragt, wie man Programme aus der Shell ausführt, die sich aufspalten und das übergeordnete Element beenden, beiWarum wird ein Programm manchmal nicht im Terminal ausgeführt, wenn ich es ausführe?.)
Type=oneshot
ist in diesem speziellen Fall wahrscheinlich nicht das, was Sie wollen, da der Dienst erst dann als bereit gilt, wenn das gesamte Serviceprogramm vollständig ausgeführt wurde. Es hat seine Vorteile, aber so wie es klingt, gelten diese nicht für Sie.
Verwenden Sie niemals Type=forking
. Es sollte der letzte Ausweg aus Verzweiflung sein, da fast keine Programmetatsächlich das Protokoll sprechen. Sie machenetwas anderes, was in der Tatnichtdieses Protokoll, nicht korrekt interoperabel mit diesem Protokoll und signalisiert tatsächlich keine Bereitschaft.
Weiterführende Literatur
- Jonathan de Boyne Pollard (2001). Zu vermeidende Fehler beim Entwurf von Unix-Dämon-Programmen. Häufig gestellte Fragen.
- Jonathan de Boyne Pollard (2015).Sie müssen wirklich nicht dämonisieren. Wirklich.. Das systemd-Haus des Grauens.
- Jonathan de Boyne Pollard (2015).Readiness-Protokoll-Probleme mit Unix-Dämonen. Häufig gestellte Fragen.
- https://unix.stackexchange.com/a/401611/5132