bash 如何从脚本发送信号 SIGINT 到脚本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2524937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 21:52:32  来源:igfitidea点击:

How to send a signal SIGINT from script to script?

bashsignalskillbash-trap

提问by Debugger

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

我想捕获从 Script-A.sh 发送到 Script-B.sh 的信号,因此在 Script-A.sh 中我使用以下命令:

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

(发送 SIGINT 到 Script-B.sh)
kill -2 $PID_Script-B.sh

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

在 Script-B.sh 中,我捕捉到信号并调用函数 Clean

trap 'Clean' 2

陷阱“清洁”2

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

它不起作用,而是立即杀死 Script-B.sh 而不执行 Clean !

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

我还注意到,如果我想从终端向任何捕获它的脚本发送 SIGINT,actrl-c将被正确捕获,但如果我通过命令指定信号则不会kill -2 $pid_of_script

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

关于发送 SIGINT ( ctrl-cVS kill -2 $pid_of_script)的两种方法之间的区别,以及如何将 SIGINT 从脚本发送到另一个的任何想法?

采纳答案by Paused until further notice.

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

我能够重现您报告的行为。我的假设是,由于脚本是非交互式 shell(作为脚本的子项)运行的SIGINT,因此忽略了作为键盘信号的 。

From info bash:

来自info bash

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

后台进程是那些进程组ID与终端不同的进程;此类进程不受键盘生成信号的影响。

I have found that if you trapand killusing another signal such as SIGUSR1it works.

我发现,如果你trapkill使用其他信号,比如SIGUSR1它的工作原理。

Additional information from man bash:

附加信息来自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.

bash 运行的非内置命令将信号处理程序设置为 shell 从其父级继承的值。当作业控制无效时,除了这些继承的处理程序之外,异步命令还会忽略 SIGINT 和 SIGQUIT。

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.

如果 bash 正在等待命令完成并接收到设置了陷阱的信号,则在命令完成之前不会执行陷阱。

and

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

SIGCHLD 上的任何陷阱都会为每个退出的孩子执行。

回答by AKS

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)

在脚本 A 中:Trap 函数将如下所示,它将调用 scriptA.sh 中的 trap_mesg() 函数。KILL 信号(2/中断,5/终止-默认)。所有,您要做的就是在从 scriptA.sh 调用 scriptB.sh 后获取正在运行的 scriptB.sh 进程/会话的 PID(nohup ... & 将给您或使用 ps 命令)

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).




现在,在 scriptB.sh 中,执行相同/类似的操作,但仅针对 scriptB 陷阱作业(例如调用 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 ...."

这样,您不必将 scriptA.sh 中的 scriptB.sh 源/调用为“.scriptB.sh ....”