如果某个命令挂起,我使用“看门狗”功能来执行故障安全唤醒。这是通过运行一个休眠 30 秒然后执行唤醒的后台任务来实现的。如果父命令在超时期限之前成功,脚本将终止看门狗。
当管道函数(例如sed
格式化其输出)时,即使kill
在后台任务上调用之后,它也会在睡眠期间挂起。是什么赋予了?
这是一个 MCVE:
#! /bin/bash
function indent () { "$@" 2>&1 | sed 's/^/ /'; }
function sleeper () { sleep 1 && echo "Sleep complete."; }
function child () {
sleeper &
# ... do something that might hang here ...
local spid=$! echo "Invoked sleeper." | grep "sleep"
kill $spid
echo "Done child."
}
indent child
即使睡眠者已经被杀死,该进程也会睡眠一秒钟。
答案1
稍微修改一下,杀死sleep
父 PID 为 的进程$spid
:
#! /bin/bash
function indent () { "$@" | sed 's/^/ /'; }
function sleeper () { sleep 1 && echo "Sleep complete."; }
function child () {
sleeper &
local spid=$!
echo "Invoked sleeper." | grep "sleep"
pkill -P "$spid" sleep
echo "Done child."
}
indent child
我认为问题在于后台作业在运行时sleep
实际上不会收到TERM
您发送的信号,直到sleep
终止为止。上面的pkill
命令将向进程发出信号sleep
,而不是向后台作业本身发出信号。