如何杀死shell的所有子进程?

37 bash shell fork kill process

我正在写一个bash脚本,它做了几件事.

最初它启动了几个监视器脚本,每个脚本都运行一些其他工具.

在我的主脚本结束时,我想杀死从我的shell中生成的所有东西.

所以,它可能看起来像这样:

#!/bin/bash

some_monitor1.sh &
some_monitor2.sh &
some_monitor3.sh &

do_some_work
...

kill_subprocesses
Run Code Online (Sandbox Code Playgroud)

问题是这些监视器中的大多数都会生成自己的子进程,所以这样做(例如):killall some_monitor1.sh并不总是有用.

还有其他办法可以处理这种情况吗?

pih*_*agy 87

pkill -P $$
Run Code Online (Sandbox Code Playgroud)

适合(只是杀死它自己的后代)

编辑:我有一个downvote,不知道为什么.无论如何这里是-P的帮助

   -P, --parent ppid,...
          Only match processes whose parent process ID is listed.
Run Code Online (Sandbox Code Playgroud)

并且$$脚本本身进程ID

  • 不,这里没有竞争条件.pkill是pgrep的符号链接,在第441行的pgrep.c中你可以看到pkill在检查要杀死的进程时会跳过它自己.因此,在杀死所有其他孩子后,pkill命令将定期终止. (12认同)
  • 不杀死通过直接子进程的后代。 (4认同)
  • @Chexpir:这不是bash的一部分.但是,如果您的系统没有它,那么您在deep5h1t.它是Ubuntu下`procps`包的一部分,这个包包含其他核心实用程序,如`free`,`kill`和`ps`. (3认同)
  • @pihentagy 没有竞争条件吗?pkill 本身是当前 shell 的子级。因此,“pkill -P $$”会在所有其他进程被杀死之前杀死“pkill”进程吗? (3认同)

Pét*_*rök 27

启动每个子进程后,您可以获取其ID

ID=$!
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用存储的PID来查找和终止所有孙子等进程,如此此处所述.


Pau*_*ce. 16

如果使用负PID,kill则会终止进程组.例:

kill -- -1234

  • @LarsQuentin:与 1 相比,负 1 是不同且特殊的。[手册页](https://man7.org/linux/man-pages/man1/kill.1.html) 说“PID 大于的所有进程1 已发出信号。” (2认同)

Jür*_*zel 9

kill $(jobs -p)
Run Code Online (Sandbox Code Playgroud)

Rhys Ulerich的建议:

注意竞争条件,使用[下面的代码]完成Jürgen建议的内容,而不会在没有任何作业时导致错误

[[ -z "$(jobs -p)" ]] || kill $(jobs -p)
Run Code Online (Sandbox Code Playgroud)

  • 注意竞争条件,使用'test -z"\`jobs -p \`"|| kill \`jobs -p \`'完成Jürgen建议的内容,不会在没有作业时导致错误 (3认同)

小智 7

扩展pihentagy的答案以递归方式杀死所有后代(不仅仅是孩子):

kill_descendant_processes() {
    local pid="$1"
    local and_self="${2:-false}"
    if children="$(pgrep -P "$pid")"; then
        for child in $children; do
            kill_descendant_processes "$child" true
        done
    fi
    if [[ "$and_self" == true ]]; then
        kill -9 "$pid"
    fi
}
Run Code Online (Sandbox Code Playgroud)

现在

kill_descendant_processes $$
Run Code Online (Sandbox Code Playgroud)

将杀死当前脚本/ shell的descedants.

(在Mac OS 10.9.5上测试.仅依赖于pgrep和kill)

  • 好的,但请不要使用`kill -9`"默认情况下",更改要退出的进程!http://serverfault.com/a/415744/55046 (3认同)

yby*_*ygu 6

带有选项“-P”的 pkill 应该会有所帮助:

pkill -P $(pgrep some_monitor1.sh)
Run Code Online (Sandbox Code Playgroud)

从手册页:

   -P ppid,...
          Only match processes whose parent process ID is listed.
Run Code Online (Sandbox Code Playgroud)

linuxquests.org 上有一些讨论,请查看:

http://www.linuxquestions.org/questions/programming-9/use-only-one-kill-to-kill-father-and-child-processes-665753/