在 bash 中添加(收集)退出代码
Posted
技术标签:
【中文标题】在 bash 中添加(收集)退出代码【英文标题】:Add (collect) exit codes in bash 【发布时间】:2009-06-16 09:14:28 【问题描述】:我需要依赖脚本中的几个单独执行,并且不想将它们全部捆绑在一个丑陋的“if”语句中。我想使用退出代码“$?”每次执行并添加它;最后,如果这个值超过阈值 - 我想执行一个命令。
伪代码:
ALLOWEDERROR=5
run_something
RESULT=$?
..other things..
run_something_else
RESULT=$RESULT + $?
if [ $RESULT -gt ALLOWEDERROR ]
then echo "Too many errors"
fi
问题:尽管 Internet 声称并非如此,bash 拒绝处理 RESULT 和 $?作为整数。正确的语法是什么?
谢谢。
【问题讨论】:
result=$(( result + $? ))
【参考方案1】:
您可能想看看 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 会立即使您超过阈值。除了ERR
之外,您还可以注册trap
s 用于其他信号。
【讨论】:
【参考方案2】:快速实验并深入了解 bash 信息说:
declare -i RESULT=$RESULT + $?
由于您多次添加到结果中,您可以在开始时使用声明,如下所示:
declare -i RESULT=0
true
RESULT+=$?
false
RESULT+=$?
false
RESULT+=$?
echo $RESULT
2
看起来干净多了。
declare -i
表示变量是整数。
您也可以避免声明和使用算术表达式括号:
RESULT=$(($RESULT+$?))
【讨论】:
最后一个只计算执行次数,不考虑错误(或成功):RESULT=$(($RESULT+1))。如果要使用 $(()) 构造,则需要添加 $?而不是 1(如 Dave Hinton 的回答)。否则,即使命令返回 0,您也会递增。或者您可以使用我的答案中的陷阱。 谢谢您,我已在您的修复中进行了编辑。我喜欢你的回答。 如果一行的返回码为 -1 而另一行的返回码为 1,这将不起作用,因为它们加起来看起来像成功(即 0)。跨度> 【参考方案3】:使用$(( ... ))
构造。
$ cat st.sh
RESULT=0
true
RESULT=$(($RESULT + $?))
false
RESULT=$(($RESULT + $?))
false
RESULT=$(($RESULT + $?))
echo $RESULT
$ sh st.sh
2
$
【讨论】:
【参考方案4】:有关如何在 Bash 中添加数字,另请参阅:
help let
【讨论】:
【参考方案5】:如果您想在脚本中使用 ALLOWEDERROR,请在其前面加上 $,例如 $ALLOWEDERROR。
【讨论】:
【参考方案6】:正如 mouviciel 提到的那样,收集返回码的总和看起来相当无意义。可能,您可以使用数组来累积非零结果代码并检查其长度。这种方法的例子如下:
#!/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
【讨论】:
【参考方案7】:以下是一些在 bash 或 sh 中执行加法的方法:
RESULT=`expr $RESULT + $?`
RESULT=`dc -e "$RESULT $? + pq"`
还有一些仅在 bash 中的:
RESULT=$((RESULT + $?))
RESULT=`bc <<< "$RESULT + $?"`
无论如何,错误退出状态并不总是 1,其值也不取决于错误级别,因此在一般情况下,根据阈值检查状态总和没有多大意义。
【讨论】:
我会为你答案的“不总是 1”部分给你一个 +1,但我不会因为 a) 你使用反引号而不是 $() 和 b) expr 是在 bash 和 3) 中是不必要的,并且 dc 对添加来说太过分了。如果 OP 使用 sh 而不是 bash(或者如果它是为了可移植性),那么 expr 和 back tick 就可以了。 ...和 d) 为什么没有 RESULT=bc <<< "$RESULT + $?"
?
没有理由在任何符合 POSIX sh 规范的原始 1991 版本的 shell 中使用 expr
。 $(( ... ))
已经提供了更快、更高效的内置语法,现在不需要分叉子进程和 exec()
'ing 外部命令 decades。
...也就是说,$(( ... ))
绝对不是 bash-only;它适用于每个符合标准的/bin/sh
。以上是关于在 bash 中添加(收集)退出代码的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 ERR 陷阱中退出 0 时 bash 会抑制标准输出?