Eseguire ripetutamente un comando shell fino a quando non fallisce?


191

Ho scritto un test fuzzy che fallisce in modo spiacevole. Ho aggiunto un po 'di codice di debug, ma ora voglio eseguire il test fino a quando non riesce in modo da poter raccogliere l'output di debug.

Ho installato il test in modo da poterlo eseguire usando:

./runtest

La mia attuale soluzione è scrivere una untilfailsceneggiatura:

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

Quindi usalo:

untilfail ./runtest

C'è una soluzione più semplice?


11
Nota a margine: abitualmente citare "$ @".
Giordania,

Risposte:


328

while richiede un comando per eseguire, in modo da poter usare il più semplice

while ./runtest; do :; done

Questo interromperà il ciclo quando ./runtestrestituisce un codice di uscita diverso da zero (che di solito è indicativo di errore).

Per semplificare ulteriormente la tua attuale soluzione, tuttavia, dovresti semplicemente modificare il tuo script untilfail in questo modo:

#!/bin/bash

while "$@"; do :; done

E poi puoi chiamarlo con qualunque comando tu stia già usando:

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

25
È bene sottolineare anche che [è un comando. È un malinteso comune con i nuovi utenti che [fa parte ife whilesintassi.
Giordania,

2
Come ho potuto contare su quante volte ha funzionato prima di fallire?
GrantJ

13
@GrantJ: in realtà è davvero semplice. Metti count=0prima del loop, quindi anziché :nel loop (un no-op), put (( count++ ))- questo incrementa il contatore.
nneonneo,

14
Un trucco per la produttività: se utilizzi un sistema saye un altoparlante puoi utilizzare while ./runtest; do :; done && say test failedper ricevere una notifica in caso di interruzione
Schneems,

5
@Schneems: vale la pena notare che sayè specifico per macOS.
nneonneo,

13

Se non vuoi avvolgere una linea di pipe complessa in uno script o una funzione shell, allora funziona:

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

La richiesta HTTP in questo caso restituisce sempre 200 ma restituisce anche alcuni JSON che ha un attributo "HasErrors": true quando si verifica un errore.


1

Avendo avuto un problema simile in un sistema in cui la logica dei tentativi di shell era duplicata ovunque, ho creato uno strumento dedicato per risolvere questo "tentativo":

retry --until=fail ./runtest

Un esempio più complesso:

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

Strumento disponibile da https://github.com/minfrin/retry .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.