【问题标题】:Interrupt sleep in bash with a signal trap使用信号陷阱中断 bash 中的睡眠
【发布时间】:2017-12-12 00:52:56
【问题描述】:

我正在尝试通过sleep 命令在休眠的 bash 脚本中捕获SIGUSR1 信号:

#!/bin/bash

trap 'echo "Caught SIGUSR1"' SIGUSR1

echo "Sleeping.  Pid=$$"
while :
do
    sleep 10
    echo "Sleep over"
done

信号陷阱有效,但在 sleep 10 完成之前不会显示正在回显的消息。
看来 bash 信号处理会等到当前命令完成后再处理信号。

有没有办法让它在收到信号后立即中断正在运行的sleep 命令,就像C 程序中断libc sleep() 函数一样?

【问题讨论】:

    标签: bash shell


    【解决方案1】:
    #!/bin/bash
    
    trap 'echo "Caught SIGUSR1"' SIGUSR1
    
    echo "Sleeping.  Pid=$$"
    while :
    do
       sleep 10 &
       wait $!
       echo "Sleep over"
    done
    

    【讨论】:

    • 将 10 替换为无穷大,例如“sleep infinity &”
    • @iruvar 你的链接值得它的黄金重量。无法从其他进程中断睡眠非常非常违反直觉
    • 根据那个链接,当bash被中断时,sleep 10不会被自动杀死,应该将其添加到陷阱中?
    【解决方案2】:

    关于sleep 之后的wait 的一点,因为我刚刚在我的脚本中犯了这个错误:

    如果在你的脚本中,你已经在后台启动了其他进程,你应该使用 wait $! 而不是wait

    例如,下一个 sn-p 代码中的 wait等待 process_1sleep 10 的终止:

    process_1 &
      ...
    sleep 10 &
    wait  
    

    如果您使用wait 而不是wait $!,您的脚本将只等待sleep 10,因为$! 表示最后一个后台进程的PID

    【讨论】:

    • 非常感谢!我按照您的建议更改了答案。
    【解决方案3】:

    备注

    sleep infinity &
    wait
    

    将睡眠置于后台,并通过信号停止等待。这会在每个信号上留下无限的睡眠!

    将睡眠和等待替换为

    read
    

    你会没事的。

    【讨论】:

    • 我认为它不会让后台进程挂起,至少在 MacOS 10.12 上不会。
    • read 不会永远等待。用户按下回车 -> 立即返回。标准输入连接到/dev/null -> 立即返回。
    • read 把戏很有趣,谢谢。如果您想确保永远不会阅读您可能使用的任何内容:read -u 2 in bash,它指示 read 从文件描述号 2(即 stderr 显然永远不会输入)获取其输入。
    猜你喜欢
    • 2016-12-18
    • 1970-01-01
    • 2011-03-21
    • 2018-01-11
    • 1970-01-01
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    • 2018-08-31
    相关资源
    最近更新 更多