systemd
관리 프로세스의 하위 프로세스 종료를 어떻게 처리합니까 ?
systemd
가 데몬을 시작한 foo
다음 세 개의 다른 데몬( , 및 )을 시작 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 종료를 인식하려면 두 가지 일이 발생해야 합니다.
- A는 ~해야 한다자신을 "하위 리퍼"로 등록. systemd는 upstart 및 nosh를 포함한 다양한 다른 서비스 관리자와 마찬가지로 이 작업을 수행합니다
service-manager
. - B는
exit()
. 서비스어리석게, 잘못하고, 헛되이스스로를 "악마화"하려고 해보세요.
kevent()
( BSD에 대해 영리하게 이해할 수 있습니다 . 그러나 이것은 Linux 질문입니다.)
답변2
systemd
메인 프로세스라는 개념을 가지고 있습니다. 시스템 문서에서는 이를 "주요 서비스 프로세스" 또는 간단히 "주요 프로세스"라고 합니다.
예제 4systemd.service 문서설명하면 주요 프로세스가 계산됩니다 Type=forking
.
Restart=
systemd.service 문서에 대한 문서기본 프로세스와 관련하여 서비스가 시작될 때의 다양한 가능성을 설명합니다.
위에 링크된 "예제 4"의 주요 텍스트는 다음과 같습니다.
systemd는 원래 프로그램이 계속 실행되는 동안 서비스가 초기화 과정에 있는 것으로 간주합니다. 성공적으로 종료되고 최소한 프로세스가 남아 있으면(RemainAfterExit=no) 서비스가 시작된 것으로 간주됩니다.
종종 전통적인 데몬은 하나의 프로세스로만 구성됩니다. 따라서 원래 프로세스가 종료된 후 하나의 프로세스만 남게 되면 systemd는 해당 프로세스를 서비스의 주요 프로세스로 간주합니다. 이 경우 $MAINPID 변수는 ExecReload=, ExecStop= 등에서 사용할 수 있습니다.
둘 이상의 프로세스가 남아 있는 경우 systemd는 기본 프로세스를 결정할 수 없으므로 기본 프로세스가 있다고 가정하지 않습니다. 이 경우 $MAINPID는 아무 것도 확장되지 않습니다. 그러나 프로세스가 기존 PID 파일을 작성하기로 결정하면 systemd는 거기에서 기본 PID를 읽을 수 있습니다. 이에 따라 PIDFile=을 설정하십시오.