我有一个非常简单的脚本来捕捉信号:
#!/bin/bash
unlink SigTermRecieved
unlink SigIntRecieved
#trap " touch SigTermRecieved ; exit " SIGTERM
trap " touch SigIntRecieved ; exit " SIGINT
echo "pid is $"
while true
do
sleep 60m
done
exit行为
这两个陷阱行注释: SIGTERM发送:终止程序。?从另一个终端窗口发送的SIGINT将被忽略!CTRL C终止程序。
与SIGTERM陷阱未评论:?SIGTERM发送:程序不终止,SIGTERM陷阱未执行。?从另一个终端窗口发送的SIGINT将被忽略!CTRL C终止程序。
与SIGINT陷阱未注释: SIGTERM发送:终止程序。?来自另一个终端窗口的SIGINT被忽略!CTRL执行陷阱代码并终止程序。
之前的行为?是意料之外的还是错误的。我不太关心SIGINT的行为。我试过了看看有没有陷阱能起作用。
所以,我去掉了打盹的功能,只是:
sleep 60m &
wait $!现在,kill -TERM -pid杀死两个进程并执行SIGTERM的陷阱。
在我的应用程序中,我等待SIGTERM从系统关闭,以便我可以清理一些细节。我不知道系统关闭是使用pid还是-pid,两者都适用于我,系统最终会杀死所有进程。在我测试的时候,几个摇摇欲坠的睡眠过程没什么大不了的。
fifo的解决方案很复杂,我不明白。
谢谢你的帮助。
发布于 2020-01-15 00:36:45
在两个陷阱行的注释:
SIGTERM发送:终止程序。
由于bash没有为SIGTERM设置任何处理程序,该信号将彻底杀死它,从而导致启动它的shell返回提示符。但是,sleep命令(它是一个外部程序,在单独的子进程中运行)将继续运行(pgrep -a sleep用于验证)。
?从另一个终端窗口发送的
SIGINT将被忽略!
当等待子进程(在本例中为sleep )时,bash为SIGINT设置一个信号处理程序,如果没有为其设置陷阱,则将忽略该信号,除非它等待的子进程由于相同的信号而终止。bash能够从儿童的退出状态中收集它是否被信号杀死,以及它是哪个信号。
这就是所谓的“等待和合作退出”(WCE),只适用于SIGINT和SIGQUIT信号。
其他shell可能不会这样做,可能只是推迟对SIGINT信号的操作,直到他们等待的子节点终止为止。比较bash和dash的示例:
$ ( (sleep .2; pkill -INT -P $)&); dash -c 'while :; do /bin/sleep 3; done'
$ ( (sleep .2; pkill -INT -P $)&); bash -c 'while :; do /bin/sleep 3; done'
^C
CTRL C终止程序。
Ctrl-C将导致内核从前台进程组(job)向所有进程发送SIGINT信号,在本例中包括脚本及其sleep子进程。您可以使用kill命令(与process相同)使用进程组领导的否定pid命令,或者使用带有作业id的kill shell内部结构来模拟这一点:
bash -c 'sleep 3600; echo DONE' &
[1] 12381
kill -INT -12381 # or kill -INT %1只有当脚本真正是进程组领导人时,才能使用脚本的否定pid。如果脚本是从子subshell或另一个脚本调用的,或者作为管道的一部分,则情况可能不是这样。
SIGTERM陷阱未注释:?SIGTERM已发送:程序不终止,SIGTERM陷阱未执行。
是的,陷阱将被执行。但是只有在sleep命令终止之后。如果您不想等待60分钟来确认它,请使用sleep 1而不是sleep 60m ;-)
在链接的答案中也解释了这一点,这是一个标准-要求行为。
如果
SIGINT陷阱未注释:?来自另一个终端窗口的SIGINT将被忽略!
也是。
发布于 2020-01-16 16:40:45
我找到了一个简单的解决方案。
function snooze {
sleep $1
}
while true
do
snooze 60m &
wait $!
done这将执行陷阱,然后在接收到SIGTERM后立即终止。
谢谢你的帮助。
https://unix.stackexchange.com/questions/562109
复制相似问题