重试 Bash 命令超时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12321469/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 22:38:58  来源:igfitidea点击:

Retry a Bash command with timeout

bashloopstimeout

提问by Philippe Blayo

How to retry a bash command until its status is ok or until a timeout is reached?

如何重试 bash 命令直到其状态正常或达到超时?

My best shot (I'm looking for something simpler):

我最好的镜头(我正在寻找更简单的东西):

NEXT_WAIT_TIME=0
COMMAND_STATUS=1
until [ $COMMAND_STATUS -eq 0 || $NEXT_WAIT_TIME -eq 4 ]; do
  command
  COMMAND_STATUS=$?
  sleep $NEXT_WAIT_TIME
  let NEXT_WAIT_TIME=NEXT_WAIT_TIME+1
done

回答by Grisha Levit

You can simplify things a bit by putting commandright in the test and doing increments a bit differently. Otherwise the script looks fine:

您可以通过command在测试中正确放置并以稍微不同的方式进行增量来简化一些事情。否则脚本看起来不错:

NEXT_WAIT_TIME=0
until [ $NEXT_WAIT_TIME -eq 5 ] || command; do
    sleep $(( NEXT_WAIT_TIME++ ))
done
[ $NEXT_WAIT_TIME -lt 5 ]

回答by nkadwa

Put together some tools.

把一些工具放在一起。

retry: https://github.com/kadwanev/retry

重试:https: //github.com/kadwanev/retry

timeout: http://manpages.courier-mta.org/htmlman1/timeout.1.html

超时:http: //manpages.courier-mta.org/htmlman1/timeout.1.html

Then see the magic

然后看魔术

retry timeout 3 ping google.com

PING google.com (173.194.123.97): 56 data bytes
64 bytes from 173.194.123.97: icmp_seq=0 ttl=55 time=13.982 ms
64 bytes from 173.194.123.97: icmp_seq=1 ttl=55 time=44.857 ms
64 bytes from 173.194.123.97: icmp_seq=2 ttl=55 time=64.187 ms
Before retry #1: sleeping 0.3 seconds
PING google.com (173.194.123.103): 56 data bytes
64 bytes from 173.194.123.103: icmp_seq=0 ttl=55 time=56.549 ms
64 bytes from 173.194.123.103: icmp_seq=1 ttl=55 time=60.220 ms
64 bytes from 173.194.123.103: icmp_seq=2 ttl=55 time=8.872 ms
Before retry #2: sleeping 0.6 seconds
PING google.com (173.194.123.103): 56 data bytes
64 bytes from 173.194.123.103: icmp_seq=0 ttl=55 time=25.819 ms
64 bytes from 173.194.123.103: icmp_seq=1 ttl=55 time=16.382 ms
64 bytes from 173.194.123.103: icmp_seq=2 ttl=55 time=3.224 ms
Before retry #3: sleeping 1.2 seconds
PING google.com (173.194.123.103): 56 data bytes
64 bytes from 173.194.123.103: icmp_seq=0 ttl=55 time=58.438 ms
64 bytes from 173.194.123.103: icmp_seq=1 ttl=55 time=94.828 ms
64 bytes from 173.194.123.103: icmp_seq=2 ttl=55 time=61.075 ms
Before retry #4: sleeping 2.4 seconds
PING google.com (173.194.123.103): 56 data bytes
64 bytes from 173.194.123.103: icmp_seq=0 ttl=55 time=43.361 ms
64 bytes from 173.194.123.103: icmp_seq=1 ttl=55 time=32.171 ms
...

Check exit status for ultimate pass/fail.

检查最终通过/失败的退出状态。

回答by rhinoceros.xn

retry fuction is from:

重试功能来自:

http://fahdshariff.blogspot.com/2014/02/retrying-commands-in-shell-scripts.html

http://fahdshariff.blogspot.com/2014/02/retrying-commands-in-shell-scripts.html

#!/bin/bash

# Retries a command on failure.
#  - the max number of attempts
# ... - the command to run
retry() {
    local -r -i max_attempts=""; 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

if you want to retry an function in your script, you should do like this:

如果你想在你的脚本中重试一个函数,你应该这样做:

# example usage:
foo()
{
   #whatever you want do.
}

declare -fxr foo
retry 3 timeout 60 bash -ce 'foo'

回答by okwap

One line and shortest, and maybe the best approach:

一行最短,也许是最好的方法:

timeout 12h bash -c 'until ssh root@mynewvm; do sleep 10; done'

Credited by http://jeromebelleman.gitlab.io/posts/devops/until/

归功于http://jeromebelleman.gitlab.io/posts/devops/until/

回答by MatrixManAtYrService

I made some tweaks to thisanswer which let you switch on whether the timeout was reached, or whether the command succeed. Also, in this version there is a retry every second:

我对这个答案做了一些调整,让你可以切换是否达到超时,或者命令是否成功。此外,在此版本中,每秒重试一次:

ELAPSED=0
started=$(mktemp)
echo "False" > $started
until the_command_here && echo "True" > $started || [ $ELAPSED -eq 30 ]
do
   sleep 1
   (( ELAPSED++ ))
done

if [[ $(cat $started) == "True" ]]                                                                                                                                                                                                                            
then                                                                                                                    
    echo "the command completed after $ELAPSED seconds"                                                                                              
else                                                                                                                    
    echo "timed out after $ELAPSED seconds"                                                                               
    exit 111                                                                                                            
fi