2012-01-16 17 views
10

Sono molto nuovo per gli script di bash e, per il mio primo tentativo di script, invio i file alla casella personale del mio professore all'interno dello stesso server.Errore di script Bash Catching

Il codice è questo:

#! /bin/bash 
echo "Submit Lab$1? \c" 

read choice 

if [ $choice = "y" ]; then 
    echo "Sending to Prof's dropbox..." 
    cp -r /path/to/lab$1 /path/to/dropbox 
else 
    echo "Submission terminated." 
fi 

Uso per il comando è semplicemente "$ submit 1" (1 è un singolo intero, corrispondenti alla quale laboratorio voglio inviare)

Lo script bash aggiunge i argomento inserito (un singolo intero) al nome file necessario (una directory), quindi invia tale directory alla casella personale del mio prof utilizzando cp.

Altro per motivi di apprendimento piuttosto che di necessità assoluta, volevo creare un prompt pulito che catturasse qualsiasi errore di cp (come il file non esistente), ed essere in grado di generare il mio messaggio di errore.

Quindi, in pratica, qualcosa di simile:

echo "Submit lab$1?" 

read choice 

echo "Send to Prof's dropbox" 
cp -rv /path/to/lab$1 /path/to/dropbox 

<catch any errors from cp> 

if [ cp has errors ] 

    echo "Submission failed." 

else if [ cp has no errors ] 

    echo "Submission successful." 

And so on... 

ho capito che avrei potuto utilizzare la modalità verbose, e che cp si stamperà gli errori, ma come detto prima, sto facendo questo allo scopo di errore di apprendimento catturare in bash e essere in grado di fare un prompt pulito.

Qualsiasi aiuto sarebbe apprezzato.

Grazie!


anche: Ho uno script simile che presenta i laboratori dal mio computer portatile, utilizzando scp. Supponendo che abbia risposto a questa domanda, posso applicare le soluzioni a scp esattamente nello stesso modo?

EDIT: Non voglio cp errori di uscita alla shell! L'errore più comune sarebbe probabilmente "non può stat blah: nessun file o directory di questo tipo". Vorrei rilevare questo errore e dire semplicemente "Invio non riuscito".

EDIT # 2: La risposta di jcollado è corretta, il problema è da parte mia. Non è stato terminato lo if-else nidificato con l'appropriato "fi".

Dopo aver risolto il problema, ha funzionato come previsto. Devo ancora catturare l'output dell'errore, ma credo di sapere dove devo andare a capirlo da solo, quindi questa domanda è stata esaudita per quanto mi riguarda.

FINALE: Ah, che diamine - il reindirizzamento è stato così facile ho pensato di mettere la soluzione qui. Se si utilizza Linux, è sufficiente aggiungere "2>/dev/null" (se non si desidera che i messaggi di errore in fase di salvataggio in qualsiasi file) dopo la cp di fare "cp -r /first/path /second/path 2>/dev/null"

risposta

23

Anche se è possibile testare $ ?, si può anche verificare lo stato di uscita di un comando direttamente:

if cp -rv /path/to/lab$1 /path/to/dropbox 
then echo Submission successful 
fi 
exit $? 

Gli errori sono stati già segnalati allo standard errore di cp. Lo exit visualizzato uscirà con lo stato 0 (esito positivo) se cp ha avuto esito positivo; altrimenti, viene chiuso con lo stato con cui è stato chiuso cp.

Chiaramente, è possibile avvolgerlo in un ciclo se lo si desidera oppure è possibile renderlo non interattivo (ma qualsiasi uscita termina lo script).

+0

Grazie per la soluzione alternativa. La migliore risposta basata sulla semplicità. – skippr

+0

Credo che il codice di uscita di cui sopra sarà sempre zero. Se 'cp' fallisce (restituendo non-0) allora' if' restituirà 0. bash's 'echo' restituisce sempre 0. Dalla pagina man, riguardo a 'if': * Lo stato di uscita è lo stato di uscita dell'ultimo comando eseguito o zero se nessuna condizione è stata verificata. * –

+1

@ mr.spuratic: sembra che tu abbia ragione. Esecuzione 'se vera; quindi eco vero; fi; echo $? 'in Bash, Korn shell, la shell di Heirloom stampa true e quindi 0; sostituirlo con 'se falso; quindi eco vero; fi; echo $? 'e stampa solo 0. Quindi, lo stato' $? 'non conserva lo stato di uscita del comando eseguito in' if'. Ci sono modi per aggirare questo, di maggiore o minore eleganza. Uno di questi è 'status = 0; se è vero; quindi eco vero; altro stato = 1; fi; echo $ status'. Oppure puoi fare l'inverso: 'status = 1; se è vero; quindi eco vero; status = 0; fi; echo $ status'. –

8

Per controllare il codice di ritorno del comando precedente, è possibile utilizzare il $? variabile speciale come segue:

if [ "$?" -ne "0" ]; then 
    echo "Submission failed" 
    exit 1 
fi 

echo "Submission successful." 

Inoltre, se si desidera un prompt pulita, è possibile redired stderr come spiegato here.

Infine, è possibile utilizzarlo anche nello script che utilizza scp, poiché funziona indipendentemente dal comando che si sta utilizzando.

+0

Grazie per la risposta immediata (no pun intended)! Guarderò più a reindirizzamenti stderr, in quanto sembra essere dove risiede la soluzione "clean prompt". Tuttavia, il codice che hai fornito non funziona per invii non riusciti. Non stampa "Invio non riuscito". quando cp fallisce. Tuttavia, ignora "Invio riuscito" quando cp fallisce. – skippr

+0

Ho notato che quando cp fallisce, nulla dopo viene eseguito. – skippr

+0

Ah, il problema era da parte mia. Ho capito adesso. Grazie! – skippr

2
echo "Submit lab$1?" 

read choice 

echo "Send to Prof's dropbox" 
cp -rv /path/to/lab$1 /path/to/dropbox &>/dev/null 

[ $? -eq 0 ] && { #success, do something } || { #fail, do something } 

E così via ...