【问题标题】:How can I silence the "Terminated" message when my command is killed by timeout?当我的命令因超时而终止时,如何使“终止”消息静音?
【发布时间】:2015-09-13 16:10:26
【问题描述】:

通过引用 bash: silently kill background function processTimeout a command in bash without unnecessary delay,我编写了自己的脚本来设置命令的超时时间,以及使终止消息静音。

但是当我的进程被终止时,我仍然收到“终止”消息。我的代码有什么问题?

#!/bin/bash
silent_kill() {
    kill $1 2>/dev/null
    wait $1 2>/dev/null
}
timeout() {
    limit=$1 #timeout limit
    shift
    command=$* #command to run
    interval=1 #default interval between checks if the process is still alive
    delay=1 #default delay between SIGTERM and SIGKILL
    (
        ((t = limit))
        while ((t > 0)); do
            sleep $interval;
            #kill -0 $$ || exit 0
            ((t -= interval))
        done
        silent_kill $$
        #kill -s SIGTERM $$ && kill -0 $$ || exit 0 
        sleep $delay
        #kill -s SIGKILL $$
    ) &> /dev/null &
    exec $*
}
timeout 1 sleep 10

【问题讨论】:

  • 有什么问题?
  • @SMA 我不想从终端得到“终止”。
  • 我觉得这可能是退后一步并想知道您将其用于什么目的的好时机。 “已终止”消息是有关您启动的命令的有用信息:它恰好是由于信号而不是正常进程完成而结束。您的 cmets 使您看起来对此不感兴趣。如果您不想让命令调用对父 shell 尽可能透明,那么使用 exec 包装器毫无意义;您最好将该命令作为后台任务启动并从前台脚本中监视它。
  • (除非你需要终端 I/O,但在交互过程中需要超时中断似乎很奇怪。)

标签: bash shell


【解决方案1】:

您的代码没有任何问题,“已终止”消息不是来自您的脚本,而是来自调用 shell(您启动脚本的那个) 来自)。

您可以通过禁用作业控制来停用:

$ set +m
$ bash <your timeout script>

【讨论】:

  • 我可以在脚本中临时设置,而不是在交互式 bash 中设置吗?
  • 恐怕你不能:脚本不知道交互式shell,也没有能力改变设置。它只能反过来工作:脚本可以从 shell 继承环境和设置。
  • 可能我错过了什么。我摆脱了 Termianted 只是添加` &> /dev/null`
  • @PabloBianchi 您的调用案例可能比此处的 OP 更简单。注意他确实&amp;&gt; /dev/null
  • @JB。同样在我的情况下,调用 shell 的不是临时函数,而是 coreutils homonym command timeout: timeout duration command ... &amp;&gt; /dev/null
【解决方案2】:

也许 bash 已经发展了 4 年。我知道你可以避免 通过 disowning 子进程获取Terminated。你不能再控制它了。例如:

$ sleep 100 &
[1] 15436
$ disown -r
$ kill -9 15436

help disown:

否认 [-h] [-ar] [jobspec ...]
从当前 shell 中删除作业。
从活动作业表中删除每个 JOBSPEC 参数。没有 任何 JOBSPEC,shell 使用其当前作业的概念。

  • -a 如果未提供 JOBSPEC,则删除所有作业
  • -h 标记每个 JOBSPEC,以便在 shell 收到 SIGHUP 时不会向作业发送 SIGHUP
  • -r 只删除正在运行的作业

【讨论】:

  • 在我的例子中,要被杀死的进程是一个exec,而不是一个后台进程,它不适用于这种情况。
【解决方案3】:

在内部,shell 维护了一个它派生的孩子的列表,并等待()s 让他们中的任何一个退出或被杀死。当收集到孩子的退出状态时,shell 会打印一条消息。这在 shell 用语中称为 监控

您似乎想关闭监控。使用m 选项管理监控;要打开它,请使用set -m(启动时的默认值)。要关闭它,set +m

请注意,关闭监控也会禁用异步作业的消息,例如没有更多类似的消息

$ sleep 5 &
[1] 59468
$
[1]  + done       sleep 5
$

【讨论】:

    猜你喜欢
    • 2014-08-29
    • 1970-01-01
    • 2012-10-24
    • 2018-03-03
    • 2018-10-20
    • 2018-03-26
    • 2019-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多