使用超时重试Bash命令

Phi*_*ayo 41 bash loops timeout

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

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

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
Run Code Online (Sandbox Code Playgroud)

Gri*_*vit 60

您可以通过command在测试中直接进行一些简化,并以不同的方式进行增量.否则脚本看起来很好:

NEXT_WAIT_TIME=0
until command || [ $NEXT_WAIT_TIME -eq 4 ]; do
   sleep $(( NEXT_WAIT_TIME++ ))
done
Run Code Online (Sandbox Code Playgroud)

  • 很好的解决方案,唯一的问题是在最后一个"命令"失败后,你仍然需要睡4秒钟.不确定是否可以避免这种情况并保持代码紧凑. (6认同)
  • 至少在bash版本4.1.5中你需要将睡眠行改为睡眠$((NEXT_WAIT_TIME ++)) (4认同)
  • @大卫真的吗?如果左侧返回真值,`||` 运算符会评估右侧吗?(我不太了解 bash,我只知道在 javascript 中它不会。) (2认同)

okw*_*wap 26

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

timeout 12h bash -c 'until ssh root@mynewvm; do sleep 10; done'
Run Code Online (Sandbox Code Playgroud)

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

  • 我认为对于大多数目的来说,这是最好的答案。如果您需要更多笨拙的代码,您可以使用函数。然而,它使您想要实现的主要目标足够短,以便于理解。 (3认同)

nka*_*dwa 11

把一些工具放在一起.

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

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

然后看看魔术

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
...
Run Code Online (Sandbox Code Playgroud)

检查退出状态以确定最终通过/未通过.


rhi*_*.xn 10

重试功能来自:

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)

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

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

declare -fxr foo
retry 3 timeout 60 bash -ce 'foo'
Run Code Online (Sandbox Code Playgroud)