Question

I want to trap a signal send from Script-A.sh to Script-B.sh so in Script-A.sh i use the command:

(Send SIGINT to Script-B.sh)
kill -2 $PID_Script-B.sh

And in Script-B.sh i catch the signal and call function Clean

trap 'Clean' 2

It does not work, instead the Script-B.sh is killed right away without performing the Clean !!

What i notice also is that if i want to send SIGINT from terminal to any script that traps it, a ctrl-c will be caught correctly, but not if i specify the signal via the command kill -2 $pid_of_script

Any idea about the difference between the two method to send the SIGINT (ctrl-c VS kill -2 $pid_of_script), and how i can send a SIGINT from a script to another?

Was it helpful?

Solution

I was able to reproduce the behavior you report. My hypothesis is that since the script is running from a non-interactive shell (as a child of a script) that SIGINT, which is a keyboard signal, is ignored.

From info bash:

Background processes are those whose process group ID differs from the terminal's; such processes are immune to keyboard-generated signals.

I have found that if you trap and kill using another signal such as SIGUSR1 it works.

Additional information from man bash:

Non-builtin commands run by bash have signal handlers set to the values inherited by the shell from its parent. When job control is not in effect, asynchronous commands ignore SIGINT and SIGQUIT in addition to these inherited handlers.

and

If bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes.

and

Any trap on SIGCHLD is executed for each child that exits.

OTHER TIPS

In script A: Trap function will look like following which will call trap_mesg() function in scriptA.sh. KILL Signal (2/INTerrupt, 5/TERMinate-default). All, you have to do is to get the PID of a runing scriptB.sh process/session once scriptB.sh is called from scriptA.sh (nohup ... & will give you or use ps command)

trap_mesg ()
{
 #...do something here for script B..
 # i.e. 
 kill -2 PID_of_ScriptB.sh_running_process_session
 sleep 10; #just in case, not reqd though.
 #show using ps -eAf|grep "scriptB" ... if null means, scriptB is gone. user is happy now.
 #...before actually exiting out...
 #show script A is exiting out as ScriptB is dead already, time for scriptA now.
 #...do something here..
}

#####################################
## Trap signals : INT, TERM. catch ##
#####################################
#Set NULL/Blank value to trap_call. This variable will help in running trap_mesg only once during the life of this script.
trap_call="";

trap 'if [ -z ${trap_call} ]; then trap_call="1"; trap_mesg ; fi' 2 15
##################################




Now, within scriptB.sh, do the same/similar but just for scriptB trap job (like calling clean).

clean ()
{
echo "karoge seva to milega meva"; 
rm -fr /some/folder_file
}

trap_mesg ()
{
 #...do something here JUST for script B trap message work..
 # i.e. 
 clean;
 #...do something here..
}

#####################################
## Trap signals : INT, TERM. catch ##
#####################################
#Set NULL/Blank value to trap_call. This variable will help in running trap_mesg only once during the life of this script.
trap_call="";

trap 'if [ -z ${trap_call} ]; then trap_call="1"; trap_mesg ; fi' 2 15
##################################

This way, you dont have to source/call scriptB.sh within scriptA.sh as ". scriptB.sh ...."

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top