Come verificare se un comando è riuscito?


235

C'è un modo per verificare se c'è un errore nell'esecuzione di un comando?

Esempio :

test1=`sed -i "/:@/c connection.url=jdbc:oracle:thin:@$ip:1521:$dataBase" $search`
valid $test1

function valid () {
  if $test -eq 1; then
    echo "OK"
    else echo "ERROR" 
  fi
}

Ho già provato a farlo, ma sembra che non funzioni. Non lo faccio.


9
Preferisci $ (pippo) rispetto ai backtick `pippo` , perché puoi annidarlo ed è più facile distinguerlo dagli apostrofi.
utente sconosciuto

1
A proposito, è necessario definire una funzione ( valid) prima di chiamarla.
wjandrea,

Risposte:


345

Il valore restituito è memorizzato in $?. 0 indica successo, altri indica errore.

some_command
if [ $? -eq 0 ]; then
    echo OK
else
    echo FAIL
fi

Come qualsiasi altro valore testuale, puoi memorizzarlo in una variabile per un confronto futuro:

some_command
retval=$?
do_something $retval
if [ $retval -ne 0 ]; then
    echo "Return code was not zero but $retval"
fi

Per possibili operatori di confronto, vedere man test.


È bello ... posso contenere l'errore di output ?? !! , Perché in questo caso ho 2 errore: "testo" ex comando di errore, file non trovato e il mio errore "testo" che è in questo caso non è riuscita ad esempio
moata_u

@moata_u: è possibile memorizzare il valore in una variabile come mostrato nella mia risposta.
Lekensteyn,

