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


当前回答

在杀死孩子之前杀死父母可能更好;否则,父母可能会在他自杀之前再次繁殖新的孩子。这些会在杀戮中幸存下来。

我的ps版本和上面的不一样;也许太老了,所以奇怪的握手……

使用shell脚本而不是shell函数有很多优点…

然而,这基本上是志刚的想法


#!/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

其他回答

如果你想按名称杀死一个进程:

killall -9 -g someprocessname

or

pgrep someprocessname | xargs pkill -9 -g

根据志刚的回答,这可以避免自我毁灭:

init_killtree() {
    local pid=$1 child

    for child in $(pgrep -P $pid); do
        init_killtree $child
    done
    [ $pid -ne $$ ] && kill -kill $pid
}

老问题,我知道,但所有的回答似乎都叫ps,我不喜欢。

这个基于awc的解决方案不需要递归,只调用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集中移除之前。

请记住,这里存在一个竞争条件,但这对所有的解都是正确的(据我所知)。它做了我所需要的,因为我需要它的脚本不会创建大量短暂的子进程。

对于读者来说,一个练习是将其设置为2次循环:在第一次传递之后,将SIGSTOP发送给p列表中的所有进程,然后再次循环运行ps,在第二次传递之后发送SIGTERM,然后是SIGCONT。如果你不关心美好的结局,那么第二遍可能只是SIGKILL,我想。

要递归地杀死进程树,请使用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 -ef检查进程id。 通过输入Kill -9 <pid>来终止进程