我有一个函数,该函数运行一组脚本,这些脚本在当前shell中设置变量,函数和别名。
reloadVariablesFromScript() {
for script in "${scripts[@]}"; do
. "$script"
done
}
如果其中一个脚本有错误,我想退出该脚本,然后退出该功能,但不要杀死该外壳。
reloadVariablesFromScript() {
for script in "${scripts[@]}"; do
{(
set -e
. "$script"
)}
if [[ $? -ne 0 ]]; then
>&2 echo $script failed. Skipping remaining scripts.
return 1
fi
done
}
这将满足我的要求,只是它不会在脚本中设置变量是成功还是失败。
没有子set -e
外壳,将导致整个外壳退出,这是不希望的。
有没有一种方法可以防止被调用的脚本继续发生错误而不杀死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
更糟的是,由于这些脚本实际上并未编辑文件系统,因此我可以在子外壳程序中运行每个脚本,检查退出代码,如果成功,则可以在子外壳程序外部运行它。
请注意,它set -e
具有许多令人惊讶的行为-普遍认为,依靠它不是一个好主意。但是,需要注意的是:我们可以将环境变量,别名和shell函数改写为文本:
envTest() {
local errorCode newVars
newVars=$(
set -e
{
export foo=bar
false
echo Should not have gotten here!
export bar=baz
} >&2
# print generate code which, when eval'd, recreates our functions and variables
declare -p | egrep -v '^declare -[^[:space:]]*r'
declare -f
alias -p
); errorCode=$?
if (( errorCode == 0 )); then
eval "$newVars"
fi
printf 'foo=%q. It should equal %q\n' "$foo" "bar"
printf 'bar=%q. It should not be set.\n' "$bar"
if [[ $errorCode -ne 0 ]]; then
echo 'Script failed correctly. Exiting function.'
return 1
fi
echo 'Should not have gotten here!'
}
envTest
请注意,此代码只计算或者 export
应当将整个脚本段成功; 问题文本和注释似乎表明,如果不需要的话,这是可以接受的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句