Add (collect) exit codes in bash

2020-06-03 04:44发布

I need to depend on few separate executions in a script and don't want to bundle them all in an ugly 'if' statement. I would like to take the exit code '$?' of each execution and add it; at the end, if this value is over a threshold - I would like to execute a command.

Pseudo code:

ALLOWEDERROR=5

run_something
RESULT=$?
..other things..

run_something_else
RESULT=$RESULT + $?

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

Issue: Even though the Internet claims otherwise, bash refuses to treat the RESULT and $? as integer. What is the correct syntax?

Thanks.

7条回答
在下西门庆
2楼-- · 2020-06-03 05:03

Use the $(( ... )) construct.

$ cat st.sh
RESULT=0
true
RESULT=$(($RESULT + $?))
false
RESULT=$(($RESULT + $?))
false
RESULT=$(($RESULT + $?))
echo $RESULT
$ sh st.sh
2
$
查看更多
走好不送
3楼-- · 2020-06-03 05:05

Here are some ways to perform an addition in bash or sh:

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

And some others in bash only:

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

Anyway, exit status on error is not always 1 and its value does not depend on error level, so in the general case there is not much sense to check a sum of statuses against a threshold.

查看更多
叛逆
4楼-- · 2020-06-03 05:12

A quick experiment and dip into bash info says:

declare -i RESULT=$RESULT + $?

since you are adding to the result several times, you can use declare at the start, like this:

declare -i RESULT=0

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

echo $RESULT
2

which looks much cleaner.

declare -i says that the variable is integer.

Alternatively you can avoid declare and use arithmetic expression brackets:

RESULT=$(($RESULT+$?))
查看更多
女痞
5楼-- · 2020-06-03 05:12

For how to add numbers in Bash also see:

help let 
查看更多
Luminary・发光体
6楼-- · 2020-06-03 05:13

If you want to use ALLOWEDERROR in your script, preface it with a $, e.g $ALLOWEDERROR.

查看更多
成全新的幸福
7楼-- · 2020-06-03 05:20

As mouviciel mentioned collecting sum of return codes looks rather senseless. Probably, you can use array for accumulating non-zero result codes and check against its length. Example of this approach is below:

#!/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
查看更多
登录 后发表回答