【发布时间】:2020-08-20 17:45:20
【问题描述】:
我有一个函数运行一组脚本,这些脚本在当前 shell 中设置变量、函数和别名。
reloadVariablesFromScript() {
for script in "${scripts[@]}"; do
. "$script"
done
}
如果其中一个脚本有错误,我想退出脚本然后退出函数,而不是杀死shell。
reloadVariablesFromScript() {
for script in "${scripts[@]}"; do
{(
set -e
. "$script"
)}
if [[ $? -ne 0 ]]; then
>&2 echo $script failed. Skipping remaining scripts.
return 1
fi
done
}
这会做我想要的,只是它不会在脚本中设置变量,无论脚本是成功还是失败。
没有子shell,set -e 会导致整个 shell 退出,这是不可取的。
有没有一种方法可以防止被调用的脚本在不终止 shell 的情况下继续出错,或者从子 shell 中设置/导出变量、别名和函数?
以下脚本模拟了我的问题:
test() {
{(
set -e
export foo=bar
false
echo Should not have gotten here!
export bar=baz
)}
local errorCode=$?
echo foo="'$foo'". It should equal 'bar'.
echo bar="'$bar'". It should not be set.
if [[ $errorCode -ne 0 ]]; then
echo Script failed correctly. Exiting function.
return 1
fi
echo Should not have gotten here!
}
test
如果最糟糕的情况变得更糟,因为这些脚本实际上并不编辑文件系统,我可以在子 shell 中运行每个脚本,检查退出代码,如果成功,则在子 shell 之外运行它。
【问题讨论】:
-
脚本要么在当前 shell 上运行,要么不在。如果您不想退出 shell,请不要使用
set -e。 -
只有成功的脚本中的环境变量,失败的脚本不设置它们可以吗?
-
@MarcSances 是的,这实际上是理想的。虽然,它必须包含别名和函数。
-
“必须包括别名和函数”的细节至关重要——我有一个半写的答案,它不会包括在内。函数可以导出到环境中,但别名不能;显式调用是一项重要要求。
-
@alecxs, ...如果用户没有获取脚本,他们将没有它的函数/变量/别名/等。如果成功,则在他们的父环境中,这是他们明确尝试完成的。