후손 처리


20

프로세스 컨테이너를 만들려고합니다. 컨테이너는 다른 프로그램을 트리거합니다. 예를 들어 '&'사용법으로 백그라운드 작업을 실행하는 bash 스크립트입니다.

내가 따르는 중요한 기능은 이것입니다 : 컨테이너를 죽일 때 그 아래에 생성 된 모든 것을 죽여야합니다. 아이들을 지시 할뿐만 아니라 그들의 후손들도 마찬가지입니다.

이 프로젝트를 시작했을 때, 나는 당신이 프로세스를 죽일 때 그 아이들도 자동으로 죽었다고 잘못 생각했습니다. 나는 같은 잘못된 생각을 가진 사람들로부터 조언을 구했습니다. 신호를 잡아서 죽일 수는 있지만 아이들이 원하는 것은 아닙니다.

나는 xterm을 닫으면 nohup'd되지 않은 한 xterm 내에서 실행중인 모든 것이 종료되기 때문에 내가 달성하고자하는 것을 믿습니다. 이것은 고아 프로세스를 포함합니다. 그것이 제가 다시 만들고자하는 것입니다.

내가 찾고있는 것은 유닉스 세션과 관련이 있다는 생각이 있습니다.

프로세스의 모든 하위 항목을 식별 할 수있는 안정적인 방법이 있다면 임의의 신호도 보낼 수있는 것이 좋습니다. 예 : SIGUSR1.


부모 프로세스를 죽이면 SIGHUP직접적인 자식 프로세스로 보내 집니다. 중단 신호의 기본 처리기는 프로세스 실행을 중단하므로 기본 경로는 모든 하위 항목을 종료하는 것입니다. 프로세스 및 프로세스 그룹에 대해 자세히 알아보십시오.
alex

xterm을 닫으면 TTY가 파괴되어 xterm에 생성 된 모든 것이 종료됩니다. 하위 프로세스가 사용할 수있는 tty를 작성하는 방법을 생각 해낼 수 있으면 TTY를 파괴하고 동일한 작업을 수행 할 수 있습니다. TTY (nohup & friends)를 닫지 않은 프로세스는 SIGHUP을 얻습니다.
Patrick

답변:


23

프로세스에 신호를 보내면 해당 프로세스가 종료됩니다. 프로세스를 죽이면 다른 프로세스도 죽인다는 소문이 시작된 것 같습니다. 특히 직관적이지 않은 것 같습니다.

그러나 하나 이상의 프로세스를 종료하는 방법이 있습니다. 그러나 하나의 프로세스에 신호를 보내지 않을 것입니다. 신호를 -1234로 보내 전체 프로세스 그룹 을 종료 할 수 있습니다. 여기서 1234는 프로세스 그룹 리더의 PID 인 PGID (프로세스 그룹 ID)입니다. 당신이 실행하면 파이프 라인을 전체 파이프 라인 프로세스 그룹으로 밖으로 시작 (응용 프로그램이 호출하여이 변경 될 수 있습니다 setpgid또는 setpgrp).

백그라운드 ( foo &) 에서 프로세스를 시작하면 해당 프로세스가 자체 프로세스 그룹에 있습니다. 프로세스 그룹은 터미널에 대한 액세스를 관리하는 데 사용됩니다. 일반적으로 포 그라운드 프로세스 그룹 만 터미널에 액세스 할 수 있습니다. 백그라운드 작업은 동일한 세션에 남아 있지만 전체 세션을 종료하거나 세션의 프로세스 그룹 또는 프로세스를 열거 할 수있는 기능이 없으므로 그다지 도움이되지 않습니다.

