systemd
管理プロセスの子プロセス出口を処理する方法は?
systemd
デーモンが起動したfoo
後、デーモンが3つの異なるデーモン(bar1
、bar2
および)を起動するとしますbar3
。予期しないシャットダウンが発生した場合はsystemd
どうなりますか?私が理解したのは、プロパティを変更して通知しないと、Solarisのサービス管理機能(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
(後でsudo systemctl daemon-reload
)親デーモンと5つの子デーモンを見ることができます。
子のいずれかを殺しても親には影響はありませんが、親を殺すと(したがって再開が始まる)、子が再開されます。
mother_daemon.target
止まると子供たちも終わりますsudo systemctl stop mother_daemon.target
。
これが私の質問に対する答えだと思います。
答え1
しかし、実際にはそうではありません。
基本プロセスは、通常の方法で子プロセスの終了を処理します。
これがPOSIXの世界です。プロセスAがBを分岐し、プロセスBがC、D、およびEを分岐すると、プロセスBは終了後にC、D、およびEの状態を確認します。プロセスAはC、D、Eに何が起こったのかわからず、systemdとは何の関係もありませんSIGCHLD
。wait()
AがC、D、Eが終了したことを知るには、2つのことが必要です。
- 必須自分を「サブハーベスター」として登録してください。 systemdは、他のサービスマネージャ(upstartとnoshを含む)と同様にこれを行います
service-manager
。 - B
exit()
必須サービス愚かな、誤って、無駄にそのために自分自身を「悪魔化」してみてください。
kevent()
(人々はBSDについて賢明になるかもしれませんが、これはLinuxの問題です。)
答え2
systemd
メインプロセスという概念があります。システム文書では、これを「メインサービスプロセス」または単に「メインプロセス」と呼びます。
例4ではsystemd.service ドキュメント計算の主なプロセスが紹介されますType=forking
。
Restart=
systemd.service ドキュメントのドキュメント基本プロセスに関連するサービスを開始する際のさまざまな可能性について説明します。
上記の「例4」の主なテキストは次のとおりです。
systemd は、元のプログラムが実行され続けている間にサービスが初期化されていると考えています。サービスが正常に終了し、1つ以上のプロセスが残っている場合、サービスは開始されたと見なされます(RemainAfterExit = no)。
通常、既存のデーモンは1つのプロセスのみで構成されます。したがって、元のプロセスが終了してから1つのプロセスしか残っていない場合、systemdはそのプロセスをサービスの主要なプロセスと見なします。この場合、$ MAINPID変数はExecReload =、ExecStop =などで使用できます。
複数のプロセスがある場合、systemdは基本プロセスを決定できないため、1つのプロセスが存在するとは想定されません。この場合、$ MAINPIDは何も拡張されません。ただし、プロセスが既存のPIDファイルに書き込むことを決定した場合、systemdはそこからデフォルトのPIDを読み取ることができます。これに応じてPIDFile =を設定してください。