2009-06-16 9 views
7

Ho bisogno di dipendere da alcune esecuzioni separate in uno script e non voglio raggrupparle tutte in una brutta 'se' istruzione. Vorrei prendere il codice di uscita '$?' di ogni esecuzione e aggiungila; alla fine, se questo valore supera una soglia, vorrei eseguire un comando.Aggiungere (raccogliere) i codici di uscita in bash

Pseudo codice:

ALLOWEDERROR=5 

run_something 
RESULT=$? 
..other things.. 

run_something_else 
RESULT=$RESULT + $? 

if [ $RESULT -gt ALLOWEDERROR ] 
    then echo "Too many errors" 
fi 

Problema: Anche se Internet afferma il contrario, bash si rifiuta di trattare il risultato e $? come numero intero. Qual è la sintassi corretta?

Grazie.

risposta

9

Si potrebbe voler dare un'occhiata al trap incorporato per vedere se sarebbe utile:

help trap 

o

man bash 

è possibile impostare una trappola per gli errori come questo:

#!/bin/bash 

AllowedError=5 

SomeErrorHandler() { 
    ((errcount++))  # or ((errcount += $?)) 
    if ((errcount > $AllowedError)) 
    then 
     echo "Too many errors" 
     exit $errcount 
    fi 
} 

trap SomeErrorHandler ERR 

for i in {1..6} 
do 
    false 
    echo "Reached $i"  # "Reached 6" is never printed 
done 

echo "completed"   # this is never printed 

Se si contano gli errori (e solo quando sono errori) come questo invece di utilizzare "$?", quindi non devi preoccuparti di restituisce valori diversi da zero o uno. Ad esempio, un singolo valore di restituzione di 127, ti getterebbe immediatamente oltre la soglia. È inoltre possibile registrare trap s per altri segnali oltre a ERR.

13

Un esperimento rapido e tuffo info bash dice:

declare -i RESULT=$RESULT + $? 

dal momento che si sta aggiungendo al risultato più volte, è possibile utilizzare dichiarare alla partenza, in questo modo:

declare -i RESULT=0 

true 
RESULT+=$? 
false 
RESULT+=$? 
false 
RESULT+=$? 

echo $RESULT 
2 

che sembra molto più pulito.

declare -i dice che la variabile è intera.

In alternativa si può evitare di dichiarare e utilizzare le parentesi espressione aritmetica:

RESULT=$(($RESULT+$?)) 
+1

L'ultimo conta solo il numero di volte in cui è stato eseguito, indipendentemente dall'errore (o dal successo): RISULTATO = $ (($ RISULTATO + 1)). Se si desidera utilizzare il costrutto $ (()), è necessario aggiungere $? invece di 1 (come nella risposta di Dave Hinton). Altrimenti, aumenterai anche quando il comando restituirà 0. Oppure puoi usare una trappola come nella mia risposta. –

+1

Grazie per quello, ho modificato la tua correzione. Mi piace la tua risposta. –

+0

Questo non funzionerà se una riga ha un codice di ritorno di -1 e un altro ha un codice di ritorno di 1, poiché verranno sommati per apparire come successi (che è 0). –

0

Utilizzare la $((...)) costrutto.

$ cat st.sh 
RESULT=0 
true 
RESULT=$(($RESULT + $?)) 
false 
RESULT=$(($RESULT + $?)) 
false 
RESULT=$(($RESULT + $?)) 
echo $RESULT 
$ sh st.sh 
2 
$ 
1

Ecco alcuni modi per eseguire un'addizione in bash o sh:

RESULT=`expr $RESULT + $?` 
RESULT=`dc -e "$RESULT $? + pq"` 

e alcuni altri in bash solo:

RESULT=$((RESULT + $?)) 
RESULT=`bc <<< "$RESULT + $?"` 

In ogni caso, lo stato di uscita in caso di errore non è sempre 1 e il suo valore non dipende dal livello di errore, quindi nel caso generale non ha molto senso controllare una somma di stati rispetto a una soglia.

+0

Ti darei un +1 per la parte "non sempre 1" della tua risposta, ma non lo farò perché a) usi i tick posteriori invece di $() eb) expr non è necessario in bash e 3) dc è un modo eccessivo per l'aggiunta. Se l'OP usava sh invece di bash (o se era per la portabilità) allora i tick di expr e back sarebbero OK. –

+0

... e d) perché non avere RISULTATO = 'bc <<<" $ RISULTATO + $? "'? –

+1

Grazie per le tue precisioni. Risposta aggiornata – mouviciel

-1

Come mouviciel menzionato raccogliendo la somma dei codici di ritorno sembra piuttosto insensato. Probabilmente, puoi usare la matrice per accumulare codici di risultato diversi da zero e controllarne la lunghezza.Esempio di questo approccio è di seguito:

#!/bin/sh 

declare RESULT 
declare index=0 
declare ALLOWED_ERROR=1 

function write_result { 
    if [ $1 -gt 0 ]; then 
     RESULT[index++]=$1 
    fi 
} 

true 
write_result $? 

false 
write_result $? 

false 
write_result $? 

echo ${#RESULT[*]} 
if [ ${#RESULT[*]} -gt $ALLOWEDERROR ] 
    then echo "Too many errors" 
fi 
1

Per informazioni su come aggiungere numeri Bash vedi anche:

help let 
1

Se si desidera utilizzare ALLOWEDERROR nel proprio script, inserirlo con $, ad esempio $ ALLOWEDERROR.