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


当前回答

如果你的系统上有pstrree和perl,你可以尝试这样做:

perl -e 'kill 9, (`pstree -p PID` =~ m/\((\d+)\)/sg)'

其他回答

我进一步开发了志刚、木uri和固颈的溶液:

 #!/bin/bash

if test $# -lt 1 ; then
    echo >&2 "usage: kiltree pid (sig)"
    exit 1 ;
  fi ;

_pid=$1
_sig=${2:-TERM}

# echo >&2 "killtree($_pid) mypid = $$"
# ps axwwf | grep -6 "^[ ]*$_pid " >&2 ;

function _killtree () {
    local _children
    local _child
    local _success

    if test $1 -eq $2 ; then # this is killtree - don't commit suicide!
        echo >&2 "killtree can´t kill it´s own branch - some processes will survive." ; 
        return 1 ;
      fi ;
    # this avoids that children are spawned or disappear.
    kill -SIGSTOP $2 ;

    _children=$(ps -o pid --no-headers --ppid $2) ;        
    _success=0 
    for _child in ${_children}; do
        _killtree $1 ${_child} $3 ;
        _success=$(($_success+$?)) ;
      done ;

    if test $_success -eq 0 ; then
        kill -$3 $2
      fi ;
    # when a stopped process is killed, it will linger in the system until it is continued
    kill -SIGCONT $2
    test $_success -eq 0 ;
    return $?
    }

_killtree $$ $_pid $_sig

这个版本将避免杀死它的祖先进程——在以前的解决方案中,这会导致大量的子进程。

在确定子列表之前适当地停止进程,这样就不会创建或消失新的子列表。

停止的作业被杀死后,必须继续执行,才能从系统中消失。

使用psutil使用python非常容易做到这一点。只要用pip安装psutil,你就有了一整套进程操作工具:

def killChildren(pid):
    parent = psutil.Process(pid)
    for child in parent.get_children(True):
        if child.is_running():
            child.terminate()

如果你知道传递父进程的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

只使用属于该组的进程名删除该组:

kill -- -$(ps -ae o pid,pgrp,cmd | grep "[e]xample.py" | awk '{print $2}' | tail -1)

这是对olibre的答案的修改,但你不需要知道PID,只需要知道组中成员的名字。

解释:

要获得组id,您可以使用如下所示的参数执行ps命令,为您的命令grep它,但是使用引号格式化example.py,并使用括号作为第一个字母(这将过滤掉grep命令本身),然后通过awk过滤它以获得第二个字段,即组id。尾部的-1可以去除重复的组id。您使用$()语法将所有这些放到一个变量中,瞧——您得到了组id。用$(mess)替换上面的-groupid。

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

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