首页 > 解决方案 > Shell / Bash:如何在命令行shell中未定义的函数上失败?

问题描述

我想确保我的命令行 shell 自动在未定义的函数上失败。

我不希望我的 shell 脚本在未定义的变量上失败,因为这会破坏我在 .bashrc 中采购的一些外部 shell 脚本(特别是 .git-completion.bash 开始与set -u标志行为不端)

我也不想在返回码 1 上失败,因为这会使我的 shell 无法使用(对文件中不存在的内容进行 grepping 会自动退出我的 shell)。

我想要的是在使用未定义的函数时硬停止。理想情况下,进程中断kill -INT -$$会立即停止当前进程,但不会退出 shell,但只要退出 shell 就可以正常工作,只要它只适用于未定义的函数,并且在捕获函数的输出时也能正常工作。

我所说的函数输出的意思是捕获只是设置set -uset -e甚至没有完全完成工作:

go1(){
  set -u
  set -e

  iDontExist

  echo "!!! reached operation after undefined !!!"
}
# > go1
# bash: iDontExist: command not found
# Saving session...bash: HISTTIMEFORMAT: unbound variable

以上工作。但是,如果我捕获输出,则标志不会捕获未定义的错误(即使由于问题开头指定的原因,我什至不想使用这些标志)

go2(){
  set -u
  set -e
  set -o pipefail

  echo $(iDontExist)

  echo "!!! reached operation after undefined !!!"
}
# > go2
# bash: iDontExist: command not found
#
# !!! reached operation after undefined !!!

还有其他一些很棒的标志可以完成工作吗?

标签: bashshellerror-handlinginterrupt

解决方案


使用时pipefailerrorexit您想通过以下方式清除错误状态:

may_fail_command || true

或者在一个条件下处理返回状态

declare myvar
if ! myvar="$(may_fail_command)"; then
  printf 'Error assigning myvar because may_fail_command failed code %d\n' $?
fi

如果您必须获取可能存在错误的源文件,您可以暂时禁用这些errorexit nounset pipefail标志。

您还应该测试采购的返回代码

if ! source may_fail_sourced.sh; then
... handle sourcing errors
fi

推荐阅读