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


当前回答

我知道这很老了,但这是我找到的更好的解决方案:

killtree() { 
    for p in $(pstree -p $1 | grep -o "([[:digit:]]*)" |grep -o "[[:digit:]]*" | tac);do
        echo Terminating: $p 
        kill $p
    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
}

rkill命令从pslist包发送给定的信号(或SIGTERM默认)到指定的进程及其所有后代:

rkill [-SIG] pid/name...

我使用了这里描述的方法的一个稍微修改的版本: https://stackoverflow.com/a/5311362/563175

它看起来是这样的:

kill `pstree -p 24901 | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" " "`

其中24901是父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,我想。