首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SIGTERM击打陷阱失败

SIGTERM击打陷阱失败
EN

Unix & Linux用户
提问于 2020-01-14 20:11:31
回答 2查看 4.1K关注 0票数 0

我有一个非常简单的脚本来捕捉信号:

代码语言:javascript
复制
#!/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的行为。我试过了看看有没有陷阱能起作用。

所以,我去掉了打盹的功能,只是:

代码语言:javascript
复制
sleep 60m &
wait $!

现在,kill -TERM -pid杀死两个进程并执行SIGTERM的陷阱。

在我的应用程序中,我等待SIGTERM从系统关闭,以便我可以清理一些细节。我不知道系统关闭是使用pid还是-pid,两者都适用于我,系统最终会杀死所有进程。在我测试的时候,几个摇摇欲坠的睡眠过程没什么大不了的。

fifo的解决方案很复杂,我不明白。

谢谢你的帮助。

EN

回答 2

Unix & Linux用户

发布于 2020-01-15 00:36:45

在两个陷阱行的注释:SIGTERM发送:终止程序。

由于bash没有为SIGTERM设置任何处理程序,该信号将彻底杀死它,从而导致启动它的shell返回提示符。但是,sleep命令(它是一个外部程序,在单独的子进程中运行)将继续运行(pgrep -a sleep用于验证)。

?从另一个终端窗口发送的SIGINT将被忽略!

当等待子进程(在本例中为sleep )时,bashSIGINT设置一个信号处理程序,如果没有为其设置陷阱,则将忽略该信号,除非它等待的子进程由于相同的信号而终止。bash能够从儿童的退出状态中收集它是否被信号杀死,以及它是哪个信号。

这就是所谓的“等待和合作退出”(WCE),只适用于SIGINTSIGQUIT信号。

其他shell可能不会这样做,可能只是推迟对SIGINT信号的操作,直到他们等待的子节点终止为止。比较bashdash的示例:

代码语言:javascript
复制
$ ( (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内部结构来模拟这一点:

代码语言:javascript
复制
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将被忽略!

也是。

票数 3
EN

Unix & Linux用户

发布于 2020-01-16 16:40:45

我找到了一个简单的解决方案。

代码语言:javascript
复制
function snooze {
    sleep $1
}

while true
do
    snooze 60m &
    wait $!
done

这将执行陷阱,然后在接收到SIGTERM后立即终止。

谢谢你的帮助。

票数 1
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/562109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档