【发布时间】:2021-04-21 06:02:30
【问题描述】:
阅读test shell 命令的手册:
man test
描述状态:
以 EXPRESSION 确定的状态退出。
但这与我的 POSIX sh 测试脚本示例冲突,我使用 set -eu 如果命令的退出状态不为零,则应该终止脚本:
#!/bin/sh
set -eu
status=1
test "$status" -ne 0 && echo "Status not eq 0"
echo "(A) Exit code for "$status" = $?"
echo ""
status=0
test "$status" -ne 0 && echo "Status not eq 0"
echo "(B) Exit code for "$status" = $?"
echo ""
status=1
test "$status" -ne 0
echo "(C) Exit code for "$status" = $?"
echo ""
status=0
test "$status" -ne 0
echo "(D) Exit code for "$status" = $?"
运行该脚本提供输出:
Status not eq 0
(A) Exit code for 1 = 0
(B) Exit code for 0 = 1
(C) Exit code for 1 = 0
这就是我对以下执行流程的理解:
status=1
test "$status" -ne 0 && echo "Status not eq 0"
echo "(A) Exit code for "$status" = $?"
带输出:
Status not eq 0
(A) Exit code for 1 = 0
test "$status" -ne 0 计算结果为 true,因此其退出代码为零,因此在执行布尔 && 之后的表达式,并且由于它只是一个 echo,它也返回零退出代码,因此脚本不会停止并回显下一行(A) Exit code for 1 = 0
但对于
status=0
test "$status" -ne 0 && echo "Status not eq 0"
echo "(B) Exit code for "$status" = $?"
输出:
(B) Exit code for 0 = 1
按照前面的推理,test 应该返回非零,因此不应执行 && 之后的表达式(并且它不是),但脚本甚至会执行 test 返回非零退出代码 (B) 退出代码对于 0 = 1。
为什么脚本会继续执行?由于非零退出状态,它应该刹车。
案例没有输出:
status=0
test "$status" -ne 0
echo "(D) Exit code for "$status" = $?"
这表明脚本执行在test "$status" -ne 0 行终止,如果您在运行脚本后运行echo $?,实际上您将得到1。
但是,当测试返回示例 (D) 的非零退出状态但不是示例 (B) 时,为什么脚本会终止?
(D) 和 (B) 之间的唯一区别是 (B) 在测试后有&& echo "Status not eq 0" 但那是未执行,退出状态为1,所以在 (B) 的情况下,脚本应该被终止,但它没有被终止,如果测试的退出状态以某种方式被特别处理,那么它会这样做不终止具有set -e 的脚本,那么为什么它会终止 (D) 示例的脚本?
编辑
类似于test 的行为ls
对于脚本:
#!/bin/sh
set -eu
ls notexitingfile && echo "File exists"
echo "Exit code for ls = $?"
ls notexitingfile
echo "Exit code for ls = $?"
输出是:
ls: cannot access 'notexitingfile': No such file or directory
Exit code for ls = 2
ls: cannot access 'notexitingfile': No such file or directory
第一个示例请注意Exit code for ls = 2,第二个示例则没有。
我认为意外行为的原因可能是我对使用&& 运算符时的非零退出代码导致脚本终止(set -e)的误解。
【问题讨论】: