【问题标题】:Posix Shell test non zero exit code script termination when set -e设置 -e 时 Posix Shell 测试非零退出代码脚本终止
【发布时间】: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)的误解。

【问题讨论】:

标签: shell sh posix exit-code


【解决方案1】:

set -e 选项仅适用于单个命令。 它不适用于与 || 组合的命令或 &&。

man bash 说:

如果失败的命令是紧跟在 while 或 until 关键字之后的命令列表的一部分,是在 if 或 elif 保留字之后的测试的一部分,在 && 或 || 中执行的任何命令的一部分,则 shell 不会退出列出除了最后一个 && 或 || 之后的命令,管道中除最后一个之外的任何命令,或者命令的返回值是否用 ! 反转。

【讨论】:

  • 这可以解释很多,您能否提供一个指向任何说明这一点的文档的链接?
  • 尽管有&&||,是否可以应用set -e?也许我可以使用另一个选项来实现中断脚本执行,即使使用&&|| 组合多个命令?
  • 我用来自 bash 的引用编辑了回复(这实际上修复了我之前声明中的不准确之处)。
  • 不,我认为没有处理 && 或 || 的选项。
  • &&|| 的全部意义在于以一种比中止脚本更有意义的方式对失败做出反应
猜你喜欢
  • 2022-06-13
  • 1970-01-01
  • 2013-01-26
  • 2017-04-08
  • 2019-08-08
  • 1970-01-01
  • 1970-01-01
  • 2015-07-02
  • 2014-10-10
相关资源
最近更新 更多