전체 프로세스 트리를 죽이고 싶습니다. 일반적인 스크립팅 언어를 사용하여이를 수행하는 가장 좋은 방법은 무엇입니까? 간단한 해결책을 찾고 있습니다.
chronos
또는 herodes
명령 중 하나를 사용하십시오 .
전체 프로세스 트리를 죽이고 싶습니다. 일반적인 스크립팅 언어를 사용하여이를 수행하는 가장 좋은 방법은 무엇입니까? 간단한 해결책을 찾고 있습니다.
chronos
또는 herodes
명령 중 하나를 사용하십시오 .
답변:
죽이고 자하는 트리가 단일 프로세스 그룹인지는 말할 수 없습니다. (트리가 서버 시작 또는 쉘 명령 행에서 분기 된 결과 인 경우가 종종 있습니다.) 다음과 같이 GNU ps를 사용하여 프로세스 그룹을 발견 할 수 있습니다.
ps x -o "%p %r %y %x %c "
강제 종료하려는 프로세스 그룹 인 경우 kill(1)
명령을 사용 하지만 프로세스 번호를 지정하는 대신 그룹 번호를 무시 하십시오. 예를 들어 그룹 5112의 모든 프로세스를 종료하려면을 사용하십시오 kill -TERM -- -5112
.
pgrep
프로세스 그룹 ID를보다 쉽게 찾을 수 있습니다. 예를 들어 my-script.sh의 프로세스 그룹을 종료하려면을 실행하십시오 kill -TERM -$(pgrep -o my-script.sh)
.
ps -o pid --no-headers --ppid $PARENT_PID
ps x -o "%r %p %y %x %c" | sort -nk1,2
프로세스 그룹 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)
kill
동일한 트리에 속하는 프로세스에 의해 호출 되면 ,kill
전체 트리의 살해를 종료하기 전에 자신을 죽일 위험.> 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 (다른 프로세스 트리) 에서 호출 될 때 전체 프로세스 트리를 죽이는 가장 간단한 트릭 이라고 생각 합니다 .
kill
자신의 신호를 받기 전에 항상 전체 트리에 신호를 보내야 한다고 생각 합니다. 그러나 일부 특정 상황 / 구현 kill
에서 신호를 자신에게 보내고 중단 한 다음 자체 신호를 수신 할 수 있습니다. 그러나 위험은 충분히 최소화되어야하며, 다른 버그가이 버그보다 먼저 발생하기 때문에 대부분의 경우 무시 될 수 있습니다. 귀하의 경우이 위험을 무시할 수 있습니까? 또한 다른 답변에는이 일반적인 버그가 있습니다 ( kill
프로세스 트리의 일부가 종료 됨). 도움이
man
그렇게합니다. 반면에 자식 프로세스에서 Gandchild 프로세스를 죽이려면 kill -- -$pid
작동하지 않습니다. 따라서 일반적인 해결책이 아닙니다.
child.sh
.
pkill -TERM -P 27888
부모 프로세스 ID가 27888 인 모든 프로세스가 종료됩니다.
또는 더 강력한 :
CPIDS=$(pgrep -P 27888); (sleep 33 && kill -KILL $CPIDS &); kill -TERM $CPIDS
33 초 후에 살해를 계획하고 프로세스 종료를 정중하게 요청합니다.
모든 자손을 종료하려면 이 답변 을 참조하십시오 .
pkill -TERM -P ${$}
.
$ time for i in {1..32768}; do ( echo $BASHPID >> pids ); done real 0m18.860s
프로세스 트리를 재귀 적으로 종료하려면 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 $@
--
인수하기 ps
는 대체가 작동하도록 OS X의에없는 일을 ps
:에 의해 명령을 전과 정의 : 루프ps ax -o "pid= ppid=" | grep -E "${_regex}" | sed -E "s/${_regex}/\1/g
_regex
for
local _regex="[ ]*([0-9]+)[ ]+${_pid}"
killtree()
안정적으로 작동 하도록 SIGTERM 대신 SIGKILL을 보내면 충분 합니까?
ps
지원하지 않는 --ppid
한 사용할 수 있습니다 pgrep -P ${_pid}
대신에
부모 프로세스의 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
여기에 설명 된 약간 수정 된 버전의 메소드를 사용합니다. https://stackoverflow.com/a/5311362/563175
따라서 다음과 같습니다.
kill `pstree -p 24901 | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" " "`
여기서 24901은 부모의 PID입니다.
꽤 추한 것처럼 보이지만 완벽하게 작동합니다.
pstree -p 24901 | grep -oP '(?<=\()[0-9]+(?=\))'
-l
에 pstree
너무 긴 줄이 잘릴 해달라고; 그것은 더 잘 읽을 수 있습니다 kill `pstree -l -p 24901 |grep "([[:digit:]]*)" -o |tr -d '()'`
( \n
정확하게 작동하기 때문에 공간으로 변환 할 필요가 없습니다 ), thx!
zhigang의 답변의 수정 된 버전 :
#!/usr/bin/env bash
set -eu
killtree() {
local pid
for pid; do
kill -stop $pid
local cpid
for cpid in $(pgrep -P $pid); do
killtree $cpid
done
kill $pid
kill -cont $pid
wait $pid 2>/dev/null || true
done
}
cpids() {
local pid=$1 options=${2:-} space=${3:-}
local cpid
for cpid in $(pgrep -P $pid); do
echo "$space$cpid"
if [[ "${options/a/}" != "$options" ]]; then
cpids $cpid "$options" "$space "
fi
done
}
while true; do sleep 1; done &
cpid=$!
for i in $(seq 1 2); do
cpids $$ a
sleep 1
done
killtree $cpid
echo ---
cpids $$ a
wait $pid
이 일반적인 솔루션되지 않도록 프로세스 만에 당신은, 모든 세차 운동을 시작했습니다
wait
표시되지 않습니다 Terminated
그것은 아이의 경우 메시지를.
나는 (평판이 충분하지 않은) 의견을 말할 수 없으므로 이것이 실제로 답변이 아니지만 새로운 답변 을 추가해야합니다 .
2 월 28 일에 @olibre가 제공 한 매우 훌륭하고 철저한 대답에는 약간의 문제 ps opgid= $PID
가 있습니다 . 결과 ps
는 열을 정당화 하기 때문에 5 자리보다 짧은 PID의 선행 공백을 포함 합니다 (숫자를 정렬합니다). 전체 명령 행에서 음수 부호, 공백, 그룹 PID가 차례로 나타납니다. 간단한 해결책은 공간을 제거 하기 위해 파이프 ps
하는 tr
것입니다.
kill -- -$( ps opgid= $PID | tr -d ' ' )
Norman Ramsey의 답변에 추가하려면 프로세스 그룹을 작성하려는 경우 setsid를 살펴볼 가치가 있습니다.
http://pubs.opengroup.org/onlinepubs/009695399/functions/setsid.html
호출 프로세스가 프로세스 그룹 리더가 아닌 경우 setsid () 함수는 새 세션을 작성해야합니다. 돌아온 후, 호출 프로세스는이 새로운 세션의 세션 리더가되며, 새로운 프로세스 그룹의 프로세스 그룹 리더가되며 제어 터미널이 없어야합니다. 호출 프로세스의 프로세스 그룹 ID는 호출 프로세스의 프로세스 ID와 동일하게 설정해야합니다. 호출 프로세스는 새로운 프로세스 그룹의 유일한 프로세스이고 새로운 세션의 유일한 프로세스입니다.
시작 프로세스에서 그룹을 만들 수 있음을 의미합니다. 나는 그것을 시작한 후 전체 프로세스 트리를 죽일 수 있도록 PHP에서 이것을 사용했습니다.
이것은 나쁜 생각 일 수 있습니다. 의견에 관심이 있습니다.
다음 쉘 함수는 다른 많은 답변과 비슷하지만 외부 종속성없이 Linux 및 BSD (OS X 등)에서 모두 작동합니다 pgrep
.
killtree() {
local parent=$1 child
for child in $(ps -o ppid= -o pid= | awk "\$1==$parent {print \$2}"); do
killtree $child
done
kill $parent
}
$child
동일한 이름을 가진 다른 (로컬이 아닌) 변수를 방해하지 않고 함수가 종료 된 후에 로컬 변수의 값이 정리되도록 해당 함수 의 범위를 제한합니다 .
psutil을 사용하여 파이썬 으로이 작업을 수행하는 것은 매우 쉽습니다 . psutil을 pip와 함께 설치하면 전체 프로세스 조작 도구 세트가 있습니다.
def killChildren(pid):
parent = psutil.Process(pid)
for child in parent.get_children(True):
if child.is_running():
child.terminate()
이것은 bash 스크립트를 사용하여 모든 자식 프로세스를 죽이는 버전입니다. 재귀를 사용하지 않으며 pgrep 명령에 따라 다릅니다.
사용하다
killtree.sh PID SIGNAL
killtrees.sh의 내용
#!/bin/bash
PID=$1
if [ -z $PID ];
then
echo "No pid specified"
fi
PPLIST=$PID
CHILD_LIST=`pgrep -P $PPLIST -d,`
while [ ! -z "$CHILD_LIST" ]
do
PPLIST="$PPLIST,$CHILD_LIST"
CHILD_LIST=`pgrep -P $CHILD_LIST -d,`
done
SIGNAL=$2
if [ -z $SIGNAL ]
then
SIGNAL="TERM"
fi
#do substring from comma to space
kill -$SIGNAL ${PPLIST//,/ }
다음은 BW의 기본 구문 분석 가능성에만 의존하는 AWK가없는 @zhigang의 대답 변형입니다.
function killtree {
kill -STOP "$1"
ps -e -o pid= -o ppid= | while read -r pid ppid
do
[[ $ppid = $1 ]] || continue
killtree "$pid" || true # Skip over failures
done
kill -CONT "$1"
kill -TERM "$1"
}
Mac과 Linux 모두에서 잘 작동하는 것 같습니다. 여러 환경에서 빌드해야하는 소프트웨어를 테스트하기 위해 스크립트를 작성할 때와 같이 프로세스 그룹을 관리 할 수없는 상황에서이 트리 워킹 기술은 확실히 도움이됩니다.
여러분의 지혜에 감사드립니다. 내 스크립트는 종료시 일부 자식 프로세스를 남겨두고 부정 팁으로 작업을 쉽게했습니다. 필요한 경우 다른 스크립트에서 사용되도록이 함수를 작성했습니다.
# kill my group's subprocesses: killGroup
# kill also myself: killGroup -x
# kill another group's subprocesses: killGroup N
# kill that group all: killGroup -x N
# N: PID of the main process (= process group ID).
function killGroup () {
local prid mainpid
case $1 in
-x) [ -n "$2" ] && kill -9 -$2 || kill -9 -$$ ;;
"") mainpid=$$ ;;
*) mainpid=$1 ;;
esac
prid=$(ps ax -o pid,pgid | grep $mainpid)
prid=${prid//$mainpid/}
kill -9 $prid 2>/dev/null
return
}
건배.
자녀보다 먼저 부모를 죽이는 것이 좋습니다. 그렇지 않으면 부모는 새로운 아이들이 자신을 죽이기 전에 다시 산란 할 수 있습니다. 이들은 살해에서 살아남을 것입니다.
내 ps 버전은 위와 다릅니다. 어쩌면 너무 오래되어 이상한 잡기 ...
쉘 함수 대신 쉘 스크립트를 사용하면 많은 장점이 있습니다 ...
그러나 기본적으로 zhigangs 아이디어입니다.
#!/bin/bash
if test $# -lt 1 ; then
echo >&2 "usage: kiltree pid (sig)"
fi ;
_pid=$1
_sig=${2:-TERM}
_children=$(ps j | grep "^[ ]*${_pid} " | cut -c 7-11) ;
echo >&2 kill -${_sig} ${_pid}
kill -${_sig} ${_pid}
for _child in ${_children}; do
killtree ${_child} ${_sig}
done
다음은 FreeBSD, Linux 및 MacOS X에서 테스트되었으며 pgrep 및 kill에만 의존합니다 (ps -o 버전은 BSD에서 작동하지 않음). 첫 번째 주장은 자녀를 끝내야하는 부모 pid입니다. 두 번째 인수는 부모 pid도 종료해야하는지 여부를 결정하는 부울입니다.
KillChilds() {
local pid="${1}"
local self="${2:-false}"
if children="$(pgrep -P "$pid")"; then
for child in $children; do
KillChilds "$child" true
done
fi
if [ "$self" == true ]; then
kill -s SIGTERM "$pid" || (sleep 10 && kill -9 "$pid" &)
fi
}
KillChilds $$ > /dev/null 2>&1
쉘 스크립트 내의 모든 자식 / 손자 프로세스에 SIGTERM을 보내고 SIGTERM이 성공하지 못하면 10 초간 기다렸다가 kill을 보냅니다.
조기 답변 :
다음은 작동하지만 BSD에서 쉘 자체를 죽일 것입니다.
KillSubTree() {
local parent="${1}"
for child in $(ps -o pid=$parent); do
if [ $$ -ne $child ]; then (kill -s SIGTERM $child || (sleep 10 && kill -9 $child & )) > /dev/null 2>&1 ; fi
done
}
# Example lanch from within script
KillSubTree $$ > /dev/null 2>&1
zhigang, xyuri 및 solidsneck의 솔루션을 추가로 개발합니다.
#!/bin/bash
if test $# -lt 1 ; then
echo >&2 "usage: kiltree pid (sig)"
exit 1 ;
fi ;
_pid=$1
_sig=${2:-TERM}
# echo >&2 "killtree($_pid) mypid = $$"
# ps axwwf | grep -6 "^[ ]*$_pid " >&2 ;
function _killtree () {
local _children
local _child
local _success
if test $1 -eq $2 ; then # this is killtree - don't commit suicide!
echo >&2 "killtree can´t kill it´s own branch - some processes will survive." ;
return 1 ;
fi ;
# this avoids that children are spawned or disappear.
kill -SIGSTOP $2 ;
_children=$(ps -o pid --no-headers --ppid $2) ;
_success=0
for _child in ${_children}; do
_killtree $1 ${_child} $3 ;
_success=$(($_success+$?)) ;
done ;
if test $_success -eq 0 ; then
kill -$3 $2
fi ;
# when a stopped process is killed, it will linger in the system until it is continued
kill -SIGCONT $2
test $_success -eq 0 ;
return $?
}
_killtree $$ $_pid $_sig
이 버전은 이전 솔루션에서 하위 프로세스가 과도하게 발생하는 조상을 제거하지 않습니다.
하위 목록이 결정되기 전에 프로세스가 올바르게 중지되므로 새 하위 항목이 작성되거나 사라지지 않습니다.
종료 된 후에는 중지 된 작업이 시스템에서 계속 사라져야합니다.
오래된 질문이지만 알고 있지만 모든 응답은 ps를 계속 호출하는 것 같습니다.
이 awk 기반 솔루션은 재귀를 요구하지 않으며 ps를 한 번만 호출합니다.
awk 'BEGIN {
p=1390
while ("ps -o ppid,pid"|getline) a[$1]=a[$1]" "$2
o=1
while (o==1) {
o=0
split(p, q, " ")
for (i in q) if (a[q[i]]!="") {
p=p""a[q[i]]
o=1
a[q[i]]=""
}
}
system("kill -TERM "p)
}'
또는 한 줄로 :
awk 'BEGIN {p=1390;while ("ps -o ppid,pid"|getline) a[$1]=a[$1]" "$2;o=1;while (o==1) {o=0;split(p, q, " ");for (i in q) {if (a[q[i]]!="") {p=p""a[q[i]];o=1;a[q[i]]=""}}}system("kill -TERM "p)}'
기본적으로 아이디어는 부모 : 자식 항목의 배열 (a)을 구축 한 다음 배열을 반복하여 일치하는 부모의 자식을 찾고 부모 목록 (p)에 추가하는 것입니다.
최상위 프로세스를 종료하지 않으려면
sub(/[0-9]*/, "", p)
system () 행이 kill set에서 제거되기 직전에.
여기에는 경쟁 조건이 있다는 것을 명심하십시오. 그러나 모든 솔루션에 대해 (내가 볼 수있는 한) 사실입니다. 내가 필요로하는 스크립트가 많은 단기 아동을 만들지 않기 때문에 필요한 작업을 수행합니다.
독자는 2 패스 루프로 만들어야합니다. 첫 번째 패스 후 SIGSTOP을 p 목록의 모든 프로세스로 보낸 다음, ps를 다시 실행하기 위해 루프하고 두 번째 패스는 SIGTERM을 보낸 다음 SIGCONT를 보내십시오. 좋은 결말에 신경 쓰지 않는다면 두 번째 패스는 SIGKILL 일 수 있습니다.
당신이 죽이고 싶은 것의 pid를 알고 있다면, 일반적으로 세션 ID와 같은 세션의 모든 것에서 벗어날 수 있습니다. 나는 이중 검사를하지만, 내가 죽을 루프에서 rsyncs를 시작하는 스크립트에 이것을 사용했고, 단지 rall을했을 때와 마찬가지로 (루프 때문에) 다른 것을 시작하지는 않았다.
kill $(ps -o pid= -s $(ps -o sess --no-heading --pid 21709))
pid를 모른다면 여전히 더 많이 중첩 할 수 있습니다.
kill $(ps -o pid= -s $(ps -o sess --no-heading --pid $(pgrep rsync )))
ps -o pid= --ppid $PPID | xargs kill -9
kill -9
정말.
kill -15
도움이되지 않습니다.
sh에서 jobs 명령은 백그라운드 프로세스를 나열합니다. 어떤 경우에는 최신 프로세스를 먼저 종료하는 것이 좋습니다. 예를 들어 오래된 프로세스는 공유 소켓을 만들었습니다. 이 경우 PID를 역순으로 정렬하십시오. 때로는 작업이 디스크 나 그와 비슷한 것들에 멈추기 전에 무언가를 쓸 때까지 기다리려고합니다.
당신이 필요하지 않으면 죽이지 마십시오!
for SIGNAL in TERM KILL; do
for CHILD in $(jobs -s|sort -r); do
kill -s $SIGNAL $CHILD
sleep $MOMENT
done
done
쉘 스크립트에서 자식 프로세스 종료
많은 시간 동안 우리는 어떤 이유로 중단되거나 차단 된 자식 프로세스를 종료해야합니다. 예. FTP 연결 문제.
두 가지 접근 방식이 있습니다.
1) 시간 초과에 도달하면 하위 프로세스를 모니터링하고 종료하는 각 하위에 대해 별도의 새 상위를 작성합니다.
다음과 같이 test.sh를 작성하십시오.
#!/bin/bash
declare -a CMDs=("AAA" "BBB" "CCC" "DDD")
for CMD in ${CMDs[*]}; do
(sleep 10 & PID=$!; echo "Started $CMD => $PID"; sleep 5; echo "Killing $CMD => $PID"; kill $PID; echo "$CMD Completed.") &
done
exit;
다음 명령을 사용하여 다른 터미널에서 이름이 'test'인 프로세스를 감시하십시오.
watch -n1 'ps x -o "%p %r %c" | grep "test" '
위의 스크립트는 4 개의 새로운 자식 프로세스와 부모를 만듭니다. 각 하위 프로세스는 10 초 동안 실행됩니다. 그러나 5 초가 초과되면 각 부모 프로세스가 해당 자식을 죽입니다. 따라서 자녀는 실행을 완료 할 수 없습니다 (10 초). 다른 동작을 보려면 해당 타이밍 (스위치 10 및 5)을 재생하십시오. 이 경우 자식은 10 초의 시간 초과에 도달하기 전에 5 초 후에 실행을 완료합니다.
2) 타임 아웃에 도달하면 현재 부모가 자식 프로세스를 모니터링하고 종료하도록합니다. 이렇게하면 각 자식을 모니터링하기 위해 별도의 부모가 생성되지 않습니다. 또한 동일한 부모 내에서 모든 자식 프로세스를 올바르게 관리 할 수 있습니다.
다음과 같이 test.sh를 작성하십시오.
#!/bin/bash
declare -A CPIDs;
declare -a CMDs=("AAA" "BBB" "CCC" "DDD")
CMD_TIME=15;
for CMD in ${CMDs[*]}; do
(echo "Started..$CMD"; sleep $CMD_TIME; echo "$CMD Done";) &
CPIDs[$!]="$RN";
sleep 1;
done
GPID=$(ps -o pgid= $$);
CNT_TIME_OUT=10;
CNT=0;
while (true); do
declare -A TMP_CPIDs;
for PID in "${!CPIDs[@]}"; do
echo "Checking "${CPIDs[$PID]}"=>"$PID;
if ps -p $PID > /dev/null ; then
echo "-->"${CPIDs[$PID]}"=>"$PID" is running..";
TMP_CPIDs[$PID]=${CPIDs[$PID]};
else
echo "-->"${CPIDs[$PID]}"=>"$PID" is completed.";
fi
done
if [ ${#TMP_CPIDs[@]} == 0 ]; then
echo "All commands completed.";
break;
else
unset CPIDs;
declare -A CPIDs;
for PID in "${!TMP_CPIDs[@]}"; do
CPIDs[$PID]=${TMP_CPIDs[$PID]};
done
unset TMP_CPIDs;
if [ $CNT -gt $CNT_TIME_OUT ]; then
echo ${CPIDs[@]}"PIDs not reponding. Timeout reached $CNT sec. killing all childern with GPID $GPID..";
kill -- -$GPID;
fi
fi
CNT=$((CNT+1));
echo "waiting since $b secs..";
sleep 1;
done
exit;
다음 명령을 사용하여 다른 터미널에서 이름이 'test'인 프로세스를 감시하십시오.
watch -n1 'ps x -o "%p %r %c" | grep "test" '
위의 스크립트는 4 개의 새로운 자식 프로세스를 만듭니다. 우리는 모든 자식 프로세스의 pid를 저장하고 반복하여 실행이 완료되었거나 여전히 실행 중인지 확인합니다. 자식 프로세스는 CMD_TIME 시간까지 실행됩니다. 그러나 CNT_TIME_OUT 시간 초과에 도달하면 모든 하위 프로세스가 상위 프로세스에 의해 종료됩니다. 타이밍을 전환하고 스크립트를 사용하여 동작을 볼 수 있습니다. 이 접근법의 한 가지 단점은 모든 자식 트리를 죽이기 위해 그룹 ID를 사용한다는 것입니다. 그러나 상위 프로세스 자체는 동일한 그룹에 속하므로 종료됩니다.
부모를 죽이지 않으려면 다른 그룹 ID를 부모 프로세스에 할당해야 할 수도 있습니다.
자세한 내용은 여기를 참조하십시오.
나는 그것이 오래되었다는 것을 알고 있지만 그것이 내가 찾은 더 좋은 해결책입니다.
killtree() {
for p in $(pstree -p $1 | grep -o "([[:digit:]]*)" |grep -o "[[:digit:]]*" | tac);do
echo Terminating: $p
kill $p
done
}