systemd は管理対象プロセスの子プロセスの終了をどのように処理しますか?

systemd は管理対象プロセスの子プロセスの終了をどのように処理しますか?

systemd管理対象プロセスの子プロセスの終了をどのように処理しますか?

systemdデーモン を起動しfoo、次に 、、bar1およびbar2という3 つの他のデーモンを起動するとしますbar3。が予期せず終了した場合、systemdは何か行いますか? 私の理解では、Solaris の Service Management Facility (SMF) では、プロパティ を変更して別の指示をしない限り、 は強制終了または再起動されます。 は異なる動作をしますか?foobar2foostartdignore_errorsystemd

編集#1:

systemdの動作をテストするためにテスト デーモンを作成しました。デーモンはmother_daemon子プロセスを生成するため呼び出されます。

#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;
  }

systemdこれは、と呼ばれるユニットで制御されます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

ユニットはmother_daemon.service以下によって制御されますmother_daemon.target:

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

を実行するとsudo systemctl start mother_daemon.target(after sudo systemctl daemon-reload)、親デーモンと 5 つの子デーモンが表示されます。

子プロセスの 1 つを終了しても親プロセスには影響はありませんが、親プロセスを終了 (および再起動のトリガー) すると、子プロセスは再起動されます。

止めればmother_daemon.target子供sudo systemctl stop mother_daemon.targetも終わります。

これで私の質問への答えが出たと思います。

答え1

それは違います。

メインプロセスは、通常の方法で、その子プロセスの終了を処理します。

これは POSIX の世界です。プロセス A が B をフォークし、プロセス B が C、D、E をフォークした場合、プロセス B は C、D、E の終了からのステータスを確認します。SIGCHLDプロセスwait()A は C、D、E に何が起こっているかを認識しません。これは systemd とは無関係です。

A が C、D、E の終了を認識するには、2 つのことが起こる必要があります。

kevent()( BSD では賢く使うことができます。しかし、これは Linux に関する質問です。)

答え2

systemdメインプロセスの概念があります。systemd のドキュメントでは、これは「メインサービスプロセス」または単に「メインプロセス」と呼ばれています。

例4systemd.service ドキュメント主なプロセスがいつ計算されるかを説明しますType=forking

Restart=systemd.serviceドキュメントのドキュメントメインプロセスに関連してサービスが開始されるさまざまな可能性について説明します。

上にリンクされている「例 4」のキーテキストは次のとおりです。

systemd は、元のプログラムがまだ実行されている間、サービスが初期化中であると見なします。正常に終了し、少なくともプロセスが残っている場合 (および RemainAfterExit=no)、サービスは開始されているとみなされます。

多くの場合、従来のデーモンは 1 つのプロセスのみで構成されます。したがって、元のプロセスが終了した後にプロセスが 1 つだけ残っている場合、systemd はそのプロセスをサービスのメイン プロセスと見なします。その場合、$MAINPID 変数は ExecReload=、ExecStop= などで使用できます。

複数のプロセスが残っている場合、systemd はメイン プロセスを判別できないため、メイン プロセスが存在するとは想定しません。その場合、$MAINPID は何も展開されません。ただし、プロセスが従来の PID ファイルを書き込むことにした場合、systemd はそこからメイン PID を読み取ることができます。それに応じて PIDFile= を設定してください。

関連情報