【问题标题】:How do I stop a signal from killing my Bash script?如何阻止信号杀死我的 Bash 脚本?
【发布时间】:2014-09-10 23:58:27
【问题描述】:

我希望无限循环继续运行,并且只是暂时被终止信号中断。我试过 SIGINT、SIGUSR1、SIGUSR2。所有这些似乎都停止了循环。我什至尝试过 SIGINFO,但 Linux 不支持。

#!/bin/bash
echo $$ > /tmp/pid  # Save the pid

function do_something {
    echo "I am doing stuff" #let's do this now, and go back to doing the thing that is to be done over and over again.
#exit
}


while :
do
    echo "This should be done over and over again, but always wait for someething else to be done in between"

    trap do_something SIGINT
    while `true`
    do
            sleep 1 #so we're waiting for that other thing.
    done

done

在从另一个脚本获得 INT 信号后,我的代码运行该函数一次,但之后再也不运行了。它停止了。

编辑:虽然我不小心把 en exit 放在了函数的末尾,但在 Stack Overflow 上,我并没有在我使用的实际代码中。无论哪种方式,它都没有任何区别。解决方案是 Tiago 描述的 SIGTERM。

【问题讨论】:

    标签: bash signals kill


    【解决方案1】:

    相信你在找SIGTERM

    例子:

    #! /bin/bash
    
    trap -- '' SIGINT SIGTERM
    while true; do
        date +%F_%T
        sleep 1
    done
    

    运行此示例 cTRL+C 不会杀死它,也不会 kill <pid> 您可以使用 kill -9 <pid> 杀死它。

    如果您不希望CTRL+Z 中断使用:trap -- '' SIGINT SIGTERM SIGTSTP

    【讨论】:

    • 你在他的 do_something 函数中漏掉了一个问题——我也几乎漏掉了:脚本终止的问题是最后有一个出口。因此,即使有正确的信号,问题仍然存在。似乎那些提高您的答案的人也错过了这一点。见证“我的代码在从另一个脚本获得 INT 信号后运行该函数一次,但之后再也没有运行过。”
    • @Bushmills 你说得对,我没有看到出口,但我给了 OP 一个例子来说明如何不被打断。我认为这就是投票的原因。
    • @Tiago,关于如何让它返回无限循环的任何想法,即使在每次运行 do_something 之后?
    • 做个免疫陷阱SIGQUIT SIGHUP SIGINT SIGTERM SIGUSR1 SIGUSR2也想想SIGPIPE
    • --trap -- '' SIGINT SIGTERM 中做了什么?
    【解决方案2】:

    捕获信号,然后在与陷阱关联的函数中对它做出适当的反应,或者通过例如 associate : as 命令在信号发生时执行来忽略它。

    为了捕获信号,bash 知道 trap 命令

    通过仅使用信号名称执行陷阱将陷阱重置为之前的操作。

    因此你想要(我认为这就是你所说的“只是暂时被终止信号打断”):

    • 在脚本开头捕获信号:trap signal custom_action
    • 就在您希望信号允许中断脚本之前,执行:trap signal
    • 在该阶段结束时,再次通过以下方式捕获:signal custom_action

    要指定信号,您还可以使用它们各自的信号编号。使用以下命令打印信号名称列表:

    trap -l 
    

    kill 发送的默认信号是 SIGTERM (15),除非你在 kill 命令之后指定不同的信号

    不要退出你的 do_something 函数。只需让函数返回到代码中信号发生时中断的部分即可。

    如果您愿意,上述“:”命令在您的脚本中还有另一个潜在用途:

    while :
    do
      sleep 1
    done
    

    可以替代“while true” - 顺便说一句,不需要反引号。

    【讨论】:

    • 谢谢。但在我的示例中,它捕获信号,运行 do_something,但随后停止。它永远不会返回到下面的无限循环。我错过了什么?
    • 这不是你错过了什么,而是太多了:我在我的回答中写道“不要退出你的 do_something 函数。只需让函数返回到你的部分信号发生时中断的代码。” - “exit”退出你的脚本
    • 但是如何让它返回到信号发生时中断的代码呢?我没有明确的退出,但也许在 do_something 的末尾隐含地完成了?那我该如何防止它这样做呢?谢谢。
    • 只需移除出口即可。是的,你确实有一个明确的退出。它是用您发布的代码编写的。我不知道 - 似乎没有人看到那个出口,我是不是产生了幻觉?
    • @Bushmills 确实有一个出口,我不小心把它放在那里。对于那个很抱歉。但删除它并没有帮助。
    【解决方案3】:

    您只想忽略退出状态。
    如果您希望脚本继续运行而不退出,而不用担心处理陷阱。

    (my_command) || true
    

    括号在子shell中执行该命令。 true 是为了与 set -e 兼容,如果你使用它的话。它只是简单地覆盖状态以始终报告成功。

    请参阅source

    我发现这个问题很有帮助: How to run a command before a Bash script exits?

    【讨论】:

      猜你喜欢
      • 2017-03-31
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-22
      • 2015-10-05
      • 2017-11-13
      • 2013-05-20
      相关资源
      最近更新 更多