目前我正在编写这样的 bash 脚本:
foo(){
while true
do
sleep 10
done
}
bar(){
while true
do
sleep 20
done
}
foo &
bar &
wait
(我知道这样的脚本没有意义,它只是关于结构)
现在我想用
trap -- <doSomething> RTMIN+1
添加信号处理.这首先起作用。当脚本收到 rtmin+1 信号时,它会执行 doSomething 但之后它存在(带有 163 退出代码,这是发送的信号的编号)。这不是我想要的行为。我希望在收到信号后,脚本继续等待进程(在这种情况下是两个函数)终止(在这种情况下当然不会发生,但脚本应该等待)。
我尝试添加
; wait
接收信号时应该做的事情,但这无济于事(或者我做错了什么)。有谁知道如何实现所需的行为?
提前致谢并致以最良好的祝愿。
编辑:也许一个更精确的例子有帮助:
clock(){
local prefix=C
local interval=1
while true
do
printf "${prefix} $(date '+%d.%m %H:%M:%S')\n"
sleep $interval
done
}
volume(){
prefix=V
volstat="$(amixer get Master 2>/dev/null)"
echo "$volstat" | grep "\[off\]" >/dev/null && icon="" #alternative: deaf: mute:
vol=$(echo "$volstat" | grep -o "\[[0-9]\+%\]" | sed "s/[^0-9]*//g;1q")
if [ -z "$icon" ] ; then
if [ "$vol" -gt "50" ]; then
icon=""
#elif [ "$vol" -gt "30" ]; then
# icon=""
else
icon=""
fi
fi
printf "${prefix}%s %3s%%\n" "$icon" "$vol"
}
clock &
volume &
trap -- "volume" RTMIN+2
wait
现在
RTMIN+2
信号应该重新运行 volume
功能,但 clock
过程不应中断。 (到目前为止,整个脚本(包括所有子进程)在接收到信号时终止)
最佳答案
当没有操作数调用时,wait
退出 0 ;这意味着调用 shell 已知的所有进程 ID 都已终止,或者 大于 128 的值;这意味着接收到已设置陷阱的信号。所以,循环直到 wait
退出 0
足以让脚本在收到信号后保持事件状态。您还可以在循环内检查其退出状态是否小于 128,但我认为没有必要。
但是,如果您使用 pkill
发送这些信号,在后台启动的作业也将接收它们,因为子进程从其父进程继承进程名称而不是自定义信号处理程序,以及 pkill
向名称匹配的所有进程发出信号。你也需要处理这种情况。
一个最小的工作示例是:
#! /bin/bash -
# ignore RTMIN+1 and RTMIN+2 temporarily
# to prevent pkill from killing jobs
trap '' RTMIN+1 RTMIN+2
# start jobs
sleep 20 && echo slept for 20 seconds &
sleep 30 && echo slept for 30 seconds &
# set traps
trap 'echo received rtmin+1' RTMIN+1
trap 'echo received rtmin+2' RTMIN+2
# wait for jobs to terminate
until wait; do
echo still waiting
done
还值得注意的是,忽略
RTMIN+1
和 RTMIN+2
在开始作业之前可以防止从它们下降的 shell 捕获/重置这些信号。如果这是一个问题,您可以按照 F. Hauri 的建议在工作中设置一个空陷阱;或者你可以完全放弃忽略和使用 pkill
与 -o
选项将信号发送到最旧的匹配进程。引用:
wait
spec. § EXIT STATUS 有关的:
关于linux - Bash 脚本捕获信号但之后等待进程终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61512635/