web-dev-qa-db-ja.com

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

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

systemdがデーモンfooを起動し、それが次にbar1bar2、およびbar3の3つのデーモンを起動するとします。 bar2が予期せず終了した場合、systemdfooに対して何かしますか?私の理解では、Solarisのサービス管理機能(SMF)の下で、fooに通知しないと、プロパティignore_errorを変更することにより、startdが強制終了または再起動されます。 systemdの動作は異なりますか?

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

これは、mother_daemon.serviceというsystemdユニットで制御されます。

[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を実行すると(Sudo systemctl daemon-reloadの後)、親デーモンと5つの子デーモンが表示されます。

子の1つを殺しても親には影響はありませんが、親を殺す(したがって再起動をトリガーする)と子が再起動します。

mother_daemon.targetSudo systemctl stop mother_daemon.targetを停止すると、子も終了します。

これは私の質問に答えると思います。

6

そうではありません。

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

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

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

(BSDでkevent()を使うと賢くなります。しかし、これはLinuxの質問です。)

4
JdeBP

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

systemd.serviceドキュメント の例4は、メインプロセスがType=forkingのときに計算されると説明しています。

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

上記の「例4」からのキーテキストは次のとおりです。

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

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

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

3
Mark Stosberg