我想杀死整个进程树。使用通用脚本语言实现这一目标的最佳方法是什么?我在寻找一个简单的解决办法。


当前回答

这是我使用bash脚本杀死所有子进程的版本。 它不使用递归,依赖于pgrep命令。

Use

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//,/ }

其他回答

pkill -TERM -P 27888

这将杀死父进程ID为27888的所有进程。

或者更有力:

CPIDS=$(pgrep -P 27888); (sleep 33 && kill -KILL $CPIDS &); kill -TERM $CPIDS

它将kill安排在33秒后,并礼貌地要求进程终止。

请参阅终止所有子代的答案。

如果你知道你想要杀死的东西的pid,你通常可以从会话id开始,和同一会话中的所有东西。我会仔细检查,但我使用这个脚本在循环中启动rsync,我想要死亡,而不是启动另一个(因为循环),因为如果我只是杀死所有的rsync。

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 )))

在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

brad的答案也是我推荐的,除了如果你使用——ppid选项ps,你可以完全放弃awk。

for child in $(ps -o pid -ax --ppid $PPID) do ....... done

我不能评论(没有足够的声誉),所以我被迫添加一个新的答案,即使这不是一个真正的答案。

@olibre在2月28日给出了一个非常好的、彻底的回答,但有一个小问题。ps opgid= $PID的输出将包含小于5位的PID的前导空格,因为ps正在对列进行对齐(将数字右对齐)。在整个命令行中,这会导致一个负号,后面跟着空格(s),然后是组PID。简单的解决方案是通过管道将ps传送到tr以删除空格:

kill -- -$( ps opgid= $PID | tr -d ' ' )