bash - 即使使用 "set -e",for 循环中的函数调用也不会失败

标签 bash

考虑以下简单的 bash 脚本:

#!/bin/bash
set -eou pipefail
IFS=$'\n\t'

gen() {
  seq 0 3
}

for c in $(gen); do
  echo c
done

echo "finish"

它设置了 set -e,所以当出现故障时,它应该以非零退出代码退出。

它将调用 gen 函数并打印 seq 0 3 的输出,将打印 finish 并以 code=0 退出。

如果我将 gen 修改为失败,例如,通过调用 seqqq 命令(它不存在)来代替:

$ ./script.sh; echo $?
./script.sh: line 6: seqqq: command not found
finish
0

它打印来自子 shell 的错误消息,它不会像 set -e 应该做的那样立即失败并立即退出(使用非零代码);它继续执行并以 code=0 退出。

这背后的解释是什么?请注意,如果我只是像这样用我的 for 循环替换,它会按预期失败:

#!/bin/bash
set -eou pipefail
IFS=$'\n\t'

gen() {
  seqqq 0 3
}

gen # <-- fails and exits here with code=127

echo "finish"

最佳答案

似乎 set -e 在命令替换的上下文中无效,如:

for c in $(gen); do
  echo c
done

但是,set -e 确实在直接函数调用的上下文中起作用,如:

gen

set -e 编写可靠的 shell 脚本很难或几乎不可能。请改用显式错误处理。您可以在这里阅读更多相关信息:BashFAQ/105

关于bash - 即使使用 "set -e",for 循环中的函数调用也不会失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44014857/

相关文章:

bash - 匹配前后的 Grep 字符?

bash - 使用 bash 将字符串转换为数组,使用引号进行分组

c - 如果你懂 C 为什么还要学 bash?

linux - 除非将脚本内容复制并粘贴到终端中,否则以其他用户身份或在 Chroot 环境中运行一系列命令不起作用

json - 使用类似 printf 的输出拖尾 JSON 日志文件

linux - 如何使用 shell 脚本执行命令并将文件存储在文件夹中?

bash - 我的 stderr 去哪儿了?

bash - 如何将循环合并到 bash 别名中

linux - 尝试使用 grep 进行过滤

bash - 在文件夹打开或内容更改时运行 bash 脚本