【问题标题】:How can you run a command in bash over and over until success?如何在 bash 中一遍又一遍地运行命令直到成功?
【发布时间】:2011-07-13 13:21:47
【问题描述】:

我有一个脚本,想向用户询问一些信息,但在用户填写此信息之前,该脚本无法继续执行。以下是我尝试将命令放入循环以实现此目的,但由于某种原因它不起作用:

echo "Please change password"
while passwd
do
    echo "Try again"
done

我尝试了许多 while 循环的变体:

while `passwd`
while [[ "`passwd`" -gt 0 ]]
while [ `passwd` -ne 0 ]]
# ... And much more

但我似乎无法让它工作。

【问题讨论】:

    标签: bash command while-loop


    【解决方案1】:
    until passwd
    do
      echo "Try again"
    done
    

    while ! passwd
    do
      echo "Try again"
    done
    

    【讨论】:

    • oneliner:until passwd; do echo "Try again"; done
    • Ctrl-C 难出这个。
    • 很容易按 Ctr-C 退出:until passwd; do echo "Try again"; sleep 2; done - 你所要做的就是在 echo 完成它的工作之后(在给定的两秒钟内)按 Ctr-C。跨度>
    • Ctrl-Z 后跟 kill %1 在 Ctrl-C 不起作用时在这里工作
    • @azmeuk: 试试until passwd || (( count++ >= 5 )); do echo "foo"; done 之类的东西(仅限 bash,如果存在该变量,请确保将 count 设置为 0)如果您需要它用于普通 sh,请增加正文中的计数器并使用 [ ]
    【解决方案2】:

    你需要改为测试$?,也就是上一条命令的退出状态。 passwd 如果一切正常,则以 0 退出,如果密码更改失败(密码错误、密码不匹配等...)则非零退出

    passwd
    while [ $? -ne 0 ]; do
        passwd
    done
    

    使用您的反引号版本,您正在比较 passwd 的输出,这可能是 Enter passwordconfirm password 之类的东西。

    【讨论】:

    • 我喜欢这个,因为它很清楚如何适应相反的情况。例如运行一个带有非确定性错误的程序,直到它失败
    • 当成功由非零退出代码指示时,这就是您所需要的。
    • 如果您不想保留两个版本的冗长而复杂的命令,我认为可以通过将第一个 passwd 更改为 /bin/false 来稍微改进一下。
    • 应该是接受的答案恕我直言。这应该适用于大多数 shell(在 bash、mksh 和 ash 中测试)并且很容易适应这种情况。
    • shellcheck 输出失败:直接使用例如检查退出代码'if mycmd;',而不是间接使用 $?。 [SC2181]
    【解决方案3】:

    详细说明@Marc B 的回答,

    $ passwd
    $ while [ $? -ne 0 ]; do !!; done
    

    是做同样事情的好方法,不是特定于命令的。

    【讨论】:

    • 不幸的是对我不起作用(我得到'!!'命令未找到)。它应该如何工作?
    • 运行上一条命令是一个 bash 技巧。例如,如果您忘记在命令前写sudo,您可以简单地使用sudo !! 以root 权限运行上一个命令。
    • 跑步之间如何睡觉?
    • ^^ while [ $? -ne 0 ]; do !!; sleep 1; done
    【解决方案4】:

    如果有人希望有重试限制:

    max_retry=5
    counter=0
    until $command
    do
       sleep 1
       [[ counter -eq $max_retry ]] && echo "Failed!" && exit 1
       echo "Trying again. Try #$counter"
       ((counter++))
    done
    

    【讨论】:

    • $command 不是一个很好的占位符——请参阅BashFAQ #50,了解为什么使用字符串存储命令天生就不可靠。
    【解决方案5】:

    您可以使用无限循环来实现此目的:

    while true
    do
      read -p "Enter password" passwd
      case "$passwd" in
        <some good condition> ) break;;
      esac
    done
    

    【讨论】:

    • 这是唯一不需要将我的多行命令放入函数的答案。我在验证命令之后做了&amp;&amp; break,而不是选择案例。
    【解决方案6】:
    while [ -n $(passwd) ]; do
            echo "Try again";
    done;
    

    【讨论】:

    • 这不是这样做的方法...您否定 psswd 的标准输出,然后对其进行一元测试。 @duckworthd 很好。
    • 此外,因为没有引用,所以当有 is 输出但它不止一个单词,或者是匹配文件的全局表达式时,测试会出现异常当前目录,等等。
    猜你喜欢
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多