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


当前回答

立即终止整个进程组,就像^C一样:

PID="$(pgrep -f unique_command_line_part)"
if [[ -n "$PID" ]]
then
    PGID="$(ps --no-headers -p $PID -o pgid)"
    kill -SIGINT -- -${PGID// /}
fi

每一行都在这个答案中进行了解释

其他回答

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

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

你没有说你想要杀死的树是否是一个单独的进程组。(如果树是从服务器启动或shell命令行派生出来的,通常会出现这种情况。)您可以使用GNU ps发现进程组,如下所示:

 ps x -o  "%p %r %y %x %c "

如果它是您想要终止的进程组,只需使用kill(1)命令,但不给它一个进程号,而是给它一个组号的负数。例如,要终止5112组中的所有进程,请使用kill -TERM——-5112。

下面是@zhigang的答案的一个变种,它没有AWK,只依赖于Bash的本地解析可能性:

function killtree {
  kill -STOP "$1"
  ps -e -o pid= -o ppid= | while read -r pid ppid
                           do
                             [[ $ppid = $1 ]] || continue
                             killtree "$pid"  || true # Skip over failures
                           done
  kill -CONT "$1"          
  kill -TERM "$1"
}

它在mac和Linux上都运行得很好。在您不能依赖于管理流程组的情况下——比如在编写测试必须在多个环境中构建的软件的脚本时——这种遍历树技术绝对是有用的。

下面的代码已经在FreeBSD, Linux和MacOS X上进行了测试,只依赖于pgrep和kill (ps -o版本在BSD下不工作)。第一个参数是父pid,子pid必须被终止。第二个参数是一个布尔值,用于确定父pid是否也必须终止。

KillChilds() {
        local pid="${1}"
        local self="${2:-false}"

        if children="$(pgrep -P "$pid")"; then
                for child in $children; do
                        KillChilds "$child" true
                done
        fi

        if [ "$self" == true ]; then
                kill -s SIGTERM "$pid" || (sleep 10 && kill -9 "$pid" &)
        fi
}

KillChilds $$ > /dev/null 2>&1

这将向shell脚本中的任何子/孙辈进程发送SIGTERM,如果SIGTERM没有成功,它将等待10秒,然后发送kill。


答:早些时候

下面的代码也可以工作,但是会在BSD上杀死shell本身。

KillSubTree() {
    local parent="${1}"
    for child in $(ps -o pid=$parent); do
            if [ $$ -ne $child ]; then (kill -s SIGTERM $child || (sleep 10 && kill -9 $child & )) > /dev/null 2>&1 ; fi
    done
}
# Example lanch from within script
KillSubTree $$ > /dev/null 2>&1

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

我的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