我尝试创建一个可以中断脚本执行的函数(由于致命错误):
quit() {
echo -e "[ERROR]" | log
exit 1
}
Run Code Online (Sandbox Code Playgroud)
调用示例:
if [ "$#" -eq 1 ]; then
# Do stuff
else
echo -e "function getValue: wrong parameters" | log
quit
fi
Run Code Online (Sandbox Code Playgroud)
函数quit被调用(在日志文件中回显)但脚本继续运行。我读过exit只终止子shell(这是真的吗?)这意味着它终止了quit函数而不是整个脚本。
目前,我不喜欢在quit方法中使用返回码,因为它意味着很多代码重构。
有没有办法从quit函数中停止脚本?
编辑: 出现错误的情况的完整示例:
#!/bin/bash
logfile="./testQuit_log"
quit() {
echo "quit" | log
exit 1
}
log() {
read data
echo -e "$data" | tee -a "$logfile"
}
foo() {
if [ "$#" -ne 1 ]; then
echo "foo error" | log
quit
fi
echo "res"
}
rm $logfile
var=`foo p1 p2`
var2=`foo p1`
echo "never echo that!" | log
Run Code Online (Sandbox Code Playgroud)
EDIT2: 当我切换这些行时它可以正常工作:
var=`foo p1 p2`
var2=`foo p1`
Run Code Online (Sandbox Code Playgroud)
和
var= foo p1 p2
var2= foo p1
Run Code Online (Sandbox Code Playgroud)
有什么解释吗?那是因为子外壳吗?
正如问题的评论部分所概述的那样,exit在子shell中使用只会退出子shell,并且不容易解决这个限制。幸运的是,从子 shell 甚至同一个 shell 中的函数退出无论如何都不是最好的主意:
在语言中解决在较低级别(如函数或子shell)处理错误的问题的一个好模式是返回错误而不是直接从较低级别终止程序:
foo() {
if [ "$#" -ne 1 ]; then
echo "foo error" | log
return 1
else
echo "res"
# return 0 is the default
fi
}
Run Code Online (Sandbox Code Playgroud)
这允许控制流即使出现错误也能返回到最高级别,这通常被认为是一件好事(并且将难以置信地简化复杂程序的调试)。您可以像这样使用您的功能:
var=$( foo p1 p2 ) || exit 1
var2=$( foo p1 ) || exit 1
Run Code Online (Sandbox Code Playgroud)
需要明确的||是,如果分配失败(不会),则不会进入分支,但如果命令替换 ( $( ))内的命令行返回非零退出代码。
请注意,$( )应该用于命令替换而不是反引号,请参阅此相关问题。