Kill all sub-processes of a bash script with SIGINT (CTRL-C)

If you have a bash script running with a very long loop (or infinite one) and starting multiple background processes, you will notice that when you stop the main process, all the child processes will continue to live until you restart the machine or you kill them one by one.

So that you can easily stop all the sub-processes when you stop the main process, you just need to use the trap function to capture the event and stop all the jobs in the background.

Here’s an example of code, executing 2 infinite functions:

#!/bin/bash

# Get number of seconds of uptime
func_1() { 
    while true
    do
        echo "Press Ctrl-C to stop me even if I'm a child..."
        sleep 10
    done
}

func_2() {
    while true
    do
        echo `date`
        sleep 3
    done
}

#####################
### MAIN PROGRAM ####
#####################

declare -a pids
declare -a functions=(func_1 func_2)

# Parse list of devices
i=0
for func in "${functions[@]}"
do
    ${func} &
    pids[${i}]=$!
    i=$((i+1))
done

trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT

# wait for all pids
for pid in ${pids[*]}; do
    wait $pid
done

Output of the script until we hit Ctrl-C:

# bash stop_proc.sh
Press Ctrl-C to stop me even if I'm a child…
Tue Nov 14 22:28:55 UTC 2022
Tue Nov 14 22:28:58 UTC 2022
Tue Nov 14 22:29:01 UTC 2022
Tue Nov 14 2:29:04 UTC 2022
Press Ctrl-C to stop me even if I'm a child…
Tue Nov 14 22:29:07 UTC 2022
Tue Nov 14 22:29:10 UTC 2022
^CTerminated