Bash running multiple program and handling close

background-processbashkillshell-script

I have a bash script that runs multiple programs

#!/bin/sh
python program1.py &
python program2.py &
other programs ... &
lastProgram

I run it as ./myscript.sh

When I hit Ctrl+C to close the lastProgram it exit and all the other ones keep running in the background. The problem is that the other programs need to be terminated.

Which is the proper way to handle the closing of all the programs started from the script?

Best Answer

Collect the process ID's, kill the background processes on exit.

#!/bin/bash
killbg() {
        for p in "${pids[@]}" ; do
                kill "$p";
        done
}
trap killbg EXIT
pids=()
background job 1 & 
pids+=($!)
background job 2... & 
pids+=($!)
foreground job

Trapping EXIT runs the function when the shell exits, regardless of the reason. You could change that to trap killbg SIGINT to only run it on ^C.

This doesn't check if one of the background processes exited before the script tries to shoot them. If they do, you could get errors, or worse, shoot the wrong process.


Or kill them by job id. Let's read the output of jobs to find out which ones are still active.

#!/bin/bash 
killjobs() {
    for x in $(jobs | awk -F '[][]' '{print $2}' ) ; do 
        kill %$x
    done
}
trap killjobs EXIT
sleep 999 &
sleep 1 &
sleep 999 &
sleep 30

If you run background processes that spawn other processes (like a subshell: (sleep 1234 ; echo foo) &), you need to enable job control with set -m ("monitor mode") for this to work. Otherwise just the lead process is terminated.

Related Question