How to kill all subprocesses of shell?

I'm writing a bash script, which does several things.

In the beginning it starts several monitor scripts, each of them runs some other tools.

At the end of my main script, I would like to kill all things that were spawned from my shell.

So, it might looks like this:

#!/bin/bash

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

do_some_work
...

kill_subprocesses

The thing is that most of these monitors spawn their own subprocesses, so doing (for example): killall some_monitor1.sh will not always help.

Any other way to handle this situation?


pkill -P $$

will fit (just kills it's own descendants)

EDIT: I got a downvote, don't know why. Anyway here is the help of -P

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

and $$ is the process id of the script itself


After starting each child process, you can get its id with

ID=$!

Then you can use the stored PIDs to find and kill all grandchild etc. processes as described here or here.


If you use a negative PID with kill it will kill a process group. Example:

kill -- -1234


Extending pihentagy's answer to recursively kill all descendants (not just children):

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
}

Now

kill_descendant_processes $$

will kill descedants of the current script/shell.

(Tested on Mac OS 10.9.5. Only depends on pgrep and kill)


kill $(jobs -p)

Rhys Ulerich's suggestion:

Caveat a race condition, using [code below] accomplishes what Jürgen suggested without causing an error when no jobs exist

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