Dia*_*gon 16 bash shell-script error-handling
我试图获取我在 Bash 循环的“条件”部分中重复调用的函数的退出代码while
:
while <function>; do
<stuff>
done
Run Code Online (Sandbox Code Playgroud)
当此循环由于错误而终止时,我需要 的退出代码<function>
。关于如何得到它有什么想法吗?
roa*_*ima 22
您可以捕获条件的退出值并将其向前传播:
while rmdir FOO; ss=$?; [[ $ss -eq 0 ]]
do
echo in loop
done
echo "out of loop with ?=$? but ss=$ss"
Run Code Online (Sandbox Code Playgroud)
输出
rmdir: failed to remove 'FOO': No such file or directory
out of loop with ?=0 but ss=1
Run Code Online (Sandbox Code Playgroud)
在本例中,退出状态rmdir FOO
已被捕获在变量中ss
,并且为1
。(尝试替换rmdir FOO
为( exit 4 )
。你会发现ss=4
。)
这是如何运作的?请记住,语法实际上是while list-1; do list-2; done
,而不是更常见的期望while command; do list; done
。可以list-1
是一系列以分号分隔的命令,并且文档指出“只要列表中的最后一个命令返回退出状态为零,该while
命令就会连续执行该列表list-2
list-1
。 ”
作为看起来混乱的while
条件的另一种表示方式,可以在表达式内部分配变量(( ... ))
,然后使用结果。这给出了更难阅读但更紧凑的分配和测试结构:
while rmdir FOO; ((! (ss=$?)))
do
echo in loop
done
echo "out of loop with ?=$? but ss=$ss"
Run Code Online (Sandbox Code Playgroud)
或者您可以使用while rmdir FOO; ! (( ss=$? ))
. 这些之所以有效,是因为 ((1)) 的算术计算结果为 1,这通常与 true 相关,因此该计算的退出代码为 0(成功)。另一方面,((0)) 的算术计算结果为 0,这通常与 false 相关,因此该计算的退出代码为 1(失败)。这可能看起来很令人困惑,因为毕竟两个评估((.))
都是“成功”的,但这是一种 hack,使表示 true/false 的算术表达式的值与 bash 的成功/失败退出代码保持一致,并创建条件表达式,如if ...; then ...; fi
、while ...; do ...; done
等,无论是基于退出代码还是算术值,都可以正常工作。
实现此目的的一种方法是显式进行测试,而不是将其委托给while
. 因此,应该执行以下操作:
err=0
while true
do
<function>
(( (err=$?) > 0 )) && break
<stuff>
done
echo "$err"
Run Code Online (Sandbox Code Playgroud)
在(先验无限)循环开始时,您将“手动”执行条件命令并存储退出代码,检查它,如果它非零(表示失败)则退出循环。仅当它为零时,您才执行“实际”循环代码。
语法可以“压缩”,因为(正如 @roaima 所指出的)您可以在(( ... ))
算术测试构造中进行变量赋值。