Nor*_*sey 295
您没有说要杀死的树是否是单个进程组.(如果树是从服务器启动或shell命令行分叉的结果,则通常会出现这种情况.)您可以使用GNU ps发现进程组,如下所示:
ps x -o "%p %r %y %x %c "
Run Code Online (Sandbox Code Playgroud)
如果它是您要杀死的进程组,只需使用该kill(1)命令,而不是给它一个进程号,给它取消组号.例如,要杀死组5112中的每个进程,请使用kill -TERM -- -5112.
oli*_*bre 193
使用进程组ID()终止属于同一进程树的所有进程PGID
kill -- -$PGID 使用默认信号(TERM= 15)kill -9 -$PGID 使用信号KILL(9)您可以PGID从同一进程树的任何Process-ID(PID)中检索
kill -- -$(ps -o pgid= $PID | grep -o '[0-9]*') (信号TERM)kill -9 -$(ps -o pgid= $PID | grep -o '[0-9]*') (信号KILL)特别感谢唐加拉雀和Speakus的捐款$PID剩余空间和OSX的兼容性.
kill -9 -"$PGID"=> KILL向所有孩子和孙子发送信号9()...PGID=$(ps opgid= "$PID")=> 从树的任何进程ID中检索Process-Group-ID,而不仅仅是Process-Parent-ID.的变型就是其中可以被替换.但:
ps opgid= $PIDps -o pgid --no-headers $PIDpgidpgrpgrep -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)
Run Code Online (Sandbox Code Playgroud)
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 Code Online (Sandbox Code Playgroud)
使用'&'在后台运行流程树
> ./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
Run Code Online (Sandbox Code Playgroud)
该命令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
Run Code Online (Sandbox Code Playgroud)
该命令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
Run Code Online (Sandbox Code Playgroud)
我注意到在这个例子中PID和PGID是相等的(28957).
这就是我原本认为kill -- -$PID足够的原因.但是,如果进程是在进程内生成的,Makefile则进程ID与组ID不同.
我认为kill -- -$(ps -o pgid= $PID | grep -o [0-9]*)是从不同的组ID(另一个进程树)调用时杀死整个进程树的最佳简单技巧.
Onl*_*job 165
pkill -TERM -P 27888
Run Code Online (Sandbox Code Playgroud)
这将终止具有父进程ID 27888的所有进程.
或者更强大:
CPIDS=$(pgrep -P 27888); (sleep 33 && kill -KILL $CPIDS &); kill -TERM $CPIDS
Run Code Online (Sandbox Code Playgroud)
计划在33秒后杀人并礼貌地要求程序终止.
请参阅此答案以终止所有后代.
zhi*_*ang 100
要以递归方式终止进程树,请使用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 $@
Run Code Online (Sandbox Code Playgroud)
Onl*_*job 16
来自 pslist包的 rkill命令将给定信号(或SIGTERM默认情况下)发送到指定进程及其所有后代:
rkill [-SIG] pid/name...
Run Code Online (Sandbox Code Playgroud)
Kim*_*bel 11
布拉德的答案也是我推荐的,除非你可以awk完全取消,如果你使用--ppid选项ps.
for child in $(ps -o pid -ax --ppid $PPID) do ....... done
Run Code Online (Sandbox Code Playgroud)
小智 9
如果你知道传递父进程的pid,这里是一个应该工作的shell脚本:
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
Run Code Online (Sandbox Code Playgroud)
小智 9
我使用了这里描述的方法的一点点修改版本:https: //stackoverflow.com/a/5311362/563175
所以看起来像这样:
kill `pstree -p 24901 | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" " "`
Run Code Online (Sandbox Code Playgroud)
其中24901是父母的PID.
它看起来很丑陋,但它的工作完美无缺.
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
Run Code Online (Sandbox Code Playgroud)
我无法评论(声誉不够),所以我被迫添加一个新的答案,即使这不是一个真正的答案.
@olibre在2月28日给出的非常好的和彻底的答案存在一些问题.输出ps opgid= $PID将包含一个短于五位数的PID的前导空格,因为这样ps可以证明该列的合理性(严格对齐数字).在整个命令行中,这会产生一个负号,后跟空格,然后是组PID.简单的解决方法是管道ps,以tr去除空间:
kill -- -$( ps opgid= $PID | tr -d ' ' )
Run Code Online (Sandbox Code Playgroud)
要添加Norman Ramsey的答案,如果要创建进程组,可能值得查看setsid.
http://pubs.opengroup.org/onlinepubs/009695399/functions/setsid.html
如果调用进程不是进程组领导者,则setsid()函数将创建新会话.返回时,调用进程应该是该新进程的会话负责人,应该是新进程组的进程组负责人,并且没有控制终端.调用进程的进程组ID应设置为等于调用进程的进程ID.调用进程应该是新进程组中的唯一进程,也是新进程中唯一的进程.
我认为这意味着您可以从启动过程创建一个组.我在php中使用它,以便能够在启动后杀死整个进程树.
这可能是一个坏主意.我对评论很感兴趣.
小智 7
受到ysth评论的启发
kill -- -PGID
Run Code Online (Sandbox Code Playgroud)
而不是给它一个进程号,给它否定组号.像往常几乎任何命令一样,如果你想要一个以a开头的正常参数,
-而不是被解释为一个开关,那么在它之前--
以下shell函数与许多其他答案类似,但它适用于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
}
Run Code Online (Sandbox Code Playgroud)
小智 5
使用psutil使用python执行此操作非常容易.只需使用pip安装psutil,然后就可以使用一整套流程操作工具:
def killChildren(pid):
parent = psutil.Process(pid)
for child in parent.get_children(True):
if child.is_running():
child.terminate()
Run Code Online (Sandbox Code Playgroud)
根据志刚的回答,这可以避免自我杀戮:
init_killtree() {
local pid=$1 child
for child in $(pgrep -P $pid); do
init_killtree $child
done
[ $pid -ne $$ ] && kill -kill $pid
}
Run Code Online (Sandbox Code Playgroud)
如果您想按名称终止进程:
killall -9 -g someprocessname
Run Code Online (Sandbox Code Playgroud)
或者
pgrep someprocessname | xargs pkill -9 -g
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
365524 次 |
| 最近记录: |