在bash中有限次重试一系列命令

5
我希望您能提供一种优雅且简洁的方法,在bash中实现重试循环机制。以下是其工作原理:
retries = 3
while retries:
    cmd1
    cmd2
    cmd3
    if not_error:
        break
    echo "something went wrong, let's wait 60 seconds and retry"
    sleep 60
    retries --
if retries = 0:
    exit "Failed!"

每个命令都有可能失败,我希望停止运行下一个命令并执行重试代码。

当 cmd1 成功而 cmd2 失败时,您想重试从 cmd1 还是 cmd2 开始? - Walter A
在bash中,'retries = 3' 应该写成 'retries=3'。空格会让它变得混乱。 - Bret Weinraub
6个回答

5

多年来,我总结出以下针对此类情况的“核心”循环:

(r=3;while ! some_cmd ; do ((--r))||exit;sleep 60;done)

这样做的好处是逻辑被封装在一个语句中,如果命令成功,则表达式将评估为true,如果经过3次尝试后未成功,则表达式将评估为false。如果你正在使用set -e,或者要替换现有的简单命令以进行多次重试,则这非常有用。
在你的情况下,可以这样翻译:
if ! (r=3; while ! { cmd1 && cmd2 && cm3 ; } ; do
          ((--r)||exit
          echo "something went wrong, let's wait 60 seconds and retry"
          sleep 60;done) ; then
    echo "Failed!"
    exit 1
fi

echo "Passed!"
exit 0

非常有用的地方是需要一个单一的命令来重试。 - DiamondDrake

4

类似这样:

#!/bin/bash

retries=3

for ((i=0; i<retries; i++)); do
    cmd1 && cmd2 && cmd3
    [[ $? -eq 0 ]] && break

    echo "something went wrong, let's wait 60 seconds and retry"
    sleep 60
done

(( retries == i )) && { echo 'Failed!'; exit 1; }
exit 0

3

如果单个命令很长,这可能不是最清晰的方法:

retries=3
while ((retries > 0)); do
    cmd1 &&
    cmd2 &&
    cmd3 && break

    echo "something went wrong, let's wait 60 seconds and retry"
    sleep 60
    ((retries --))
done
if ((retries == 0 )); then
    echo "Failed!"
    exit 1
fi
&& 运算符在左侧命令成功时运行右侧命令。如果三个命令都成功,则 break 退出循环。

1
这是值得外部化和重复使用的行为:
请参见: https://github.com/kadwanev/retry
retry -t 3 pipeline.sh
if [ $? -ne 0 ]; then
  echo "Failed"
  exit 1
fi

这将重试最多3次,如果每次尝试都失败,则返回。

0
你可以尝试这个解决方案:
retries=3
while [ retries gt 0 ]; do 
    if cmd1 && cmd2 && cmd3; then
        echo "Passed!"
        exit 0 
    else
    echo "something went wrong, let's wait 60 seconds and retry"
    sleep 60
    ((retries --))
    fi
done
    echo "Failed!"
    exit 1

0

当使用普通的/bin/sh shell(没有bash可用)时,以下是有效的:

retries=3
while [[ $retries -gt 0 ]]; do 
    if cmd1 && cmd2 && cmd3; then
        echo "Passed!"
        exit 0 
    else
        echo "something went wrong, let's wait 2 seconds and retry"
        sleep 2
        retries=$((retries - 1))
    fi
done
echo "Failed!"
exit 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接