重复运行shell命令直到失败?

bra*_*ers 170 bash

我写了一个不可靠的模糊测试.我添加了一些调试代码,但现在我想运行测试直到它失败,所以我可以收集调试输出.

我已经设置了测试,所以我可以使用以下命令运行它:

./runtest
Run Code Online (Sandbox Code Playgroud)

我目前的解决方案是编写一个untilfail脚本:

#!/bin/bash
$@
while [ $? -eq 0 ]; do
    $@
done
Run Code Online (Sandbox Code Playgroud)

然后使用它:

untilfail ./runtest
Run Code Online (Sandbox Code Playgroud)

有更简单的解决方案吗?

nne*_*neo 295

while 接受命令执行,因此您可以使用更简单的命令

while ./runtest; do :; done
Run Code Online (Sandbox Code Playgroud)

这将在./runtest返回非零退出代码时停止循环(这通常表示失败).

为了进一步简化当前的解决方案,您应该将untilfail脚本更改为如下所示:

#!/bin/bash

while "$@"; do :; done
Run Code Online (Sandbox Code Playgroud)

然后你可以用你已经使用的任何命令调用它:

untilfail ./runTest --and val1,val2 -o option1 "argument two"
Run Code Online (Sandbox Code Playgroud)

  • 最好指出`[`是一个命令.对于新用户来说,这是一个常见的误解,```是`if`和`while`语法的一部分. (25认同)
  • @GrantJ:实际上非常简单.在循环之前放置`count = 0`,然后在循环中取代`:`(无操作),放置`((count ++))` - 这会使计数器递增. (12认同)
  • 生产力破解:如果你使用的是'say`系统和扬声器,你可以使用`while ./runtest; 做:; 完成&&说测试失败`如果它停止通知 (11认同)
  • 值得注意的是,对于像我这样不懂 shell 的人来说,上面的“do”后面的空格很重要。如果没有它,您将收到语法错误。 (5认同)
  • @Schneems:值得注意的是`say`是特定于macOS的. (4认同)
  • 我如何计算它在失败之前运行了多少次? (2认同)

Pan*_*rat 12

还可以使用watch带有标志的命令-e,该标志运行该命令直到发生错误(然后冻结输出直到按下某个键):

watch -e ./runtest
Run Code Online (Sandbox Code Playgroud)

使用 watch 的唯一缺点是运行之间有至少 0.1 秒的强制延迟:

watch -e ./runtest -n0.1
Run Code Online (Sandbox Code Playgroud)

您还watch可以突出显示运行之间的输出更改 ( -d) 或在命令输出更改时退出 ( -g)。


小智 8

如果您不想将复杂的管道线包装到shell脚本或函数中,那么这可以:

while true; do 
  curl -s "https:..." | grep "HasErrors.:true"
  if [[ "$?" -ne 0 ]]; then 
    break
  fi
  sleep 120
done
Run Code Online (Sandbox Code Playgroud)

在这种情况下,HTTP请求总是返回200,但也返回一些具有属性"HasErrors"的JSON:当出现错误时为true.


Gra*_*ett 5

在 shell 重试逻辑到处重复的系统中遇到类似的问题后,我制作了一个专用工具来解决这个问题,称为“重试”:

retry --until=fail ./runtest
Run Code Online (Sandbox Code Playgroud)

一个更复杂的例子:

retry --until=fail --message="test succeeded" --delay=1 ./runtest
Run Code Online (Sandbox Code Playgroud)

可从https://github.com/minfrin/retry获取工具。