问题描述
如果我使用 kill 发送信号,它似乎要等到当前程序(在本例中为 sleep 1000
)完成运行。当我通过在 shell 中按 Ctrl+C
发送 SIGINT 时,它会立即收到中断。
然而,我想要的是在通过 kill
发送信号后立即接收中断。另外,为什么当我按下 Ctrl+C
时它的行为就像我想要的那样?
#!/usr/bin/env sh
int_after_a_while() {
local pid=$1
sleep 2
echo "Attempting to kill $pid with SIGINT"
# Here I want to kill the process immediately,but it waits until sleep finishes
kill -s INT $pid
}
trap "echo Interrupt received!" INT
int_after_a_while $$ &
sleep 1000
我将不胜感激对此问题的任何帮助。提前致谢!
解决方法
如参考答案 https://unix.stackexchange.com/questions/282525/why-did-my-trap-not-trigger/282631#282631 中所述,shell 通常会在运行陷阱之前等待实用程序完成。一些替代方案是:
- 在后台启动长时间运行的进程,然后使用内置的
wait
等待它。当在这样的等待期间接收到捕获信号时,等待被中断并且捕获捕获。不幸的是,wait
的退出状态不能区分子进程在收到信号时退出和发生陷阱。例如
sleep 1000 &
p=$!
wait "$p"
- 通过
kill -s INT 0
向整个进程组发送信号。效果与用户按下 Ctrl+C 非常相似,但如果您的脚本是从另一个脚本运行的,则效果可能比您想要的更极端。 - 使用支持
set -o trapsasync
的 shell,例如 zsh 或 FreeBSD sh,允许在等待前台作业时运行陷阱。