4

I have a bash shell script S1 that starts another shell script S2 (contains just sleep 20) synchronously, i.e. in the foreground.

What I want is the following:

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

Actually that works if I start S1 on the command line in the foreground an if I press CTRL-C (independent of whether I trap SIGINT in the scripts explicitly or not).

When I start S1 in the background and then send it the SIGINT signal with kill -s SIGINT $! it takes until S2 terminates its normal processing, i.e. S2 is not interrupted.

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

Caleb
  • 5,084
  • 1
  • 46
  • 65
Armin
  • 41
  • 1
  • 2
  • searching for `[unix] SIGINT` returned numerous promising answers. Particularly http://stackoverflow.com/questions/4042201/how-does-sigint-relate-to-the-other-termination-signals. Good luck. – shellter May 27 '11 at 14:39

2 Answers2

2

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!"

Have fun!

Ilya Matveychikov
  • 3,936
  • 2
  • 27
  • 42
  • You should use `$!` rather than shutting down any process with a certain name. – jilles May 27 '11 at 10:53
  • Of course, starting S2 in the background is a solution. But can I achieve the same without starting S2 in the background? Why is the behavior different as I described above (ctrl-c when S1 runs in foreground vs. "kill -s SIGINT" when S1 was started in the background)? – Armin May 27 '11 at 11:41
2

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

If you are starting S1 from another script S3, perhaps it should terminate with S1 and S2 on SIGINT, which reduces to the above. Otherwise, you can try using job control like

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

but this may not work reliably with all shells, or if there is no controlling terminal. Manually forwarding the signal as in Ilya's answer is an alternative.

jilles
  • 10,509
  • 2
  • 26
  • 39