Czy wielokrotnie uruchamiać polecenie powłoki, dopóki się nie powiedzie?


190

Napisałem rozmyty test, który zawodzi niewiarygodnie. Dodałem kod do debugowania, ale teraz chcę uruchomić test, dopóki się nie powiedzie, aby móc zebrać dane wyjściowe debugowania.

Skonfigurowałem test, aby móc go uruchomić przy użyciu:

./runtest

Moje obecne rozwiązanie to napisanie untilfailskryptu:

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

Następnie użyj go:

untilfail ./runtest

Czy istnieje prostsze rozwiązanie?


11
Uwaga dodatkowa: zwykle cytuj „$ @”.
jordanm,

Odpowiedzi:


326

while wykonuje polecenie, aby można było korzystać z prostszego

while ./runtest; do :; done

To zatrzyma pętlę, gdy ./runtestzwróci niezerowy kod wyjścia (co zwykle wskazuje na awarię).

Aby dodatkowo uprościć obecne rozwiązanie, wystarczy zmienić skrypt tillfail, aby wyglądał następująco:

#!/bin/bash

while "$@"; do :; done

A potem możesz to wywołać za pomocą dowolnego polecenia, którego już używasz:

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

25
Warto również zaznaczyć, że [jest to polecenie. Jest to błędne przekonanie, że z nowych użytkowników [jest częścią ifi whileskładnia.
jordanm,

2
Jak mogę policzyć, ile razy działało, zanim zawiodło?
GrantJ

13
@GrantJ: to naprawdę bardzo proste. Umieść count=0przed pętlą, a następnie zamiast :w pętli (no-op), wstaw (( count++ ))- to zwiększa licznik.
nneonneo

14
Hack produktywności: jeśli korzystasz z systemu sayi głośnika, możesz while ./runtest; do :; done && say test failedgo powiadomić, jeśli kiedykolwiek przestanie
Schneems

5
@ Schneems: warto zauważyć, że sayjest to specyficzne dla systemu macOS.
nneonneo,

13

Jeśli nie chcesz zawijać złożonej linii potoku w skrypcie lub funkcji powłoki, działa to:

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

Żądanie HTTP w tym przypadku zawsze zwraca 200, ale także zwraca JSON, który ma atrybut „HasErrors”: true, gdy wystąpi błąd.


1

Mając podobny problem w systemie, w którym powielana jest logika ponownej próby powłoki, stworzyłem dedykowane narzędzie do rozwiązania tego problemu, zwane „ponów próbę”:

retry --until=fail ./runtest

Bardziej złożony przykład:

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

Narzędzie dostępne na https://github.com/minfrin/retry .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.