问题 如何从脚本向脚本发送信号SIGINT? BASH


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

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

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

陷阱'清洁'2

它不起作用,而是在没有执行Clean的情况下立即杀死Script-B.sh!

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

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

问候,

调试器


10458
2018-03-26 16:32


起源



答案:


我能够重现您报告的行为。我的假设是,因为脚本正在运行  非交互式shell(作为脚本的子级) SIGINT,这是一个键盘信号,被忽略。

info bash

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

我发现如果你 trap 和 kill 使用另一个信号,如 SIGUSR1 有用。

来自的其他信息 man bash

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

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

SIGCHLD上的任何陷阱都会针对退出的每个子进行执行。


12
2018-03-26 22:47



来自bash(1)的第一位似乎是一个解释。也, zsh的 似乎工作正常。 - Chris Johnsen
对不起这个迟到的答案。你是对的,并不是所有的信号都可以被儿童捕获,但有些信号。 SIGUSR1对我和SIGTERM都有效,但不是在所有bash版本中,因为我在bash 3.00.16中尝试从父亲发送信号到儿子的脚本时出现了分段错误!其他时候使用相同的版本,它将忽略信号而不捕获它(在儿童级别)。但是较新版本运行良好并正确传播所有信号。非常感谢您的帮助 - Debugger
好。运行scriptA shell脚本并调用scriptB(源代码),如“。scriptB.sh param1 param2 .. paramN”,这样,它将为Sig 2 / INT捕获干净 - Arun Sangal
@ArunSangal:......因为 scriptB 然后,它不是一个孩子,它被视为它的一部分 scriptA。 - Dennis Williamson
SIGUSR1对我不起作用。我所做的是在前台启动一个scriptA,从另一个shell发送kill -SIGUSR1 pidof(scriptA)。什么都没发生。我究竟做错了什么 ? function iAmDone { echo "Trapped Signal" exit 0 } trap iAmDone SIGUSR1 echo "Running... " tail -f /dev/null # Do nothing  从我做的另一个外壳 kill -SIGUSR1  ps aux | grep [t]est_trap | awk '{print $2}' - 2.8a8a_G


答案:


我能够重现您报告的行为。我的假设是,因为脚本正在运行  非交互式shell(作为脚本的子级) SIGINT,这是一个键盘信号,被忽略。

info bash

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

我发现如果你 trap 和 kill 使用另一个信号,如 SIGUSR1 有用。

来自的其他信息 man bash

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

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

SIGCHLD上的任何陷阱都会针对退出的每个子进行执行。


12
2018-03-26 22:47



来自bash(1)的第一位似乎是一个解释。也, zsh的 似乎工作正常。 - Chris Johnsen
对不起这个迟到的答案。你是对的,并不是所有的信号都可以被儿童捕获,但有些信号。 SIGUSR1对我和SIGTERM都有效,但不是在所有bash版本中,因为我在bash 3.00.16中尝试从父亲发送信号到儿子的脚本时出现了分段错误!其他时候使用相同的版本,它将忽略信号而不捕获它(在儿童级别)。但是较新版本运行良好并正确传播所有信号。非常感谢您的帮助 - Debugger
好。运行scriptA shell脚本并调用scriptB(源代码),如“。scriptB.sh param1 param2 .. paramN”,这样,它将为Sig 2 / INT捕获干净 - Arun Sangal
@ArunSangal:......因为 scriptB 然后,它不是一个孩子,它被视为它的一部分 scriptA。 - Dennis Williamson
SIGUSR1对我不起作用。我所做的是在前台启动一个scriptA,从另一个shell发送kill -SIGUSR1 pidof(scriptA)。什么都没发生。我究竟做错了什么 ? function iAmDone { echo "Trapped Signal" exit 0 } trap iAmDone SIGUSR1 echo "Running... " tail -f /dev/null # Do nothing  从我做的另一个外壳 kill -SIGUSR1  ps aux | grep [t]est_trap | awk '{print $2}' - 2.8a8a_G


在脚本A中:Trap函数将如下所示,它将调用scriptA.sh中的trap_mesg()函数。 KILL信号(2 / INTerrupt,5 / TERMinate-default)。所有,你需要做的是从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
##################################




现在,在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
##################################

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


0
2018-06-18 19:06