向过程组的所有成员发送信号的最佳方式是什么?
我想杀死整个进程树。 使用任何常用的脚本语言来做这件事的最好方法是什么? 我正在寻找一个简单的解决方案。
你不会说如果你想杀死的树是一个进程组。 (如果树是从服务器启动或shell命令行分叉的结果,通常情况下就是这种情况。)您可以使用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) 您可以从同一个进程树的任何进程ID( PID
)中检索PGID
kill -- -$(ps -o pgid= $PID | grep -o '[0-9]*')
(signal TERM
) kill -9 -$(ps -o pgid= $PID | grep -o '[0-9]*')
(signal KILL
) 特别感谢Tanager和Speakus对$PID
剩余空间和OSX兼容性的贡献。
说明
kill -9 -"$PGID"
=>发送信号9( KILL
)给所有的孩子和孙子...... PGID=$(ps opgid= "$PID")
=>从树的任何Process-ID中检索Process-Group-ID,而不仅仅是Process-Parent-ID。 ps opgid= $PID
变体是ps -o pgid --no-headers $PID
,其中pgid
可以被pgrp
替换。 但:
PID
小于5位时, ps
插入前导空格,并且如tanager所注意的那样右对齐。 您可以使用: PGID=$(ps opgid= "$PID" | tr -d ' ')
ps
总是打印标题,因此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
结论
我注意到在这个例子中PID
和PGID
是相等的( 28957
)。
这就是为什么我原本以为kill -- -$PID
就足够了。 但是如果进程在Makefile
产生,进程ID与组ID不同。
我想kill -- -$(ps -o pgid= $PID | grep -o [0-9]*)
当从另一个组ID(另一个进程树)调用时, kill -- -$(ps -o pgid= $PID | grep -o [0-9]*)
是杀死整个进程树的最简单的技巧。
pkill -TERM -P 27888
这将终止具有父进程ID 27888的所有进程。
或更健壮:
CPIDS=$(pgrep -P 27888); (sleep 33 && kill -KILL $CPIDS &); kill -TERM $CPIDS
该计划在33秒之后安排杀戮,并礼貌地要求进程终止。
看到这个答案终止所有的后代。
链接地址: http://www.djcxy.com/p/86025.html上一篇: What's the best way to send a signal to all members of a process group?