Do not use kill -9 .
You want to enable the trap on EXIT , not INT .
trap 'kill $fooPid $barPid' EXIT foo & fooPid=$! bar & barPid=$! wait
This solution will always terminate foo and bar , regardless of the reason for its exit (excluding its SIGKILL 'ed).
If you want to avoid holding the PID (which has some problems with race conditions), you can do this instead:
trap 'kill $(jobs -p)' EXIT foo & bar & wait
This is the best (and cleaner!) Solution if your script has no other tasks.
Ps : These solutions mean foo and bar can write to your terminal (your script stdout ), but none of them can read from stdin . If you need to read either foo or bar with stdin, the solution becomes a bit more complicated.
source share