如何在bash中运行命令直到成功


237

我有一个脚本,想向用户询问一些信息,直到用户填写此信息,脚本才能继续。以下是我尝试将命令放入循环中以实现此目的的尝试,但由于某些原因它不起作用。

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

但是我似乎无法使其正常工作。

Answers:


403
until passwd
do
  echo "Try again"
done

要么

while ! passwd
do
  echo "Try again"
done

20
很难用Ctrl-C了。
DonGar 2013年

如果您认为需要取消此操作,只需打开一个新的Shell实例(例如,键入“ bash”),然后在想要取消它时,进入另一个终端窗口并杀死新生成的bash处理。
伊桑(Ethan)

50
轻松实现Ctr-C的目的:until passwd; do echo "Try again"; sleep 2; done-您要做的就是在工作完成后(在指定的两秒钟内)按Ctr-C echo
基督教徒

9
@azmeuk:尝试类似的操作until passwd || (( count++ >= 5 )); do echo "foo"; done(仅适用于bash,如果存在可变变量,请确保将count设置为0)。如果您需要纯sh进行计数,请在主体中增加计数器并使用[]
Justin Sane

2
多次访问该页面后,我决定创建一个通用的bash函数来重试命令,这里是:gist.github.com/felipou/6fbec22c4e04d3adfae5
felipou

94

您需要进行测试$?,这是上一个命令的退出状态。passwd如果一切正常,则以0退出;如果passwd更改失败(密码错误,密码不匹配等),则退出非零值。

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

使用反引号的版本,您正在比较passwd的输出,例如 Enter passwordconfirm password等。


2
那不是$?吗?
肖恩·钦

我喜欢这样,因为很明显如何适应相反的情况。例如,运行带有不确定性错误的程序,直到失败为止
Eric

当通过非零退出代码指示成功时,这就是您所需要的。
Gudlaugur Egilsson

2
我认为passwd/bin/false如果您有一些不想保留两个版本的冗长而复杂的命令,则可以通过更改第一个来稍微改善一下。
coladict

应该是恕我直言的答案。这应该适用于大多数shell(在bash,mksh和ash中测试),并且很容易适应这种情况。
linuxandria

73

要详细说明@Marc B的答案,

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

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


11
不幸的是,这对我不起作用(找不到“ !!”命令)。应该如何运作?
约翰内斯·鲁道夫

2
运行前面的命令是一个bash技巧。例如,如果您忘记sudo在命令前面编写代码,则只需执行sudo !!以root特权运行前面的命令即可。
JohnEye 2015年

1
我可以在我的个人资料中创建可以执行此操作的脚本,这样我就可以去吗:$ makelastwork
user230910 '16

2
跑步之间如何睡觉?
卡米尔(Kamil Dziedzic)

6

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

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

2
这是不需要将多行命令放在函数中的唯一答案。我是&& break在执行验证命令后执行的,而不是在选择情况下执行的。
carlin.scott

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

1
until $(command)基本上总是错的。使用until command代替。在$(...)使输出command是本身运行作为命令,并退出状态即二次命令是什么环路决定运行或失败上; 这是唯一的,如果有没有标准输出,当命令替换存在的命令本身的退出状态被认为是。
查尔斯·达菲

$command也不是很好的占位符-请参阅BashFAQ#50,以了解为什么天生就不可靠地使用字符串存储命令。不过,这比以前要好。下注撤回。
Charles Duffy

3
while [ -n $(passwd) ]; do
        echo "Try again";
done;

3
这不是这样做的方法……您要否定psswd的标准输出,然后对其进行一元测试。@duckworthd很好。
雷·福斯 Ray Foss)

而且,因为没有报价,所以当出现这种情况时,测试将表现异常 输出,但它比一个字,或者是一个全局正则表达式匹配的文件在当前目录,等等。
查尔斯·达菲
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.