如何在Bash中重试命令?

ste*_*ejb 7 bash

我有一个命令,执行时间不到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使用许多其他命令),那么你就会陷入信号处理程序和各种问题的痛苦和挫败的世界.


rhi*_*.xn 5

我从以下位置找到了一个脚本: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)


Jea*_*tor 5

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以分隔参数。