我有一个简单的shell脚本,带有以下序言:
#!/usr/bin/env bash
set -eu
set -o pipefail
我还具有以下功能:
foo() {
printf "Foo working... "
echo "Failed!"
false # point of interest #1
true # point of interest #2
}
作为常规命令执行foo()
可以按预期工作:该脚本在#1
处退出,因为false
的返回码非零,我们使用set -e
。
我的目标是将函数foo()
的输出捕获到一个变量中,并且仅在执行foo()
期间发生错误时才打印它。这是我想出的:
printf "Doing something that could fail... "
if a="$(foo 2>&1)"; then
echo "Success!"
else
code=$?
echo "Error:"
printf "${a}"
exit $code
fi
脚本不会在#1
处退出,并且会执行"Success!"
语句的if
路径。在true
处注释掉#2
会导致执行"Error:"
语句的if
路径。
[bash似乎只是忽略了替换中的set -e
,if
语句只是检查foo()
中最后一条命令的返回代码。
问:什么原因导致这种奇怪的行为?
A:这就是bash的工作方式,这是正常行为
Q:有什么方法可以使bash在命令替换内尊重set -e
并使它正常工作?
A:您不应为此目的使用set -e
问:在没有set -e
的情况下,您将如何实现它(即,仅当执行过程中出现问题时才打印函数的输出)?
我正在使用:
GNU bash,版本5.0.11(1)-发行版(x86_64-apple-darwin18.6.0)
您还需要在命令替换中启用set -e
:
#!/usr/bin/env bash
set -eu
set -o pipefail
foo() {
printf "Foo working... "
echo "Failed!"
false # point of interest #1
true # point of interest #2
}
printf "Doing something that could fail... "
a="$(set -e; foo)"
code=$?
if (($code == 0)); then
echo "Success!"
else
echo "Error:"
printf "${a}"
exit $code
fi
然后将其用作:
./errScript.sh; echo $?
Doing something that could fail... 1
但是请注意,在外壳程序脚本中使用set -e
并不理想,在许多情况下可能无法退出脚本。