Signal handling in a shell script

19,375

Solution 1

You start sleep in the background. As such, it is not killed when you kill the script.

If you want to kill sleep too when the script is terminated, you'd need to trap it.

sleep 500 &
sid=($!)                   # Capture the PID of sleep
trap "kill ${sid[@]}" INT   # Define handler for SIGINT

Aprogram arg1 arg2 & # Aprogram is a program which runs for an hour.
sid+=($!)
echo "done"

Now sending SIGINT to your script would cause sleep to terminate as well.

Solution 2

You need to use trap to catch signals:

To just ignore SIGINT use:

trap '' 2

if you want to specify some special action for this you can make it that in line:

trap 'some commands here' 2

or better wrap it into a function

function do_for_sigint() {
 ...
}

trap 'do_for_sigint' 2

and if you wish to allow your script to finish all it's tasks first:

keep_running="yes"

trap 'keep_running="no"' 2

while [ $keep_running=="yes" ]; do
 # main body of your script here
done
Share:
19,375
ernesto
Author by

ernesto

developer

Updated on July 29, 2022

Comments

  • ernesto
    ernesto almost 2 years

    Following is a shell script (myscript.sh) I have:

    #!/bin/bash
    
    sleep 500 &
    
    Aprogram arg1 arg2  # Aprogram is a program which runs for an hour.
    
    echo "done"
    

    I launched this in one terminal, and from another terminal I issued 'kill -INT 12345'. 12345 is the pid of myscript.sh.

    After a while I can see that both myscript.sh and Aprogram have been dead. However 'sleep 500 &' is still running.

    Can anyone explain why is this behavior?

    Also, when I issued SIGINT signal to the 'myscript.sh' what exactly is happening? Why is 'Aprogram' getting killed and why not 'sleep' ? How is the signal INT getting transmitted to it's child processes?

  • ernesto
    ernesto about 10 years
    I understand that trap can be used. But I am looking for an explanation of this behavior. What will shell do when it receives SIGINT. For example look at this article mywiki.wooledge.org/SignalTrap#When_is_the_signal_handled.3F . It has some details but I am still not clear.
  • ernesto
    ernesto about 10 years
    Please see my comment above. I understand that trap works. But I am looking for an explanation why a background job is not getting killed and it looks like shell waits for Aprogram to complete when it receives SIGINT signal. Please see this: mywiki.wooledge.org/SignalTrap#When_is_the_signal_handled.3F
  • pawel7318
    pawel7318 about 10 years
    When the parent dies than it's children are still running. It's normal behavior. You can see how it looks like with pstree -aup
  • devnull
    devnull about 10 years
    @ernesto A background job is a different process altogether. As such, specifying the PID of the script wouldn't delete it. Regarding the other question, what do you observe if you send SIGINT to a script that contains only the Aprogram command?
  • ernesto
    ernesto about 10 years
    But here in this case, after myscript.sh recieved SIGINT, it waits for Aprogram to complete and then both of them die. But sleep continues to exist. One child is getting killed and the other one is not. It's a background process, but still myscript.sh is it's parent.
  • ernesto
    ernesto about 10 years
    After sending SIGINT via 'kill -INT pid', myscript.sh still exists, and Aprogram also continues to print the output unless it really completed it's execution. Please note the method of killing, it's not Ctrl+c , it's with 'kill -INT pid'. This seems to have a different effect.
  • devnull
    devnull about 10 years
    @ernesto Yes, I understand that SIGINT is not SIGKILL or SIGHUP. You'd need to start the other process in the background too and capture it's PID to pass to trap. Refer to the update above.
  • pawel7318
    pawel7318 about 10 years
    @Jayesh: every process is child of its parent, except the init with pid 1 (to be honest even init has its parent start_init but this is a different story)
  • pawel7318
    pawel7318 about 10 years
    I get into same problem as you. Then I found this
  • Martin
    Martin over 2 years
    I believe this is wrong. If you run Aprogram in the background, the script will simply go on and finish on its own, leaving Aprogram running until you kill it.