我想捕捉一个信号(让我们专注于INT
)而不是完成当前正在运行的命令,以便在运行信号处理程序后完成。
我们说我有以下脚本:
#!/bin/bash
READY=0
ctrl_c(){
READY=1
}
trap ctrl_c INT
while true; do
echo first sleep
sleep 1
echo second sleep
sleep 1
if [ $READY -ne 0 ] ; then
echo -e "\n$READY"
echo Exit
exit
fi
done
当我在first sleep
之后点击 Ctrl C 时,我会立即下降到second sleep
,第二个sleep 1
并完成脚本
当我在second sleep
之后点击 Ctrl C 时(正在运行第二个sleep 1
),我立即得到脚本终止。
如何确保此脚本在whole seconds
中运行,即:sleep
未终止?
答案 0 :(得分:1)
您可以通过利用只有前台进程才会收到信号的事实来实现。因此,您可以在后台运行命令,在前台陷阱并wait
直到命令退出。
但此外,由于wait
will also exit on reception of a trapped signal:
当Bash通过内置
wait
等待异步命令时,接收到已设置陷阱的信号将导致wait
内置函数立即返回,退出状态大于128,紧接着执行陷阱。
我们必须在循环中等待,仅在低于(或等于)128 - 的退出状态时中止,假设命令永远不会退出,状态高于128 。如果此假设在您的情况下无效,则此解决方案将无效。
我们可以将所有这些包装在一个函数中,让我们称之为trapwrap
:
trapwrap() {
declare -i pid status=255
# set the trap for the foreground process
trap ctrl_c INT
# run the command in background
"$@" & pid=$!
# wait until bg command finishes, handling interruptions by trapped signals
while (( status > 128 )); do
wait $pid
status=$?
done
# restore the trap
trap - INT
# return the command exit status
return $status
}
(解释:首先我们将pid
和status
声明为整数,因此我们以后不必将它们转义。将SIGINT
的陷阱设置为先前定义的用户函数ctrl_c
,我们在后台运行用户提供的命令,并将PID
存储在pid
中。wait
pid
在无限循环中完成wait
因为SIGINT
也会在被困>128
上中断,在这种情况下,它会以状态wait
退出。我们循环直到<=128
退出trapwrap
,因为这表示退出状态实际上来自刚刚完成的后台进程。最后,我们恢复陷阱并返回命令退出状态。)
然后,我们可以像这样使用#!/bin/bash
READY=0
ctrl_c() {
READY=1
}
while true; do
echo first sleep
trapwrap sleep 1
echo second sleep
trapwrap sleep 1
if [ $READY -ne 0 ] ; then
echo -e "\n$READY"
echo Exit
exit
fi
done
:
first sleep
^C^C^C^Csecond sleep
^C^C
1
Exit
运行时,您会得到预期的结果:
blockingStub = SomeGrpc
.newBlockingStub(channel)
.withDeadlineAfter(5, TimeUnit.SECONDS);