【问题标题】:Why does my bash script take so long to respond to kill when it runs in the background?为什么我的 bash 脚本在后台运行时响应 kill 需要这么长时间?
【发布时间】:2013-12-11 07:46:59
【问题描述】:

(问题已修改,现在我对实际情况有了更多了解)

我有一个在后台运行的脚本,定期做一些工作,然后休眠 30 秒:

echo "background script PID: $$"
trap 'echo "Exiting..."' INT EXIT
while true; do
    # check for stuff to do, do it
    sleep 30
done &

如果我尝试通过killkill INT 终止此脚本,则响应信号需要30 秒。

我会在下面回答这个问题,因为我在网上找到了一个很好的解释。

我原来的、令人尴尬的未经研究的问题

这个问题是针对包含以下陷阱的 bash 脚本:

trap 'echo "Exiting...">&2; kill $childPID 2>/dev/null; exit 0' \
SIGALRM SIGHUP SIGINT SIGKILL SIGPIPE SIGPROF SIGTERM \
SIGUSR1 SIGUSR2 SIGVTALRM SIGSTKFLT

如果我在前台运行脚本,然后点击 CTRL-C,立即获取信号并退出 (不到一秒)。

如果我在后台运行相同的脚本 (&),然后通过 killkill -INT,需要30秒才能收到信号。

为什么会这样,我该如何解决?

【问题讨论】:

  • 你能展示一下脚本吗?
  • 好的,我现在可以看到还涉及一些其他因素,因为我没有通过一个简单的示例得到相同的行为。我将花一些时间将其缩小到重现该行为的最小示例,并用更多细节更新我的问题。

标签: bash signals kill bash-trap


【解决方案1】:

http://mywiki.wooledge.org/SignalTrap 中所述--

“当 bash 在前台执行外部命令时,它不会处理接收到的任何信号,直到前台进程终止” - 由于sleep 是一个外部命令,bash 甚至在 sleep 完成之前都看不到信号。

该页面很好地概述了 bash 中的信号处理以及解决此问题的方法。简而言之,处理这种情况的一种正确方法是将信号发送到进程 group 而不仅仅是父进程:

kill -INT -123   # will kill the process group with the ID 123

前往参考页面以获得完整的解释(我在这里再复制它没有任何意义)。

【讨论】:

    【解决方案2】:

    可能的原因:进程休眠时发出的信号直到进程唤醒时才传递。通过命令行启动时,进程不会休眠,因此会立即传递信号。

    【讨论】:

    • Jens,你打败了我,但无论如何我都会在下面添加我的答案,因为它有更多细节;-)
    【解决方案3】:

    @RashaMatt,我无法让 read 命令像 Greg 的 wiki 上所宣传的那样工作。向脚本发送信号根本不会中断读取。我需要这样做:

    #!/bin/bash
    bail() {
            echo "exiting"
            kill $readpid
            rm -rf $TMPDIR
            exit 0
    }
    
    sig2() {
      echo "doing stuff"
    }
    
    echo Shell $$ started.
    trap sig2 SIGUSR2
    trap bail SIGUSR1 SIGHUP SIGINT SIGQUIT SIGTERM
    trap -p
    
    TMPDIR=$(mktemp -p /tmp -d .daemonXXXXXXX)
    chmod 700 $TMPDIR
    mkfifo $TMPDIR/fifo
    chmod 400 $TMPDIR/fifo
    
    while : ; do
            read < $TMPDIR/fifo & readpid=$!
            wait $readpid
    done
    

    ...向Shell $$ started 行中显示的shell pid 发送所需的信号,并观察兴奋。

    waitsleep 更简单,没错,但有些操作系统没有 sleep infinity,我想看看 Greg 的 read 示例如何工作(它没有)。

    【讨论】:

      猜你喜欢
      • 2017-09-22
      • 2019-07-02
      • 1970-01-01
      • 2020-02-15
      • 1970-01-01
      • 2021-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多