我尝试创建一个可以中断脚本执行的函数(由于致命错误):
quit() {
echo -e "[ERROR]" | log
exit 1
}
致电示例:
if [ "$#" -eq 1 ]; then
# Do stuff
else
echo -e "function getValue: wrong parameters" | log
quit
fi
调用函数quit
(日志文件中的echo),但脚本继续运行。我读过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
EDIT2: 切换这些行时它可以正常工作:
var=`foo p1 p2`
var2=`foo p1`
与
var= foo p1 p2
var2= foo p1
任何解释?这是因为子shell吗?
答案 0 :(得分:4)
正如问题的评论部分所述,在子shell中使用exit
只会退出子shell,并且要解决此限制并不容易。幸运的是,退出子shell或甚至同一个shell中的函数不是最好的想法:
解决在没有异常的语言中处理较低级别(如函数或子shell)上的错误的问题的良好模式是返回错误,而不是直接从较低级别终止程序:
foo() {
if [ "$#" -ne 1 ]; then
echo "foo error" | log
return 1
else
echo "res"
# return 0 is the default
fi
}
这允许控制流甚至在出错时返回到最高级别,这通常被认为是一件好事(并且将极其简化调试复杂程序)。您可以使用以下功能:
var=$( foo p1 p2 ) || exit 1
var2=$( foo p1 ) || exit 1
为了清楚起见,如果赋值失败(它不会),则不会输入||
分支,但如果命令替换($( )
)内的命令行返回非 - 零退出代码。
请注意,$( )
应该用于命令替换而不是反引号,请参阅此related question。
答案 1 :(得分:2)
查看脚本的调试显示了问题。 var =`foo p1 p2` 强制在子shell中执行foo
(注意:级别从+
增加到{{1}在下面的调用时)脚本的执行在子shell中继续,直到达到++
。 exit 1
有效地退出返回主脚本的子shell。
exit 1
您可以利用此优势来完成您想要做的事情。怎么样?当$ bash -x exitstuck.sh
+ logfile=./testQuit_log
+ rm ./testQuit_log
++ foo p1 p2 # var=`foo p1 p2` enters subshell '+ -> ++'
++ '[' 2 -ne 1 ']'
++ echo 'foo error'
++ log # log() called
++ read data
++ echo -e 'foo error'
++ tee -a ./testQuit_log
++ quit # quit() called
++ echo quit
++ log
++ read data
++ echo -e quit
++ tee -a ./testQuit_log
++ exit 1 # exit 1 exits subshell, note: '++ -> +'
+ var='foo error
quit'
++ foo p1
++ '[' 1 -ne 1 ']'
++ echo res
+ var2=res
+ log
+ read data
+ echo 'never echo that!'
+ echo -e 'never echo that!'
+ tee -a ./testQuit_log
never echo that!
退出子shell时,它会返回退出代码exit 1
。您可以在主脚本中测试退出代码并按预期退出:
1
再次在调试中运行会显示预期的操作:
var=`foo p1 p2`
if [ $? -eq 1 ]; then
exit
fi
var2=`foo p1`