55

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

一开始它会启动几个监控脚本,每个脚本都运行一些其他工具。

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

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

#!/bin/bash

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

do_some_work
...

kill_subprocesses

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

有没有其他方法来处理这种情况?

4

7 回答 7

121
pkill -P $$

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

编辑:我投了反对票,不知道为什么。无论如何,这里是 -P 的帮助

   -P, --parent ppid,...
          Only match processes whose parent process ID is listed.

并且$$脚本本身的进程ID

于 2013-07-12T12:42:02.367 回答
32

启动每个子进程后,您可以使用

ID=$!

然后,您可以使用存储的 PID 来查找并杀死所有孙子等进程,如此此处所述。

于 2010-04-11T19:38:45.467 回答
28

如果您使用负 PID,kill它将杀死一个进程组。例子:

kill -- -1234

于 2010-04-11T20:49:06.950 回答
13

扩展 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
}

现在

kill_descendant_processes $$

将杀死当前脚本/外壳的后代。

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

于 2014-11-17T06:28:54.490 回答
11
kill $(jobs -p)

Rhys Ulerich的建议:

警告竞争条件,使用 [下面的代码] 完成 Jürgen 建议的操作,而不会在不存在作业时导致错误

[[ -z "$(jobs -p)" ]] || kill $(jobs -p)
于 2010-04-11T20:04:07.497 回答
5

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

pkill -P $(pgrep some_monitor1.sh)

从手册页:

   -P ppid,...
          Only match processes whose parent process ID is listed.

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

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

于 2010-04-12T10:27:24.543 回答
1

我喜欢以下简单的方法:使用具有某些名称/值的环境变量启动子进程,然后使用它来杀死子进程。最方便的是使用正在运行的 bash 脚本的进程 ID,即 $$。当子进程在继承环境时启动另一个子进程时,这也适用。

所以像这样启动子流程:

MY_SCRIPT_TOKEN=$$ some_monitor1.sh &
MY_SCRIPT_TOKEN=$$ some_monitor2.sh &

然后像这样杀死他们:

ps -Eef | grep "MY_SCRIPT_TOKEN=$$" | awk '{print $2}' | xargs kill
于 2021-04-13T19:52:25.967 回答