Signal handling in a shell script
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
Comments
-
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 about 10 yearsI 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 about 10 yearsPlease 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 about 10 yearsWhen 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 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 theAprogram
command? -
ernesto about 10 yearsBut 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 about 10 yearsAfter 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 about 10 years@ernesto Yes, I understand that
SIGINT
is notSIGKILL
orSIGHUP
. You'd need to start the other process in the background too and capture it's PID to pass totrap
. Refer to the update above. -
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 about 10 yearsI get into same problem as you. Then I found this
-
Martin over 2 yearsI 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.