2012-09-07 16 views
26

Come riprovare un comando bash fino a quando il suo stato è ok o fino al raggiungimento di un timeout?Riprovare un comando Bash con timeout

mio colpo migliore (sto cercando qualcosa di più semplice):

NEXT_WAIT_TIME=0 
COMMAND_STATUS=1 
until [ $COMMAND_STATUS -eq 0 || $NEXT_WAIT_TIME -eq 4 ]; do 
    command 
    COMMAND_STATUS=$? 
    sleep $NEXT_WAIT_TIME 
    let NEXT_WAIT_TIME=NEXT_WAIT_TIME+1 
done 
+0

Non vuoi metti il ​​'$?' nel test statement - presumo che sia un errore di battitura e che tu voglia veramente '$ COMMAND_STATUS' lì? –

+0

@Grisha Levit: hai ragione, aggiorno la domanda –

+0

questo modulo ha il vantaggio che $ COMMAND_STATUS è disponibile dopo l'esecuzione. – AnneTheAgile

risposta

37

È possibile semplificare le cose un po 'mettendo command destra nel test e facendo incrementa un po' diverso. In caso contrario, lo script sembra corretto:

NEXT_WAIT_TIME=0 
until command || [ $NEXT_WAIT_TIME -eq 4 ]; do 
    sleep $((NEXT_WAIT_TIME++)) 
done 
+4

Almeno in bash versione 4.1.5 è necessario modificare la linea di sonno su sleep $ ((NEXT_WAIT_TIME ++)) – Nightscape

+0

Grazie, risolto nella risposta. –

+6

Buona soluzione, l'unico problema è che dopo l'ultimo "comando" fallito, dovrai comunque dormire per 4 secondi. Non sono sicuro se ciò possa essere evitato e mantenere il codice così compatto. – David

9

Unire alcuni strumenti.

tentativo: https://github.com/kadwanev/retry

timeout: http://manpages.courier-mta.org/htmlman1/timeout.1.html

Poi vedere la magia

retry timeout 3 ping google.com 

PING google.com (173.194.123.97): 56 data bytes 
64 bytes from 173.194.123.97: icmp_seq=0 ttl=55 time=13.982 ms 
64 bytes from 173.194.123.97: icmp_seq=1 ttl=55 time=44.857 ms 
64 bytes from 173.194.123.97: icmp_seq=2 ttl=55 time=64.187 ms 
Before retry #1: sleeping 0.3 seconds 
PING google.com (173.194.123.103): 56 data bytes 
64 bytes from 173.194.123.103: icmp_seq=0 ttl=55 time=56.549 ms 
64 bytes from 173.194.123.103: icmp_seq=1 ttl=55 time=60.220 ms 
64 bytes from 173.194.123.103: icmp_seq=2 ttl=55 time=8.872 ms 
Before retry #2: sleeping 0.6 seconds 
PING google.com (173.194.123.103): 56 data bytes 
64 bytes from 173.194.123.103: icmp_seq=0 ttl=55 time=25.819 ms 
64 bytes from 173.194.123.103: icmp_seq=1 ttl=55 time=16.382 ms 
64 bytes from 173.194.123.103: icmp_seq=2 ttl=55 time=3.224 ms 
Before retry #3: sleeping 1.2 seconds 
PING google.com (173.194.123.103): 56 data bytes 
64 bytes from 173.194.123.103: icmp_seq=0 ttl=55 time=58.438 ms 
64 bytes from 173.194.123.103: icmp_seq=1 ttl=55 time=94.828 ms 
64 bytes from 173.194.123.103: icmp_seq=2 ttl=55 time=61.075 ms 
Before retry #4: sleeping 2.4 seconds 
PING google.com (173.194.123.103): 56 data bytes 
64 bytes from 173.194.123.103: icmp_seq=0 ttl=55 time=43.361 ms 
64 bytes from 173.194.123.103: icmp_seq=1 ttl=55 time=32.171 ms 
... 

Verifica stato uscita per passaggio finale/fail.

+0

Snap: https://github.com/sky-shiny/retrycli – J0hnG4lt

9

tentativi fuction è da:

http://fahdshariff.blogspot.com/2014/02/retrying-commands-in-shell-scripts.html

#!/bin/bash 

# Retries a command on failure. 
# $1 - the max number of attempts 
# $2... - the command to run 
retry() { 
    local -r -i max_attempts="$1"; shift 
    local -r cmd="[email protected]" 
    local -i attempt_num=1 

    until $cmd 
    do 
     if ((attempt_num == max_attempts)) 
     then 
      echo "Attempt $attempt_num failed and there are no more attempts left!" 
      return 1 
     else 
      echo "Attempt $attempt_num failed! Trying again in $attempt_num seconds..." 
      sleep $((attempt_num++)) 
     fi 
    done 
} 

# example usage: 
retry 5 ls -ltr foo 

se si vuole riprovare una funzione nello script, si dovrebbe fare in questo modo:

# example usage: 
foo() 
{ 
    #whatever you want do. 
} 

declare -fxr foo 
retry 3 timeout 60 bash -ce 'foo'