I'm trying to set up a shell script so that it runs background processes, and when I Ctrlc the shell script, it kills the children, then exits.The best that I've managed to come up with is this. It appears that the kill 0 -INT also kills the script before the wait happens, so the shell script dies before the children complete.Any ideas on how I can make this shell script wait for the children to die after sending INT?#!/bin/bashtrap 'killall' INTkillall() {    echo **** Shutting down... ****    kill 0 -INT    wait # Why doesn't this wait??    echo DONE}process1 &process2 &process3 &cat # wait forever
How can I kill and wait for background processes to finish in a shell script when I Ctrl+C it?
bash;shell;kill;signals;job control
Your kill command is backwards.Like many UNIX commands, options that start with a minus must come first, before other arguments.If you writekill -INT 0it sees the -INT as an option, and sends SIGINT to 0 (0 is a special number meaning all processes in the current process group).But if you writekill 0 -INTit sees the 0, decides there's no more options, so uses SIGTERM by default.  And sends that to the current process group, the same as if you didkill -TERM 0 -INT    (it would also try sending SIGTERM to -INT, which would cause a syntax error, but it sends SIGTERM to 0 first, and never gets that far.)So your main script is getting a SIGTERM before it gets to run the wait and echo DONE.Addtrap 'echo got SIGTERM' TERMat the top, just aftertrap 'killall' INTand run it again to prove this.As Stephane Chazelas points out, your backgrounded children (process1, etc.) will ignore SIGINT by default.In any case, I think sending SIGTERM would make more sense.Finally, I'm not sure whether kill -process group is guaranteed to go to the children first.  Ignoring signals while shutting down might be a good idea.So try this:#!/bin/bashtrap 'killall' INTkillall() {    trap '' INT TERM     # ignore INT and TERM while shutting down    echo **** Shutting down... ****     # added double quotes    kill -TERM 0         # fixed order, send TERM not INT    wait    echo DONE}./process1 &./process2 &./process3 &cat # wait forever