循环执行 bash 中的多条指令,如果一条指令失败,则从顶部开始

循环执行 bash 中的多条指令,如果一条指令失败,则从顶部开始

我正在寻找一种有效的方法来做到这一点。

我有各种命令需要按顺序执行;如果第一个命令失败,第二个命令就无法运行,依此类推。

我确实循环遍历了它们;但是循环必须遍历每个命令,这不是我需要做的。

例如,如果有 3 个命令:a、b 和 c;a 始终运行,b 仅在 a 成功运行时运行,c 仅在 b 成功运行时才运行,但如果 b 失败一次,则必须从 a 重新开始

LOOP *****************************
until a; do
  echo "a failed, retrying"
  sleep(3)
done
until b; do
  echo "b failed, need to start all over"
  b_failed=1
  break
  START FROM THE BEGIN OF LOOP ***************
done
until c; do
  echo "c failed, need to start all over from a"
  c_failed=1
  break
  START FROM THE BEGIN OF LOOP ***************
done
.... OTHER INSTRUCTIONS
LOOP *****************************

我尝试使用常规循环,但 break 会从子循环退出,而不会从头开始。我想进入这个主循环,执行第一个操作直到它通过,然后执行第二个;如果失败,则从循环顶部开始,而不运行所有其他命令等等。虽然我似乎找不到正确的方法来做到这一点,除非我用大量的 if-else 检查每个命令来膨胀逻辑。

有没有一种简洁的方法可以用几行代码来做到这一点?

编辑:将“until”改为“while”;进行了更正

EDIT2:非常感谢您的解决方案!虽然必须对其进行修改,因为我无法按原样运行它:if 缺少 fi 来终止命令,并且缺少“then”语句。我无法在 if 中运行 do;所以这是对我有用的:

while true; do
    until a; do
        echo "a failed, retrying"
        sleep(3)
    done
    if [ ! b ]; then
        echo "b failed, need to start all over"
        continue
    else
        c
    fi
    if [ ! c ]; then
        echo "c failed, need to start all over from a"
        continue
    else
        break
    fi
done

答案1

一个非常简单的解决方案,正如 Squeezy 部分提到的:

until a && b && c; do
    :
done

&&是逻辑与运算符。它确实会短路,因此只有当左侧表达式为真时,右侧表达式才会被求值。

&&完整表达式(或 s 链)的返回值&&是最后一个求值表达式的结果。因此,如果此处三个命令中的任何一个失败,后面的命令将被忽略,并且将until看到 afalse并进入其主体,不执行任何操作(:只是无操作来填充循环主体),然后a && b && c再次循环回到测试条件。如果所有三个都成功,那么until将看到 atrue并结束。

因此,这对于简单情况来说很好,但如果您想打印这些状态消息,则不太好。使用||(逻辑或)和是可能的{ },但会非常混乱。

如果您想在命令失败时做一些额外的事情,例如回显状态消息,这样做会更好:

while true; do
    until a; do
        echo "a failed, retrying"
        sleep(3)
    done
    if [ ! `b` ]; then
        echo "b failed, need to start all over"
        continue
    fi
    if [ ! `c` ]; then
        echo "c failed, need to start all over from a"
        continue
    fi
    break
done

continue返回到封闭循环的开始处。在返回到封闭循环的开始处后放置一个数字会n提升级别。虽然这里没有必要,因为它们在ifs 内而不是循环内。顺便说一句,break同样会取一个数字并跳出n封闭循环。

如果您希望保持外观不变,该a部分也可以是if [ ! a ];而不是 循环。在这种情况下,until您需要添加。continue

相关内容