How to propagate a signal through a collection of scripts?

Debugger picture Debugger · Mar 26, 2010 · Viewed 9.2k times · Source

I have an collection of scripts which are controlled by a main one. I want to trap the signal ctrl+c in the main script and propagate it to the others. The other scripts should trap this signal as well ( from the main script ) and do some clean-up ...

I have tried to send kill -s SIGINT to the children, but they seem they are unable to catch the signal( even if trap 'Cleanup' SIGINT being defined on the children scripts )

Any clues how to realize this?

Answer

lhunath picture lhunath · Aug 5, 2010

The following example demonstrates a parent script that does something (sleep 5) after it starts two children that do their own thing (also sleep 5). When the parent exits (for whatever reason) it signals the children to terminate (don't SIGINT, termination is signaled by SIGTERM, also the default kill signal). The children then do their thing on reception of SIGTERM. If the children are scripts of their own, I recommend you change the trap on TERM into a trap on EXIT so that the children clean up no matter what the cause of their termination be (so long as it's trappable).

Notice my use of wait. Bash does not interrupt running non-builtin commands when it receives a signal. Instead, it waits for them to complete and handles the signal after the command is done. If you use wait, bash stops waiting immediately and handles the signal right away.

#!/usr/bin/env bash

trap 'echo parent shutting down; kill $(jobs -p)' EXIT

{ trap 'echo child 1 signaled' TERM; sleep 5 & wait; } &
{ trap 'echo child 2 signaled' TERM; sleep 5 & wait; } &

sleep 5