#!/usr/bin/env bash
set -e
shopt -s inherit_errexit
a=$(cat no-such-file)
echo survived
Run Code Online (Sandbox Code Playgroud)
$ /tmp/a.sh
cat: no-such-file: No such file or directory
Run Code Online (Sandbox Code Playgroud)
#!/usr/bin/env bash
set -e
shopt -s inherit_errexit
echo -n $(cat no-such-file)
echo survived
Run Code Online (Sandbox Code Playgroud)
$ /tmp/a.sh
cat: no-such-file: No such file or directory
survived
Run Code Online (Sandbox Code Playgroud)
#!/usr/bin/env bash
set -e
shopt -s inherit_errexit
f() { :; }
f $(cat no-such-file)
echo survived
Run Code Online (Sandbox Code Playgroud)
$ /tmp/a.sh
cat: no-such-file: No such file or directory
survived
Run Code Online (Sandbox Code Playgroud)
还有其他案例吗?或者一些概括?
TL,DR: 受益于set -e,请将命令替换的结果直接分配给变量(可以选择在其周围添加额外的字符串)。不要将多个命令替换组合在一起或在命令参数中使用命令替换。
问题不在于inherit_errexit. 它正在发挥作用。问题是其局限性set -e(这不是 bash 所特有的:其他类似 sh 的 shell 也有同样的问题)的局限性。
演示:运行第二个示例的变体。
\n$ cat b2.sh \n#!/usr/bin/env bash\nset -e\nshopt -s inherit_errexit\necho -n $(cat no-such-file; echo >&2 after cat)\necho survived\n$ ./b2.sh \ncat: no-such-file: No such file or directory\nsurvived\nRun Code Online (Sandbox Code Playgroud)\n请注意,echo >&2 after cat没有执行。那就如果inherit_errexit如果关闭的话
问题是set -e仅在简单情况下出现错误时才会停止执行。如果命令替换返回失败状态,则不会停止包含替换的简单命令的执行。它最多可能设置简单命令的返回状态,这可能反过来停止脚本的执行。\xe2\x80\x9csimple 命令\xe2\x80\x9d 由赋值、重定向和可选的可执行命令名称和参数组成。如果重定向失败,则返回状态为1。否则,如果有命令名,则简单命令的返回状态为可执行命令的返回状态。否则返回状态是最后一个命令替换的返回状态,如果没有则返回0。以下是一些简单命令的示例:
true </no/such/file由于重定向失败,\xe2\x86\x92 状态为 1false </dev/null\xe2\x86\x92 状态 1 来自falsea=b\xe2\x86\x92 状态 0,因为没有任何可能失败的部分a=$(exit 0) b=$(exit 1) c=$(exit 2)上次命令替换的 \xe2\x86\x92 状态 2a=$(exit 2) b=$(exit 1) c=$(exit 0)上次命令替换的 \xe2\x86\x92 状态 0true $(exit 0) $(exit 1) $(exit 2)\xe2\x86\x92 状态 0 来自true再次强调,在所有情况下,set -e只有当命令的状态非零时才会停止脚本。嵌入命令的状态不直接相关。
因此,在第二个脚本中,echo -n $(\xe2\x80\xa6)状态为 0,来自echo(除非echo无法写入),无论命令替换中发生什么。因此,即使脚本处于活动状态,也不会在此停止set -e。同样,在第三个脚本中,f $(\xe2\x80\xa6)的状态为 0 f。
| 归档时间: |
|
| 查看次数: |
1523 次 |
| 最近记录: |