用信号陷阱中断bash中的睡眠

Joh*_*ris 23 bash shell

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

#!/bin/bash

trap 'echo "Caught SIGUSR1"' SIGUSR1

echo "Sleeping.  Pid=$$"
while :
do
    sleep 10
    echo "Sleep over"
done
Run Code Online (Sandbox Code Playgroud)

信号陷阱有效,但回显的信息sleep 10在完成之前不会显示.
看起来bash信号处理在处理信号之前等待当前命令完成.

有没有办法sleep让它在获得信号后立即中断运行命令,就像C程序中断libc sleep()功能一样?

Han*_*der 31

#!/bin/bash

trap 'echo "Caught SIGUSR1"' SIGUSR1

echo "Sleeping.  Pid=$$"
while :
do
   sleep 10 &
   wait $!
   echo "Sleep over"
done
Run Code Online (Sandbox Code Playgroud)

  • 一些[相关信息](http://mywiki.wooledge.org/SignalTrap#When_is_the_signal_handled.3F) (13认同)
  • @iruvar 你的链接值得它的黄金重量。无法从不同的进程中断睡眠*非常非常违反直觉*。 (3认同)
  • 根据那个链接,当 bash 被中断时,`sleep 10` 不会自动被杀死,应该将它添加到陷阱中吗? (3认同)
  • 将 10 替换为无穷大,例如“sleep infinity &” (2认同)

小智 10

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

您应该在脚本中使用wait $!而不是waitif,而不是在后台启动其他进程

例如,wait下一段代码内部将等待两者的终止,process_1并且sleep 10:

process_1 &
  ...
sleep 10 &
wait  
Run Code Online (Sandbox Code Playgroud)

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


dir*_*irk 6

请注意

sleep infinity &
wait
Run Code Online (Sandbox Code Playgroud)

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

替换睡眠并等待

read
Run Code Online (Sandbox Code Playgroud)

你会没事的。