Aggiungi (raccogli) i codici di uscita in bash
Domanda
Devo dipendere da poche esecuzioni separate in uno script e non voglio raggrupparle tutte in una brutta dichiarazione 'if'. Vorrei prendere il codice di uscita '$?' di ogni esecuzione e aggiungerlo; alla fine, se questo valore supera una soglia, vorrei eseguire un comando.
Codice pseudo:
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 diversamente, bash rifiuta di trattare il RISULTATO e $? come intero. Qual è la sintassi corretta?
Grazie.
Soluzione
Potresti dare un'occhiata al trap
incorporato per vedere se sarebbe utile:
help trap
o
man bash
puoi impostare una trappola per 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 conti gli errori (e solo quando sono errori) in questo modo invece di usare " $?
" ;, allora non devi preoccuparti di valori di ritorno diversi da zero o uno. Un singolo valore di ritorno di 127, ad esempio, ti getterebbe immediatamente oltre la soglia. Puoi anche registrare trap
per altri segnali oltre a ERR
.
Altri suggerimenti
Un rapido esperimento e un tuffo nelle informazioni bash dice:
declare -i RESULT=$RESULT + $?
poiché stai aggiungendo più volte al risultato, puoi usare dichiarare all'inizio, 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 puoi evitare di dichiarare e usare parentesi di espressione aritmetica:
RESULT=$(($RESULT+$?))
Usa il costrutto $ ((...))
.
$ cat st.sh
RESULT=0
true
RESULT=$(($RESULT + $?))
false
RESULT=$(($RESULT + $?))
false
RESULT=$(($RESULT + $?))
echo $RESULT
$ sh st.sh
2
$
Per come aggiungere numeri in Bash vedi anche:
help let
Se vuoi usare ALLOWEDERROR nel tuo script, prefiguralo con $, ad esempio $ ALLOWEDERROR.
Ecco alcuni modi per eseguire un'aggiunta in bash o sh:
RESULT=`expr $RESULT + $?`
RESULT=`dc -e "$RESULT $? + pq"`
E alcuni altri solo in bash:
RESULT=$((RESULT + $?))
RESULT=`bc <<< "$RESULT + $?"`
Comunque, 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.
Come menzionato da mouviciel, la raccolta della somma dei codici di ritorno sembra piuttosto insensata. Probabilmente, puoi usare l'array per accumulare codici di risultato diversi da zero e verificarne la lunghezza. L'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