How to kill all subprocesses of shell?


Bash Problem Overview

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 & & &



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

Any other way to handle this situation?

Bash Solutions

Solution 1 - Bash

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

Solution 2 - Bash

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


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

Solution 3 - Bash

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

kill -- -1234

Solution 4 - Bash

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
    if [[ "$and_self" == true ]]; then
        kill -9 "$pid"


kill_descendant_processes $$

will kill descedants of the current script/shell.

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

Solution 5 - Bash

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)

Solution 6 - Bash

pkill with optioin "-P" should help:

pkill -P $(pgrep

from man page:

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

There are some discussions on, please check:

Solution 7 - Bash

I like the following straightforward approach: start the subprocesses with an environment variable with some name/value and use this to kill the subprocesses later. Most convenient is to use the process-id of the running bash script i.e. $$. This also works when subprocesses starts another subprocesses as the environment is inherited.

So start the subprocesses like this:


And afterwards kill them like this:

ps -Eef | grep "MY_SCRIPT_TOKEN=$$" | awk '{print $2}' | xargs kill

Solution 8 - Bash

Similar to above, just a minor tweak to kill all processes indicated by ps:

ps -o pid= | tail -n +2 | xargs kill -9

Perhaps sloppy / fragile, but seemed to work at first blush. Relies on fact that current process ($$) tends to be first line.

Description of commands, in order:

  1. Print PIDs for processes in current terminal, excl. header column
  2. Start from Line 2 (excl. current terminal's shell)
  3. Kill those procs

Solution 9 - Bash

I've incorporated a bunch of the suggestions from the answers here into a single function. It gives time for processes to exit, murders them if they take too long, and doesn't have to grep through output (eg, via ps)

# This function will kill all sub jobs.
function KillJobs() {
  [[ -z "$(jobs -p)" ]] && return # no jobs to kill
  local SIG="INT" # default to a gentle goodbye
  [[ ! -z "$1" ]] && SIG="$1" # optionally send a different signal
  # my version of 'kill' doesn't seem to understand `kill -- -${PID}`
  #jobs -p | xargs -I%% kill -s "$SIG" -- -%% # kill each job's processes group
  jobs -p | xargs kill -s "$SIG" # kill each job's processes group
  ## give the processes a moment to die, before forcing them to.
  [[ "$SIG" != "KILL" ]] && {
    sleep 0.2
    KillJobs "KILL"

I also tried to get a variation working with pkill, but on my system (xubuntu 21.10) it does absolutely nothing.

# This function doesn't seem to work.
function KillChildren() {
  local SIG="INT" # default to a gentle goodbye
  [[ ! -z "$1" ]] && SIG="$1" # optionally send a different signal
  pkill --signal "$SIG" -P $$ # kill descendent's and their processes groups
  [[ "$SIG" != "KILL" ]] && {
    # give them a moment to die before we force them to.
    sleep 0.2
    KillChildren "KILL" ;


All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser80168View Question on Stackoverflow
Solution 1 - BashpihentagyView Answer on Stackoverflow
Solution 2 - BashPéter TörökView Answer on Stackoverflow
Solution 3 - BashDennis WilliamsonView Answer on Stackoverflow
Solution 4 - BashAdam CathView Answer on Stackoverflow
Solution 5 - BashJürgen HötzelView Answer on Stackoverflow
Solution 6 - BashybyyguView Answer on Stackoverflow
Solution 7 - BashcyberbirdView Answer on Stackoverflow
Solution 8 - BashEric CousineauView Answer on Stackoverflow
Solution 9 - BashBrandonView Answer on Stackoverflow