systemd
管理対象プロセスの子プロセスの終了をどのように処理しますか?
がsystemd
デーモン を起動しfoo
、次に 、、bar1
およびbar2
という3 つの他のデーモンを起動するとしますbar3
。が予期せず終了した場合、systemd
は何か行いますか? 私の理解では、Solaris の Service Management Facility (SMF) では、プロパティ を変更して別の指示をしない限り、 は強制終了または再起動されます。 は異なる動作をしますか?foo
bar2
foo
startd
ignore_error
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;
}
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 つのことが起こる必要があります。
- Aはしなければならない自身を「サブリーパー」として登録するsystemd はこれを実行しますが、 upstart や nosh などの他のさまざまなサービス マネージャーも同様に実行します
service-manager
。 - Bはしなければならない
exit()
。愚かに、誤って、無駄に自らを「悪魔化」しようとする人は、これを行います。
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= を設定してください。