Stop shell script in the background, transmitting a signal

I have a bash script S1 shell that launches a new script S2 shell (contains only sleep 20 ) synchronously, i.e. in the foreground.

I want the following:

When I send SIGTERM or SIGINT to S1 , both S1 and S2 should stop.

Actually this works if I run S1 at the forefront command line a, if I press CTRL-C (regardless of whether I explicitly block SIGINT in scripts or not).

When I run S1 in the background and then send it a SIGINT signal with kill -s SIGINT $! , it accepts until S2 completes its normal processing, i.e. S2 not interrupted.

My use case is the latter, and I need a way to interrupt both S1 and S2 , sending a signal only to S1 .

+4
source share
2 answers

S1.sh:

 #!/bin/sh on_term() { echo "S1: Sending TERM to S2.sh" pkill -TERM S2.sh echo "S1: Waiting for S2 to complete..." } trap "on_term" TERM echo "S1: Forking a child..." ./S2.sh & while [ 1 == 1 ]; do wait if [ $? -eq 0 ]; then break fi done echo "S1: Done!" 

S2.sh:

 #!/bin/sh on_term() { echo "S2: Terminating..." exit -1 } trap "on_term" TERM echo "S2: Sleeping..." sleep 5 echo "S2: Done!" 

Good luck

+2
source

If you start S1 from the command line, send a signal to all processes in the process group using the job specification starting with%, for example kill -INT %+ .

If you run S1 from another S3 script, perhaps it should end with S1 and S2 on SIGINT , which boils down to the above. Otherwise, you can try using job management, for example

 set -m S1 & set +m pid=$! ... kill -INT -- -$pid 

but this may not work reliably with all shells or if there is no control terminal. Manually redirecting the signal, as in Elijah’s answer, is an alternative.

+2
source

All Articles