Добавить (собрать) коды выхода в Bash - PullRequest
8 голосов
/ 16 июня 2009

Мне нужно зависеть от нескольких отдельных исполнений в скрипте, и я не хочу связывать их все в некрасивом операторе if. Я хотел бы взять код выхода '$?' каждого исполнения и добавить его; в конце, если это значение превышает пороговое значение - я хотел бы выполнить команду.

Псевдокод:

ALLOWEDERROR=5

run_something
RESULT=$?
..other things..

run_something_else
RESULT=$RESULT + $?

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

Проблема: даже если Интернет заявляет об обратном, bash отказывается обрабатывать RESULT и $? как целое число Какой правильный синтаксис?

Спасибо.

Ответы [ 7 ]

14 голосов
/ 16 июня 2009

Быстрый эксперимент и информация о bash говорит:

declare -i RESULT=$RESULT + $?

, так как вы добавляете результат несколько раз, вы можете использовать объявление при запуске, например:

declare -i RESULT=0

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

echo $RESULT
2

, который выглядит намного чище.

declare -i говорит, что переменная является целым числом.

В качестве альтернативы вы можете избежать объявления и использовать скобки арифметических выражений:

RESULT=$(($RESULT+$?))
9 голосов
/ 16 июня 2009

Возможно, вы захотите взглянуть на встроенную функцию 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.

1 голос
/ 16 июня 2009

Если вы хотите использовать ALLOWEDERROR в вашем скрипте, добавьте к нему префикс $, например, $ ALLOWEDERROR.

1 голос
/ 16 июня 2009

О том, как добавить числа в Bash, см. Также:

help let 
1 голос
/ 16 июня 2009

Используйте конструкцию $(( ... )).

$ cat st.sh
RESULT=0
true
RESULT=$(($RESULT + $?))
false
RESULT=$(($RESULT + $?))
false
RESULT=$(($RESULT + $?))
echo $RESULT
$ sh st.sh
2
$
0 голосов
/ 16 июня 2009

Как упоминал Мувичиэль, сбор суммы кодов возврата выглядит довольно бессмысленным. Возможно, вы можете использовать массив для накопления ненулевых кодов результата и проверки его длины. Пример такого подхода ниже:

#!/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
0 голосов
/ 16 июня 2009

Вот несколько способов выполнить сложение в bash или sh:

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

И некоторые другие только в bash:

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

В любом случае, состояние выхода при ошибке не всегда равно 1, и его значение не зависит от уровня ошибки, поэтому в общем случае нет смысла проверять сумму статусов по отношению к порогу.

...