@moata_u: Devi mettere un carattere ;prima di elsee fi: `if ...; poi ...; altro ...; fi
Lekensteyn,


1
@Blauhirn [ $? ](o equivalentemente, test $?) non funziona perché restituisce $?un numero (0, 1, ecc.) Che non è nullo. Vedere i documenti pertest : "Se EXPRESSION viene omesso, 'test' restituisce false. Se EXPRESSION è un singolo argomento, 'test' restituisce false se l'argomento è nullo e vero altrimenti."
Lekensteyn,

87

Se hai solo bisogno di sapere se il comando ha avuto esito positivo o negativo, non preoccuparti di eseguire il test $?, prova semplicemente il comando direttamente. Per esempio:

if some_command; then
    printf 'some_command succeeded\n'
else
    printf 'some_command failed\n'
fi

E assegnare l'output a una variabile non cambia il valore di ritorno (beh, a meno che non si comporti diversamente quando stdout non è un terminale ovviamente).

if output=$(some_command); then
    printf 'some_command succeded, the output was «%s»\n' "$output"
fi

http://mywiki.wooledge.org/BashGuide/TestsAndConditionals spiega ifin modo più dettagliato.


Che cosa succede se si desidera fare qualcosa di diverso dalla ramificazione, ad esempio archiviare il valore booleano in caso di errore o meno in un .ini? Quindi la tua variabile di output non lo fa, ma lo $?fa, quindi non sei corretto nel dire che testare direttamente il comando è strettamente migliore.
Timothy Swan,

L'assegnazione dell'output a una variabile può modificare il valore restituito quando si utilizza il localcomando, ovvero local foo=$(false); echo $?;produce 0sull'output. Ma localè rilevante solo all'interno delle funzioni bash.
Cromax,

26
command && echo OK || echo Failed

Se commandrestituisce un errore sullo schermo, come nasconderlo?
Sigur,

Se commandscrive errori su stderr, puoi usare il modulo command 2> /dev/null && echo OK || echo Failed. I 2> /dev/nullreindirizzamenti stderr output /dev/null. Tuttavia, alcune utility scriveranno errori su stdout (anche se questa è una cattiva pratica). In questo caso puoi omettere 2 dal reindirizzamento, ma perderai qualsiasi output dal comando. Questo metodo di verifica del successo è utile per una semplice logica ternaria, ma per comportamenti più complessi è meglio verificare la $?riuscita del comando o utilizzare il ifmetodo a blocchi indicato nella risposta di @ geirha.
Bender the Greatest,

17

$? dovrebbe contenere lo stato di uscita del comando precedente, che dovrebbe essere zero per nessun errore.

Quindi qualcosa del genere;

cd /nonexistant
if [ $? -ne 0 ]
then
    echo failed
else
    echo success!
fi

per la maggior parte dei casi, è più semplice utilizzare il costrutto && per concatenare i comandi che devono dipendere l'uno dall'altro. Quindi noncd /nonexistant && echo success! farebbe eco al successo perché il comando si interrompe prima di &&. Il corollario di questo è ||, dove sarebbe eco falliscono perché cd non è riuscita. (questo diventa utile se usi qualcosa come || exit, che terminerà lo script se il comando precedente falliva.)cd /nonexistant || echo fail


È bello ... posso contenere l'errore di output ?? !! , perché in questo caso ho 2 errori: comando errore "testo" es, file non trovato e errore "testo" che in questo caso non è riuscito ad esempio
moata_u


5
command && echo $? || echo $?

Intendi command; echo $??
Javier Buzzi,

No, la mia riga è corretta, fornisce il codice risultato effettivo come numero indipendentemente dal successo o dal fallimento.
modrobert,

1
Ok, per favore, spiegami le differenze tra loro: true && echo $? || echo $?/ true; echo $?e false && echo $? || echo $?/ false; echo $?- scoprirai che fanno esattamente la stessa cosa: D
Javier Buzzi,

Sì, lo stesso risultato ma senza la condizione. La domanda originale era "Come verificare se un comando è riuscito?", Questo si basava su risposte precedenti. Immagino che un esempio migliore sarebbe:command && echo "success: $?" || echo "fail: $?"
modrobert

5

Va notato che if...then...fie &&/ ||tipo di approccio riguarda lo stato di uscita restituito dal comando che vogliamo testare (0 in caso di successo); tuttavia, alcuni comandi non restituiscono uno stato di uscita diverso da zero se il comando non è riuscito o non è in grado di gestire l'input. Ciò significa che i soliti ife &&/ ||approcci non funzioneranno per quei comandi particolari.

Ad esempio, su Linux GNU fileesce ancora con 0 se ha ricevuto un file inesistente come argomento e findnon è riuscito a individuare il file specificato dall'utente.

$ find . -name "not_existing_file"                                          
$ echo $?
0
$ file ./not_existing_file                                                  
./not_existing_file: cannot open `./not_existing_file' (No such file or directory)
$ echo $?
0

In tali casi, un potenziale modo in cui potremmo gestire la situazione è la lettura stderr/ stdinmessaggi, ad esempio quelli restituiti dal filecomando o l'analisi dell'output del comando come in find. A tal fine, casepotrebbe essere utilizzata la dichiarazione.

$ file ./doesntexist  | while IFS= read -r output; do                                                                                                                  
> case "$output" in 
> *"No such file or directory"*) printf "%s\n" "This will show up if failed";;
> *) printf "%s\n" "This will show up if succeeded" ;;
> esac
> done
This will show up if failed

$ find . -name "doesn'texist" | if ! read IFS= out; then echo "File not found"; fi                                                                                     
File not found

(Questo è un ripostiglio della mia risposta sulla domanda correlata su unix.stackexchange.com )


1

Come menzionato in molte altre risposte, un semplice test di $?volontà farà, come questo

if [ $? -eq 0 ]; then something; fi

Se si desidera verificare se il comando non è riuscito , è possibile utilizzare una versione più breve in bash(ma forse eccessiva) come segue:

if (($?)); then something; fi

Funziona usando la (( ))modalità aritmetica, quindi se il comando è tornato success, cioè $? = 0il test valuta a ((0))quali test come false, altrimenti tornerà true.

Per verificare il successo , è possibile utilizzare:

if ! (($?)); then something; fi

ma non è già molto più breve del primo esempio.


1
critica costruttiva?
afuna,


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.