Неодноразово виконуйте команду оболонки, поки вона не виходить з ладу?


190

Я написав нечіткий тест, який виходить з ладу ненадійно. Я додав код налагодження, але тепер я хочу запустити тест, поки він не вийде, щоб я міг зібрати вихід налагодження.

Я налаштував тест, щоб я міг його запустити, використовуючи:

./runtest

Моє поточне рішення - написати untilfailсценарій:

#!/bin/bash
$@
while [ $? -eq 0 ]; do
    $@
done

Потім використовуйте його:

untilfail ./runtest

Чи є більш просте рішення?


11
Бічна примітка: звично цитувати "$ @".
Йорданм

Відповіді:


326

while приймає команду для виконання, так що ви можете використовувати більш просту

while ./runtest; do :; done

Це зупинить цикл, коли ./runtestповерне ненульовий код виходу (що зазвичай вказує на збій).

Для подальшого спрощення вашого поточного рішення вам слід просто змінити сценарій untilfail, щоб він виглядав так:

#!/bin/bash

while "$@"; do :; done

І тоді ви можете викликати його будь-якою командою, яку ви вже використовуєте:

untilfail ./runTest --and val1,val2 -o option1 "argument two"

25
Добре також зазначити, що [це команда. Це поширена помилка з новими користувачами, що [є частиною ifі whileсинтаксисом.
Йорданм

2
Як я міг підрахувати, скільки разів він пробіг, перш ніж не вдався?
GrantJ

13
@GrantJ: насправді це дуже просто. Помістіть count=0перед циклом, потім замість :петлі (без опції) поставте (( count++ ))- це збільшує лічильник.
nneonneo

14
Злом продуктивності: Якщо ви користуєтесь системою sayі динаміком, ви можете while ./runtest; do :; done && say test failedотримувати сповіщення, якщо вона коли-небудь зупиняється
Schneems

5
@Schneems: варто зазначити, що sayце специфічно для macOS.
nneonneo

13

Якщо ви не хочете загортати складну трубопровід у сценарій або функцію оболонки, це працює:

while true; do 
  curl -s "https:..." | grep "HasErrors.:true"
  if [[ "$?" -ne 0 ]]; then 
    break
  fi
  sleep 120
done

HTTP-запит у цьому випадку завжди повертає 200, але також повертає деякий JSON, який має атрибут "HasErrors": вірно, коли є помилка.


1

Маючи подібну проблему в системі, де логіка повторної оболонки повторювалася скрізь, я створив спеціальний інструмент для вирішення цього питання під назвою "повторний":

retry --until=fail ./runtest

Більш складний приклад:

retry --until=fail --message="test succeeded" --delay=1 ./runtest

Інструмент доступний на https://github.com/minfrin/retry .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.