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


当前回答

老问题,我知道,但所有的回答似乎都叫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,我想。

其他回答

如果你知道你想要杀死的东西的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 )))

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

rkill [-SIG] pid/name...

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

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

输入ps -ef检查进程id。 通过输入Kill -9 <pid>来终止进程

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

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

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