Wie geht systemd mit dem Tod eines untergeordneten Prozesses eines verwalteten Prozesses um?

Wie geht systemd mit dem Tod eines untergeordneten Prozesses eines verwalteten Prozesses um?

Wie wird systemdmit dem Tod der untergeordneten Prozesse verwaltet?

Angenommen, das systemdstartet den Daemon foo, der dann drei weitere Daemons startet: bar1, bar2, und bar3. Wird systemdetwas unternommen foo, wenn bar2es unerwartet beendet wird? Meines Wissens foowürde es unter Service Management Facility (SMF) auf Solaris beendet oder neu gestartet, wenn Sie nicht startddurch Ändern der Eigenschaft etwas anderes angeben ignore_error. systemdVerhält es sich anders?

Bearbeitung Nr. 1:

Ich habe einen Test-Daemon geschrieben, um systemddas Verhalten von zu testen. Der Daemon wird aufgerufen, mother_daemonweil er Kinder erzeugt.

#include <iostream>
#include <unistd.h>
#include <string>
#include <cstring>

using namespace std;

int main(int argc, char* argv[])
{
  cout << "Hi! I'm going to fork and make 5 child processes!" << endl;

  for (int i = 0; i < 5; i++)
    {
    pid_t pid = fork();

    if (pid > 0)
      {
    cout << "I'm the parent process, and i = " << i << endl;
      }
    if (pid == 0)
      {
      // The following four lines rename the process to make it easier to keep track of with ps
    int argv0size = strlen(argv[0]);
    string childThreadName = "mother_daemon child thread PID: ";
    childThreadName.append( to_string(::getpid()) );
    strncpy(argv[0],childThreadName.c_str(),argv0size + 25);

    cout << "I'm a child process, and i = " << i << endl;
    pause();
    // I don't want each child process spawning its own process
    break;
      }
    }
  pause();
  return 0;
  }

Dies wird mit einer systemdEinheit gesteuert, die heißt mother_daemon.service:

[Unit]
Description=Testing how systemd handles the death of the children of a managed process
StopWhenUnneeded=true

[Service]
ExecStart=/home/my_user/test_program/mother_daemon
Restart=always

Die Steuerung der mother_daemon.serviceEinheit erfolgt über mother_daemon.target:

[Unit]
Description=A target that wants mother_daemon.service
Wants=mother_daemon.service

sudo systemctl start mother_daemon.targetWenn ich (nach ) ausführe sudo systemctl daemon-reload, kann ich den übergeordneten Daemon und die fünf untergeordneten Daemons sehen.

Das Beenden eines der untergeordneten Elemente hat keine Auswirkung auf das übergeordnete Element. Das Beenden des übergeordneten Elements (und damit das Auslösen eines Neustarts) führt jedoch zum Neustarten der untergeordneten Elemente.

mother_daemon.targetMit dem Aufhören sudo systemctl stop mother_daemon.targetsind auch die Kinder fertig.

Ich denke, das beantwortet meine Frage.

Antwort1

Das ist nicht der Fall.

Der Hauptprozess behandelt den Tod seiner untergeordneten Prozesse auf die normale Weise.

Dies ist die POSIX-Welt. Wenn Prozess A B geforkt hat und Prozess B C, D und E geforkt hat, dann sieht Prozess B den Status SIGCHLDund wait()die Beendigung von C, D und E. Prozess A weiß nicht, was mit C, D und E passiert, und dies ist unabhängig von systemd.

Damit A die Beendigung von C, D und E erkennt, müssen zwei Dinge geschehen.

(Bei den BSDs kann man es schlau machen kevent(). Aber das ist eine Linux-Frage.)

Antwort2

systemdhat das Konzept eines Hauptprozesses. In der systemd-Dokumentation wird dies als „Hauptdienstprozess“ oder einfach als „Hauptprozess“ bezeichnet.

Beispiel 4 imsystemd.service-Dokumentationbeschreibt den Hauptprozess, der berechnet wird, wenn Type=forking.

Die Dokumentation für Restart=in den systemd.service-DokumentenBeschreiben Sie die verschiedenen Möglichkeiten, wann ein Dienst in Bezug auf den Hauptprozess gestartet wird.

Hier ist der Schlüsseltext aus dem oben verlinkten „Beispiel 4“:

systemd geht davon aus, dass der Dienst initialisiert wird, während das ursprüngliche Programm noch ausgeführt wird. Sobald es erfolgreich beendet wird und mindestens ein Prozess übrig bleibt (und RemainAfterExit=no), gilt der Dienst als gestartet.

Oft besteht ein herkömmlicher Daemon nur aus einem Prozess. Wenn also nach Beendigung des ursprünglichen Prozesses nur noch ein Prozess übrig ist, betrachtet systemd diesen Prozess als Hauptprozess des Dienstes. In diesem Fall ist die Variable $MAINPID in ExecReload=, ExecStop= usw. verfügbar.

Falls mehr als ein Prozess übrig bleibt, kann systemd den Hauptprozess nicht bestimmen und geht daher nicht davon aus, dass es einen gibt. In diesem Fall wird $MAINPID nicht erweitert. Wenn der Prozess jedoch beschließt, eine traditionelle PID-Datei zu schreiben, kann systemd die Haupt-PID von dort lesen. Bitte legen Sie PIDFile= entsprechend fest.

verwandte Informationen