我想知道bash脚本中的任何命令是否以非零状态退出。
我想要类似于set -e
功能的东西,除了当命令以非零状态退出时我不希望它退出。我想让它运行整个脚本,然后我想知道:
a)退出状态为0的所有命令退出
- 或 -
b)一个或多个以非零状态退出的命令
例如,给出以下内容:
#!/bin/bash
command1 # exits with status 1
command2 # exits with status 0
command3 # exits with status 0
我希望所有三个命令都能运行。运行脚本后,我想要一个指示,即至少有一个命令以非零状态退出。
答案 0 :(得分:7)
在ERR上设置陷阱:
#!/bin/bash
err=0
trap 'err=1' ERR
command1
command2
command3
test $err = 0 # Return non-zero if any command failed
您甚至可能会进行一些内省以获取有关错误发生位置的数据:
#!/bin/bash
for i in 1 2 3; do
eval "command$i() { echo command$i; test $i != 2; }"
done
err=0
report() {
err=1
echo -n "error at line ${BASH_LINENO[0]}, in call to "
sed -n ${BASH_LINENO[0]}p $0
} >&2
trap report ERR
command1
command2
command3
exit $err
答案 1 :(得分:3)
您可以尝试使用DEBUG
伪信号的陷阱执行某些操作,例如
trap '(( $? && ++errcount ))' DEBUG
在每个简单命令,DEBUG
命令,for
命令,case
命令,每个算术select
命令之前执行for
陷阱第一个命令在shell函数中执行“(引自手册)。
因此,如果您添加此陷阱并作为最后一个命令来打印错误计数,您将获得正确的值:
#!/bin/bash
trap '(( $? && ++errcount ))' DEBUG
true
false
true
echo "Errors: $errcount"
返回Errors: 1
和
#!/bin/bash
trap '(( $? && ++errcount ))' DEBUG
true
false
true
false
echo "Errors: $errcount"
打印Errors: 2
。请注意,最后一个语句实际上需要考虑第二个false
,因为在命令之前执行了陷阱,因此仅检查第二个false
的退出状态。执行echo
行的陷阱。
答案 2 :(得分:1)
我不确定是否有针对您的要求的现成解决方案。我会写一个这样的函数:
function run_cmd_with_check() {
"$@"
[[ $? -ne 0 ]] && ((non_zero++))
}
然后,使用该函数运行需要跟踪的所有命令:
run_cmd_with_check command1
run_cmd_with_check command2
run_cmd_with_check command3
printf "$non_zero commands exited with non-zero exit code\n"
如果需要,可以增强该功能,将所有失败的命令存储在一个阵列中,最后可以打印出来。
您可能需要查看此帖子以获取更多信息:Error handling in Bash
答案 3 :(得分:0)
你有bash中可用的魔术变量$?
,它告诉最后一个命令的退出代码:
#!/bin/bash
command1 # exits with status 1
C1_output=$? # will be 1
command2 # exits with status 0
C2_output=$? # will be 0
command3 # exits with status 0
C3_output=$? # will be 0
答案 4 :(得分:0)
对于每个命令,您可以执行此操作:
if ! Command1 ; then an_error=1; fi
对所有命令重复此操作
如果其中任何一个失败,an_error将为1。
如果你想要计算失败次数,那么在开始时将an_error设置为0并执行$((an_error ++))。而不是an_error = 1
答案 5 :(得分:0)
您可以将命令列表放入数组中,然后循环执行命令。任何返回错误代码的都会保留结果供以后查看。
declare -A results
commands=("your" "commands")
for cmd in "${commands[@]}"; do
out=$($cmd 2>&1)
[[ $? -eq 0 ]] || results[$cmd]="$out"
done
然后查看任何非零退出代码:
for cmd in "${!results[@]}"; do echo "$cmd = ${results[$cmd]}"; done
如果results
的长度为0,则命令列表中没有错误。
这需要Bash 4+(用于关联数组)
答案 6 :(得分:0)
您可以使用DEBUG
陷阱,如:
trap 'code+=$?' DEBUG
code=0
# run commands here normally
exit $code