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)