考虑以下功能
function current_dir {
set -e
git foobar
echo "I will not print this, because git foobar returned a non-zero exit code"
}
现在,当我获取函数并尝试在我的shell中调用它时,它不仅退出函数,还退出shell本身。
如何避免这种情况?
答案 0 :(得分:5)
如果你不需要在当前shell中执行该函数(例如,它不是设置需要对调用者可见的任何参数值),你可以创建函数的主体子shell,而不是命令组:
current_dir () (
set -e
git foobar
echo "I will not print this, because git foobar returned a non-zero exit code"
)
答案 1 :(得分:4)
据我所知,set -e
将完全按照您的看法执行:只要命令以非零状态退出,就会完全退出shell。
您可以尝试使用trap
或在命令之间使用&&
重新构建函数:
function current_dir {
git foobar && echo "I will not print this, because git foobar returned a non-zero exit code"
}
或(更好的可读性):
function current_dir {
trap 'trap - ERR; return' ERR
git foobar
...other commands...
echo "I will not print this, because a command returned a non-zero exit code"
}
如果您出于某种原因确实需要set -e
,可以使用set +e
临时禁用它,并在关键部分后重新启用它。
答案 2 :(得分:3)
“set -e”用于在命令(管道或子shell命令等)以非零状态退出时立即退出。
默认情况下,BASH会忽略错误并继续解释您的脚本。这可能会导致一个非常糟糕的惊喜,例如:
if ! lss myLock
then touch myLock; echo "No lock, I can do the job"; rm -f myLock
fi
此脚本的结果是:
bash: lss : commande introuvable
No lock, I can do the job
正如您所看到的,BASH在找不到的命令和失败的命令之间没有区别。
“ - e”经常用于确保Shell解释器在发生错误后立即停止(因此我们必须考虑所有错误......)这有助于防止在我们执行错误时出现非常糟糕的问题脚本(想想一个rm -rf“$ v”/ *当你忘了设置v ;-))。为此,我们在shebang中传递“-e”选项。显然,它不是为交互式使用而设计的,我不会想象“set -e”的好用,也不能用“set + e”(但要测试)。
回答您的初步问题。您可以通过应用以下解决方案之一来避免终止shell:
function myF1() {
if git foobar; then
echo "I will not print this, because git foobar returned a non-zero exit code"
fi
}
function myF2() {
git foobar && \
echo "I will not print this, because git foobar returned a non-zero exit code"
}
function myF4() {(
set -e
git foobar
echo "I will not print this, because git foobar returned a non-zero exit code"
)}
在这种情况下,“set -e”将立即退出子shell,但它不会终止调用者: - )
使用陷阱不是一个好主意,因为它会对调用者造成副作用(陷阱是全局定义的)。显然我们可以将陷阱和子shell结合起来,但在你的情况下它并没有用。