터미널을 닫으면 커널은 제어 터미널SIGHUP 로 사용하는 모든 프로세스에 신호 를 보냅니다 . 이러한 프로세스 는 세션을 형성 하지만 모든 세션에 제어 터미널이있는 것은 아닙니다. 따라서 프로젝트의 경우 스크립트 , 화면 등으로 작성된 자체 터미널에서 모든 프로세스를 시작할 수 있습니다 . 터미널 에뮬레이터 프로세스를 강제 종료하여 포함 된 프로세스를 강제 종료하십시오 (로 가정하지 않은 경우 ).setsid

다른 작업을 수행하지 않는 자신의 사용자로 프로세스를 실행하여 더 많은 격리를 제공 할 수 있습니다. 그런 다음 모든 프로세스를 쉽게 종료 할 수 있습니다. 사용자 kill( 시스템 호출 또는 유틸리티 )를 해당 사용자로 실행하고 -1을 PID 인수로 사용하여 "모든 사용자 프로세스"를 의미합니다.

포함 된 프로세스를 실제 컨테이너 에서 실행하여 더 많은 격리를 제공 할 수 있지만 더 많은 설정을 제공 할 수 있습니다 .


자신의 프로세스를 프로그래밍하면 다음과 같은 것을 사용할 수 있습니다. prctl(PR_SET_PDEATHSIG, SIGHUP);, 추가 정보 : man7.org/linux/man-pages/man2/prctl.2.html
Alexis Wilke

Gilles, 당신은 이것을 언급합니다- "터미널을 닫을 때, 커널은 SIGHUP 신호를 제어 터미널로 가지고있는 모든 프로세스로 보냅니다." 에서 내가 터미널을 억측하고있어 (쉘) 세션 리더에 SIGHUP을 보내는 사람들 전달합니다 세션 내의 모든 프로세스 그룹에. 둘 중 어느 것이 옳을까요?
iruvar

4

부모 스크립트 내에서 kill 신호를 트랩하여 모든 자식을 kill하십시오. 예를 들어

#!/bin/bash
# kill the parent and children together
trap "kill 0" EXIT
# create all the children
for n in $(seq 1 100)
do
    ( echo "begin $n"; sleep 60; echo "end $n" ) &
done
# wait for the children to complete
wait

2

프로세스의 모든 하위 항목을 식별하는 신뢰할 수있는 방법은 pstree <pid>pid가 상위 프로세스 ID 인 명령을 사용하는 것 입니다.

pstree 여기 에있는 맨 페이지를 읽으 십시오 .

프로세스 그룹의 모든 구성원에게 신호를 killpg(<pgrp>, <sig>);
보내 려면 다음과 같이하십시오. 여기서 pgrp는 프로세스 그룹 번호이고 sig는 신호입니다.

지정된 프로세스 그룹에서 하위를 기다리려면 다음을 수행하십시오. waitpid(-<pgrp>, &status, ...);

수행중인 작업의 대안은 새로운 bash 쉘에서 프로세스 컨테이너를 실행하는 것입니다. 명령으로 새 bash 쉘을 작성한 bash후 프로세스를 실행하십시오. 모든 프로세스를 종료하려면 명령으로 쉘을 종료하십시오 exit.


killpg를 사용하면 내가해야 할 일을 할 수 있다고 생각합니다. 감사.
Craig Turner

1

사용하다

unshare -fp --kill-child -- yourprogram

를 죽이면 unshare, 모든 자식 프로세스 ( yourprogram생성되었을 수도 있음)가 종료됩니다.

util-linux로 가능합니다 2.32. 이 업스트림을 구현했습니다 . 사용자 네임 스페이스 (커널 구성 옵션 CONFIG_USER_NS=y) 또는 루트 권한 이 필요합니다 . 여기도 참조 하십시오 .


0

pslist 패키지의 rkill 명령 은 지정된 신호 (또는 SIGTERM기본적으로)를 지정된 프로세스 및 모든 하위 항목으로 보냅니다 .

rkill [-SIG] pid/name...

0

쉘의 모든 자손을 죽이는 또 다른 옵션 : jobs -p | xargs -n 1 pkill -P

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.