使用 sleep 和 wait -n 在 bash 中实现简单超时,是否存在竞争条件?
Using sleep and wait -n to implement simple timeout in bash, race condition or not?
如果我在 bash 脚本中这样做:
sleep 10 &
sleep_pid=$!
some_command &
wait -n
cmd_pid=$!
if kill -0 $sleep_pid 2> /dev/null; then
# all ok
kill $sleep_pid
else
# some_command hung
...code to log diagnostics and then kill -9 $cmd_pid...
fi
其中 some_command 应该很快但可能会由于罕见的错误而挂起。
那么是否存在 some_command 可以在 "wait -n" 开始之前完成并清理的风险,所以只有等待睡眠?还是一个命令后的 '&' 保证 shell 在处理下一行输入之前不会对其调用 waitpid()?
它在交互式 shell 中工作。如果你这样做:
sleep 10 &
sleep 0 &
wait -n
然后 "wait -n" returns 马上,即使您在 运行 之前等待几秒钟。但我不确定非交互式 shells 是否可以信任它?
编辑: 澄清诊断需求 + 一些语法。
我相信你可以使用超时命令来做到这一点。
http://man7.org/linux/man-pages/man1/timeout.1.html
timeout 10s command_to_run
可以查看timeout命令的退出状态,了解是否超时。
timeout 2s sleep 10
if [[ $? -gt 0 ]]; then
echo "it timed out"
else
echo "It was successful"
fi
通过使用 $!
变量,我们避免依赖交互式作业控制功能。试试这个:
...long executing command... &
pid_long=$!
sleep 3 &
pid_sleep=$!
wait -n
kill -KILL $pid_long
这里的问题是PID回收。不过不太可能在 3 秒内发生。
如果命令早于睡眠结束(并且其 PID 尚未回收到新进程)kill
会产生错误消息;我们可以将其通过管道传输到 /dev/null
.
我们可能还应该 kill
睡眠,以防 它 是一个挥之不去的人。
正如@CharlesDuffy 在评论中指出的那样,答案是否定的,不存在种族(前提是 运行 在 non-interactive shell 中)。
也没有必要(在 non-interactive shells 中)确保在命令之后直接等待,因为 non-interactive shells 不需要自动收割 children.
但我想应该将其包装在 sub-shell 中,这样 "wait -n" 就不会 return 由于之前启动的一些不相关的后台作业而提前 return。
如果我在 bash 脚本中这样做:
sleep 10 &
sleep_pid=$!
some_command &
wait -n
cmd_pid=$!
if kill -0 $sleep_pid 2> /dev/null; then
# all ok
kill $sleep_pid
else
# some_command hung
...code to log diagnostics and then kill -9 $cmd_pid...
fi
其中 some_command 应该很快但可能会由于罕见的错误而挂起。
那么是否存在 some_command 可以在 "wait -n" 开始之前完成并清理的风险,所以只有等待睡眠?还是一个命令后的 '&' 保证 shell 在处理下一行输入之前不会对其调用 waitpid()?
它在交互式 shell 中工作。如果你这样做:
sleep 10 &
sleep 0 &
wait -n
然后 "wait -n" returns 马上,即使您在 运行 之前等待几秒钟。但我不确定非交互式 shells 是否可以信任它?
编辑: 澄清诊断需求 + 一些语法。
我相信你可以使用超时命令来做到这一点。
http://man7.org/linux/man-pages/man1/timeout.1.html
timeout 10s command_to_run
可以查看timeout命令的退出状态,了解是否超时。
timeout 2s sleep 10
if [[ $? -gt 0 ]]; then
echo "it timed out"
else
echo "It was successful"
fi
通过使用 $!
变量,我们避免依赖交互式作业控制功能。试试这个:
...long executing command... &
pid_long=$!
sleep 3 &
pid_sleep=$!
wait -n
kill -KILL $pid_long
这里的问题是PID回收。不过不太可能在 3 秒内发生。
如果命令早于睡眠结束(并且其 PID 尚未回收到新进程)kill
会产生错误消息;我们可以将其通过管道传输到 /dev/null
.
我们可能还应该 kill
睡眠,以防 它 是一个挥之不去的人。
正如@CharlesDuffy 在评论中指出的那样,答案是否定的,不存在种族(前提是 运行 在 non-interactive shell 中)。
也没有必要(在 non-interactive shells 中)确保在命令之后直接等待,因为 non-interactive shells 不需要自动收割 children.
但我想应该将其包装在 sub-shell 中,这样 "wait -n" 就不会 return 由于之前启动的一些不相关的后台作业而提前 return。