전체 프로세스 트리를 죽이고 싶습니다. 일반적인 스크립팅 언어를 사용하여이를 수행하는 가장 좋은 방법은 무엇입니까? 간단한 해결책을 찾고 있습니다.
답변
죽이고 자하는 트리가 단일 프로세스 그룹인지는 말할 수 없습니다. (트리가 서버 시작 또는 쉘 명령 행에서 분기 된 결과 인 경우가 종종 있습니다.) 다음과 같이 GNU ps를 사용하여 프로세스 그룹을 발견 할 수 있습니다.
ps x -o "%p %r %y %x %c "
강제 종료하려는 프로세스 그룹 인 경우 kill(1)
명령을 사용 하지만 프로세스 번호를 지정하는 대신 그룹 번호를 무시 하십시오. 예를 들어 그룹 5112의 모든 프로세스를 종료하려면을 사용하십시오 kill -TERM -- -5112
.
답변
프로세스 그룹 ID ( )를 사용하여 동일한 프로세스 트리에 속하는 모든 프로세스를 종료하십시오.PGID
kill -- -$PGID
기본 신호 사용 (TERM
= 15)kill -9 -$PGID
신호를 사용하십시오KILL
(9)
동일한 프로세스 트리 의 Process-ID ( ) PGID
에서 를 검색 할 수 있습니다.PID
kill -- -$(ps -o pgid= $PID | grep -o '[0-9]*')
(신호TERM
)kill -9 -$(ps -o pgid= $PID | grep -o '[0-9]*')
(신호KILL
)
남은 공간과 OSX 호환성 에 기여한 tanager 와 Speakus 에게 특별한 감사를드립니다 $PID
.
설명
kill -9 -"$PGID"
=>KILL
모든 어린이와 손자 에게 신호 9 ( )를 보냅니다 .PGID=$(ps opgid= "$PID")
=> Process-Parent-ID 뿐만 아니라 트리의 모든 Process -ID 에서 Process-Group-ID 를 검색합니다 . 의 변형 IS 에 의해 대체 될 수있다 . 그러나:ps opgid= $PID
ps -o pgid --no-headers $PID
pgid
pgrp
ps
tanager에서 알 수PID
있듯이 5 자리 미만이고 오른쪽으로 정렬 되면 선행 공백을 삽입합니다 . 당신이 사용할 수있는:
PGID=$(ps opgid= "$PID" | tr -d ' ')
ps
OSX에서 항상 헤더를 인쇄하므로 Speakus는 다음을 제안합니다.
PGID="$( ps -o pgid "$PID" | grep [0-9] | tr -d ' ' )"
grep -o [0-9]*
연속 숫자 만 인쇄합니다 (공백 또는 알파벳 머리글은 인쇄하지 않음).
추가 명령 줄
PGID=$(ps -o pgid= $PID | grep -o [0-9]*)
kill -TERM -"$PGID" # kill -15
kill -INT -"$PGID" # correspond to [CRTL+C] from keyboard
kill -QUIT -"$PGID" # correspond to [CRTL+\] from keyboard
kill -CONT -"$PGID" # restart a stopped process (above signals do not kill it)
sleep 2 # wait terminate process (more time if required)
kill -KILL -"$PGID" # kill -9 if it does not intercept signals (or buggy)
한정
- davide 와 Hubert Kario가 알 수 있듯이
kill
동일한 트리에 속하는 프로세스에 의해 호출 되면 ,kill
전체 트리의 살해를 종료하기 전에 자신을 죽일 위험. - 따라서 다른 Process-Group-ID 를 가진 프로세스를 사용하여 명령을 실행하십시오 .
긴 이야기
> cat run-many-processes.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
./child.sh background &
./child.sh foreground
echo "ProcessID=$$ ends ($0)"
> cat child.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
./grandchild.sh background &
./grandchild.sh foreground
echo "ProcessID=$$ ends ($0)"
> cat grandchild.sh
#!/bin/sh
echo "ProcessID=$$ begins ($0)"
sleep 9999
echo "ProcessID=$$ ends ($0)"
‘&’를 사용하여 백그라운드에서 프로세스 트리를 실행하십시오.
> ./run-many-processes.sh &
ProcessID=28957 begins (./run-many-processes.sh)
ProcessID=28959 begins (./child.sh)
ProcessID=28958 begins (./child.sh)
ProcessID=28960 begins (./grandchild.sh)
ProcessID=28961 begins (./grandchild.sh)
ProcessID=28962 begins (./grandchild.sh)
ProcessID=28963 begins (./grandchild.sh)
> PID=$! # get the Parent Process ID
> PGID=$(ps opgid= "$PID") # get the Process Group ID
> ps fj
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
28348 28349 28349 28349 pts/3 28969 Ss 33021 0:00 -bash
28349 28957 28957 28349 pts/3 28969 S 33021 0:00 \_ /bin/sh ./run-many-processes.sh
28957 28958 28957 28349 pts/3 28969 S 33021 0:00 | \_ /bin/sh ./child.sh background
28958 28961 28957 28349 pts/3 28969 S 33021 0:00 | | \_ /bin/sh ./grandchild.sh background
28961 28965 28957 28349 pts/3 28969 S 33021 0:00 | | | \_ sleep 9999
28958 28963 28957 28349 pts/3 28969 S 33021 0:00 | | \_ /bin/sh ./grandchild.sh foreground
28963 28967 28957 28349 pts/3 28969 S 33021 0:00 | | \_ sleep 9999
28957 28959 28957 28349 pts/3 28969 S 33021 0:00 | \_ /bin/sh ./child.sh foreground
28959 28960 28957 28349 pts/3 28969 S 33021 0:00 | \_ /bin/sh ./grandchild.sh background
28960 28964 28957 28349 pts/3 28969 S 33021 0:00 | | \_ sleep 9999
28959 28962 28957 28349 pts/3 28969 S 33021 0:00 | \_ /bin/sh ./grandchild.sh foreground
28962 28966 28957 28349 pts/3 28969 S 33021 0:00 | \_ sleep 9999
28349 28969 28969 28349 pts/3 28969 R+ 33021 0:00 \_ ps fj
이 명령 pkill -P $PID
은 손자를 죽이지 않습니다.
> pkill -P "$PID"
./run-many-processes.sh: line 4: 28958 Terminated ./child.sh background
./run-many-processes.sh: line 4: 28959 Terminated ./child.sh foreground
ProcessID=28957 ends (./run-many-processes.sh)
[1]+ Done ./run-many-processes.sh
> ps fj
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
28348 28349 28349 28349 pts/3 28987 Ss 33021 0:00 -bash
28349 28987 28987 28349 pts/3 28987 R+ 33021 0:00 \_ ps fj
1 28963 28957 28349 pts/3 28987 S 33021 0:00 /bin/sh ./grandchild.sh foreground
28963 28967 28957 28349 pts/3 28987 S 33021 0:00 \_ sleep 9999
1 28962 28957 28349 pts/3 28987 S 33021 0:00 /bin/sh ./grandchild.sh foreground
28962 28966 28957 28349 pts/3 28987 S 33021 0:00 \_ sleep 9999
1 28961 28957 28349 pts/3 28987 S 33021 0:00 /bin/sh ./grandchild.sh background
28961 28965 28957 28349 pts/3 28987 S 33021 0:00 \_ sleep 9999
1 28960 28957 28349 pts/3 28987 S 33021 0:00 /bin/sh ./grandchild.sh background
28960 28964 28957 28349 pts/3 28987 S 33021 0:00 \_ sleep 9999
이 명령 kill -- -$PGID
은 손자를 포함한 모든 프로세스를 종료합니다.
> kill -- -"$PGID" # default signal is TERM (kill -15)
> kill -CONT -"$PGID" # awake stopped processes
> kill -KILL -"$PGID" # kill -9 to be sure
> ps fj
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
28348 28349 28349 28349 pts/3 29039 Ss 33021 0:00 -bash
28349 29039 29039 28349 pts/3 29039 R+ 33021 0:00 \_ ps fj
결론
I는이 예에서 통지 PID
하고 PGID
(동일하다 28957
).
이것이 내가 처음 kill -- -$PID
에는 충분 하다고 생각한 이유 입니다. 그러나 경우에 프로세스는 내 산란되는 프로세스 ID가 로부터 다른 그룹 ID .Makefile
kill -- -$(ps -o pgid= $PID | grep -o [0-9]*)
다른 그룹 ID (다른 프로세스 트리) 에서 호출 될 때 전체 프로세스 트리를 죽이는 가장 간단한 트릭 이라고 생각 합니다 .
답변
pkill -TERM -P 27888
부모 프로세스 ID가 27888 인 모든 프로세스가 종료됩니다.
또는 더 강력한 :
CPIDS=$(pgrep -P 27888); (sleep 33 && kill -KILL $CPIDS &); kill -TERM $CPIDS
33 초 후에 살해를 계획하고 프로세스 종료를 정중하게 요청합니다.
모든 자손을 종료하려면 이 답변 을 참조하십시오 .
답변
프로세스 트리를 재귀 적으로 종료하려면 killtree ()를 사용하십시오.
#!/bin/bash
killtree() {
local _pid=$1
local _sig=${2:--TERM}
kill -stop ${_pid} # needed to stop quickly forking parent from producing children between child killing and parent killing
for _child in $(ps -o pid --no-headers --ppid ${_pid}); do
killtree ${_child} ${_sig}
done
kill -${_sig} ${_pid}
}
if [ $# -eq 0 -o $# -gt 2 ]; then
echo "Usage: $(basename $0) <pid> [signal]"
exit 1
fi
killtree $@
답변
답변
브래드의 대답은 내가 너무 좋습니다 당신이 멀리 할 수 있다는 점을 제외하고 줄 것입니다 awk
당신이 사용하는 모두 경우 --ppid
에 옵션을 ps
.
for child in $(ps -o pid -ax --ppid $PPID) do ....... done
답변
부모 프로세스의 pid를 전달하는 것을 알고 있다면 다음과 같이 작동하는 쉘 스크립트가 있습니다.
for child in $(ps -o pid,ppid -ax | \
awk "{ if ( \$2 == $pid ) { print \$1 }}")
do
echo "Killing child process $child because ppid = $pid"
kill $child
done
