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

时间:2010-04-11 19:34:24

标签: bash shell process fork kill

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

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

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

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

#!/bin/bash

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

do_some_work
...

kill_subprocesses

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

处理这种情况的其他任何方式?

7 个答案:

答案 0 :(得分:87)

pkill -P $$

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

编辑:我得到了一个downvote,不知道为什么。无论如何这里是-P

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

$$process id of the script itself

答案 1 :(得分:24)

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

获取其ID
ID=$!

然后您可以使用存储的PID查找并删除所有孙子等进程,如herehere所述。

答案 2 :(得分:12)

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

kill -- -1234

答案 3 :(得分:9)

kill $(jobs -p)

Rhys Ulerich的建议:

  

使用[以下代码]警告竞争条件,完成Jürgen所建议的内容,而不会在没有作业时导致错误

[[ -z "$(jobs -p)" ]] || kill $(jobs -p)

答案 4 :(得分:6)

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

会杀死当前脚本/ shell的内容。

(在Mac OS 10.9.5上测试。仅取决于pgrep并杀死)

答案 5 :(得分:3)

使用选项“-P”可以提供帮助:

pkill -P $(pgrep some_monitor1.sh)

来自手册页:

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

有关linux quests.org的一些讨论,请查看:

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

答案 6 :(得分: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