Добавляйте (собирайте) коды выхода в bash
Вопрос
Мне нужно зависеть от нескольких отдельных выполнений в скрипте, и я не хочу связывать их все в уродливом операторе 'if'.Я хотел бы взять код выхода '$?' каждого выполнения и добавить его;в конце, если это значение превышает пороговое значение - я хотел бы выполнить команду.
Псевдокод:
ALLOWEDERROR=5
run_something
RESULT=$?
..other things..
run_something_else
RESULT=$RESULT + $?
if [ $RESULT -gt ALLOWEDERROR ]
then echo "Too many errors"
fi
Проблема:Несмотря на то, что Интернет утверждает обратное, bash отказывается обрабатывать РЕЗУЛЬТАТ и $?как целое число.Каков правильный синтаксис?
Спасибо.
Решение
Возможно, вы захотите взглянуть на trap
встроенный, чтобы посмотреть, будет ли это полезно:
help trap
или
man bash
вы можете установить ловушку для подобных ошибок следующим образом:
#!/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
Если вы подсчитываете ошибки (и только тогда, когда они являются ошибками) следующим образом, вместо того чтобы использовать "$?
", тогда вам не нужно беспокоиться о возвращаемых значениях, отличных от нуля или единицы.Например, одно возвращаемое значение 127 немедленно выбросило бы вас за пределы вашего порога.Вы также можете зарегистрироваться trap
s для других сигналов в дополнение к ERR
.
Другие советы
Быстрый эксперимент и погружение в bash info говорит:
declare -i RESULT=$RESULT + $?
поскольку вы добавляете к результату несколько раз, вы можете использовать declare в начале, вот так:
declare -i RESULT=0
true
RESULT+=$?
false
RESULT+=$?
false
RESULT+=$?
echo $RESULT
2
который выглядит намного чище.
declare -i
говорит, что переменная является целочисленной.
В качестве альтернативы вы можете избежать объявления и использовать скобки арифметических выражений:
RESULT=$(($RESULT+$?))
Используйте $(( ... ))
сконструировать.
$ cat st.sh
RESULT=0
true
RESULT=$(($RESULT + $?))
false
RESULT=$(($RESULT + $?))
false
RESULT=$(($RESULT + $?))
echo $RESULT
$ sh st.sh
2
$
О том, как добавлять числа в Bash, также см.:
help let
Если вы хотите использовать ALLOWEDERROR в своем скрипте, предварите его символом $, например $ALLOWEDERROR .
Вот несколько способов выполнить сложение в bash или sh:
RESULT=`expr $RESULT + $?`
RESULT=`dc -e "$RESULT $? + pq"`
И некоторые другие только в bash:
RESULT=$((RESULT + $?))
RESULT=`bc <<< "$RESULT + $?"`
В любом случае, статус выхода при ошибке не всегда равен 1, и его значение не зависит от уровня ошибки, поэтому в общем случае нет особого смысла сверять сумму статусов с пороговым значением.
Как упоминал мувисьель, сбор суммы кодов возврата выглядит довольно бессмысленно.Вероятно, вы можете использовать array для накопления ненулевых кодов результатов и сверять их с длиной.Пример такого подхода приведен ниже:
#!/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