我正在编写一个 shell 脚本来在后台运行 ping 命令,同时为 ping 命令设置一个超时值,如果 ping 因超时而结束,我想获取退出代码,我使用如下:
timeout 10s ping -c 5 www.google.com | awk '{print "from local to google |", $0;}' &
exit_status=$?
echo $exit_status
但我发现返回的退出代码是“&”,命令在后台运行,而不是超时。
我怎样才能获得超时退出代码?
答案1
这里存在很多问题。第一的,timeout
将 a 作为参数单一命令。所以当你写的时候
timeout 10s ping -c 5 www.google.com | awk '{print "from local to google |", $0;}'
发生的事情或多或少是这样的:
( timeout 10s ping -c 5 www.google.com ) | awk '{print "from local to google |", $0;}'
即timeout
杀死ping
,而不是整个管道,因此您会得到管道的退出代码(即 的退出代码awk
)。
要获取退出代码,timeout
您需要一个子 shell。但由于timeout
将单个命令作为参数,因此您需要明确地编写:
timeout 10 sh -c 'ping ... | awk ...' sh
或者,您可以只计算管道中最后一个命令的时间(即awk
):
ping ... | timeout 10 awk ...
这对于 应该可以正常工作ping | awk
,但对于其他命令来说可能容易出现竞争条件。如果ping
产生大量输出,您可能还会收到 SIGPIPE,用于杀死侦听器。
回到你的问题,你还想把所有这些放在后台。要获取后台命令的退出代码,您需要wait
:
timeout 10 sh -c 'ping ... | awk ...' sh &
wait $!
echo $?
遗憾的bash
是没有异步wait
,这违背了在后台运行命令的目的。不过,您可以在此之前运行其他命令wait
。