【问题标题】:Function invocation in for loop does not fail even with "set -e"即使使用“set -e”,for 循环中的函数调用也不会失败
【发布时间】:2017-10-16 07:49:39
【问题描述】:

考虑以下简单的 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"

【问题讨论】:

  • 看看BashFAQ/105
  • set -u 也不是没有注意事项——参见BashFAQ #112。简短形式:编写可靠的 shell 脚本没有灵丹妙药;如果有,set -eou pipefail肯定不是。

标签: bash


【解决方案1】:

看来set -e在命令替换的上下文中是无效的,如:

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

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

gen

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

【讨论】:

    猜你喜欢
    • 2018-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    相关资源
    最近更新 更多