我有一个命令,执行时间不到1分钟,但由于某种原因,有一个非常长的内置超时机制.我想要一些执行以下操作的bash:
success = False
try(my_command)
while(!(success))
wait 1 min
if my command not finished
retry(my_command)
else
success = True
end while
Run Code Online (Sandbox Code Playgroud)
我怎么能在Bash中这样做?
Jon*_*ler 17
看看GNU timeout命令.如果在给定时间内没有完成,则会终止该过程; 你只需绕一个循环来等待timeout成功完成,并在适当的重试之间延迟等.
while timeout -k 70 60 -- my_command; [ $? = 124 ]
do sleep 2 # Pause before retry
done
Run Code Online (Sandbox Code Playgroud)
如果你必须以纯粹的方式进行bash(这不是真的可行 - bash使用许多其他命令),那么你就会陷入信号处理程序和各种问题的痛苦和挫败的世界.
我从以下位置找到了一个脚本:http : //fahdshariff.blogspot.com/2014/02/retrying-commands-in-shell-scripts.html
#!/bin/bash
# Retries a command on failure.
# $1 - the max number of attempts
# $2... - the command to run
retry() {
local -r -i max_attempts="$1"; shift
local -r cmd="$@"
local -i attempt_num=1
until $cmd
do
if ((attempt_num==max_attempts))
then
echo "Attempt $attempt_num failed and there are no more attempts left!"
return 1
else
echo "Attempt $attempt_num failed! Trying again in $attempt_num seconds..."
sleep $((attempt_num++))
fi
done
}
# example usage:
retry 5 ls -ltr foo
Run Code Online (Sandbox Code Playgroud)
retry通过组合和命令,可以在一行中实现该目标timeout- 比提供的伪代码短得多:-)
retry -d 0 timeout 60 sleep 61
Run Code Online (Sandbox Code Playgroud)
解释:
我们链接了许多命令。从右边开始:
sleep模拟长时间运行的命令 - 您需要将其替换为实际命令。timeout运行传递给它的任何内容,如果命令花费的时间超过指定时间(在我们的例子中为 60 秒),则会中止它。您可以通过 控制用于停止进程的信号-s,但默认行为通常就足够了。retry将在失败时重新运行传递给它的命令。我们通过-d 0,因为它的默认行为是在重试之间等待 10 秒,这不是问题的一部分,因此我们禁用它。默认情况下,它将无限期地重试 - 就像 OP 所请求的那样 - 但如果你想将重试次数限制为 3,只需传递-t 3.注意1:您可能需要安装该retry工具,例如通过调用sudo apt-get install retry.
注意2:如果您的某些命令的标志与 的标志冲突retry,请--在前面添加timeout以分隔参数。