상위 프로세스가 종료된 후 모든 하위 프로세스를 종료하고 초기화로 전환하는 방법은 무엇입니까?

상위 프로세스가 종료된 후 모든 하위 프로세스를 종료하고 초기화로 전환하는 방법은 무엇입니까?

다음과 같은 문제가 있습니다. 많은 하위 프로세스를 생성한 후 큰 상위 프로세스가 (실수로!) 종료되면 모든 하위 프로세스가 init.

어떻게 하면 이러한 모든 하위 프로세스를 안전하게 종료할 수 있습니까?

나는 방법이 있다고 생각했습니다.이 명령을 사용하여 상위 프로세스에 대해 알아보세요.

ps -o ppid= <number of some child process>

완료되면 사용할 수 있습니다이 답변모든 하위 프로세스를 종료합니다.

여기서 문제는 모든 하위 프로세스가 전환되고 init이 솔루션이 작동하지 않는다는 것입니다...

htop을 수동으로 종료하는 것 외에 다른 방법이 있습니까?

미리 감사드립니다!

답변1

  1. 단기 솔루션:  대규모 상위 프로세스가 동시에 모든 하위 프로세스를 생성하는 경우 psSTIME(프로세스 시작 시간)을 기준으로 출력을 정렬합니다. 이는 프로세스 이름과 함께 이 호출에서 고아를 식별하는 데 도움이 됩니다.
  2. 장기적인 수정:  시작되는 모든 프로세스의 PID 로그를 유지하도록 상위 프로세스 프로그램을 수정하십시오. 그런 다음 이를 킬 목록으로 사용할 수 있습니다.

답변2

다음 방법을 사용하여 합리적인 최종 후보 목록을 개발할 수 있습니다.

ps -ef | awk '$1 == "myUser" && $3 == 1'

아마도 이는 세션 시작에 사용되지 않는 STIME, ?에 사용되지 않는 TTY, /usr/lib, /usr/bin 또는 /lib로 시작하지 않는 CMD와 같은 다른 필드를 필터링하면 개선될 수 있습니다. 최종 검사를 위해 목록을 파일에 넣은 다음 awk | xargs | kill을 사용하여 열 2를 출력합니다.

답변3

이식 가능하지는 않지만 Linux에서는 init프로세스의 상위 항목을 다시 지정할 수 없습니다 PR_SET_CHILD_SUBREAPER.prctl(2).

PR_SET_CHILD_SUBREAPER(리눅스 3.4부터)

      만약에아르기닌 20이 아닌 경우 호출 프로세스의 "하위 하위 리퍼" 속성을 설정합니다.아르기닌 20이면 속성이 설정되지 않습니다. 프로세스가 하위 수확기로 표시되면 해당 프로세스가 생성하는 모든 하위 프로세스와 해당 하위 프로세스는 하위 수확기를 갖는 것으로 표시됩니다. 실제로 서브 수확기의 기능은 다음과 같습니다.초기화(1)하위 프로세스의 경우. …

그러나 하위 리퍼도 (우연히) 죽을 수 있습니다. 또 다른 옵션(Linux에서도)은 PID 네임스페이스 또는 컨테이너일 수 있습니다. 보다 일반적인 해결책은 부모 프로세스가 쫓겨나거나 죽을 가능성이 적도록 가능한 한 간단하고 강력하게 부모 프로세스를 만드는 것입니다.

더 복잡한 것은 자식 프로세스를 부모 프로세스에 연결하는 것입니다. 그러나 자식 프로세스가 다른 작업을 수행하거나 자식 프로세스가 비동기 I/O를 사용하여 문제를 복잡하게 만들 수 없는 경우에는 자식 프로세스가 파이프를 확인해야 하기 때문에 연결이 불가능할 수 있습니다. EOF의 경우 상위 프로세스가 떠날 때까지 참고하세요.

#include <err.h>
#include <errno.h>
#include <unistd.h>

int main(void)
{
    int fd[2];
    char ch;
    ssize_t ret;
    pipe(fd);

    switch (fork()) {
    case -1:
        err(1, "fork failed");
    case 0:
        close(fd[1]);
        warnx("child  %d start", getpid());
        /* this would really need to be done in an event loop so the
         * child can do other things meanwhile */
        ret = read(fd[0], &ch, 1);
        if (ret == 0)
            errx(1, "EOF from parent (child %d)", getpid());
        break;
    default:
        /* and another child process... */
        switch (fork()) {
        case -1:
            err(1, "fork failed");
        case 0:
            close(fd[1]);
            warnx("child  %d start", getpid());
            ret = read(fd[0], &ch, 1);
            if (ret == 0)
                errx(1, "EOF from parent (child %d)", getpid());
            break;
        default:
            sleep(9);
        }
    }
    return 0;
}

관련 정보