Bash脚本在第一次退出时不退出";退出“;使用$(func)调用有问题的函数时调用
很抱歉,我不能为发生的事情给出一个清晰的标题,但这里是简化的问题代码Bash脚本在第一次退出时不退出";退出“;使用$(func)调用有问题的函数时调用,bash,function,error-handling,Bash,Function,Error Handling,很抱歉,我不能为发生的事情给出一个清晰的标题,但这里是简化的问题代码 #!/bin/bash # get the absolute path of .conf directory get_conf_dir() { local path=$(some_command) || { echo "please install some_command first."; exit 100; } echo "$path" } # process the configuration rea
#!/bin/bash
# get the absolute path of .conf directory
get_conf_dir() {
local path=$(some_command) || { echo "please install some_command first."; exit 100; }
echo "$path"
}
# process the configuration
read_conf() {
local conf_path="$(get_conf_dir)/foo.conf"
[ -r "$conf_path" ] || { echo "conf file not found"; exit 200; }
# more code ...
}
read_conf
所以基本上,这里我要做的是,在bash脚本中读取一个简单的配置文件,我在错误处理方面遇到了一些麻烦
some_命令是一个来自第三方库(即来自coreutils的greadlink)的命令,用于获取路径
当运行上面的代码时,我希望它输出“command not found”,因为第一个错误发生在这里,但实际上它总是打印“conf file not found”
我对这种行为感到非常困惑,我认为BASH可能有意处理这样的事情,但我不知道为什么。最重要的是,如何修复它
如果您有任何想法,我们将不胜感激。您是否看到您的
请先安装一些命令消息?是否在本地conf\u path=“$(get\u conf\u dir)/foo.conf”
行的$conf\u path
中?您是否有$conf_path
值请先安装一些\u命令/foo.conf
?然后哪个测试失败了-r
不,你没有。(但是可以在退出200
块中随意回显$conf_path
的值来确认这一事实。)(通常,错误消息应该发送到标准错误,而不是标准输出。因此它们应该是回显“…”2>&1
。这样,它们就不会被正常的命令替换捕获。)
之所以不这样做,是因为退出100
块从未发生过
您也可以通过脚本顶部的set-x
看到这一点。去试试看
明白我的意思吗
它没有发生的原因是some\u命令的失败返回被local path=$(some\u命令)
赋值语句吞没
尝试运行以下命令:
f() { local a=$(false); echo "Returned: $?"; }; f
您是否希望看到返回:1
?你可能会,但你不会看到
您将看到返回:0
现在,请尝试以下任一版本:
f() { a=$(false); echo "Returned: $?"; }; f
f() { local a; a=$(false); echo "Returned: $?"; }; f
首先获得您期望的输出
对<代码>本地
和导出
和声明
和排版
是它们自己的语句。它们有自己的返回值。它们忽略(并替换)在其上下文中执行的命令的返回值
问题的解决方案是拆分本地路径
和path=$(some_命令)
语句
捕获此错误(以及许多其他常见错误)。你应该让它成为你的朋友
除上述内容外(如果您已经成功地完成了这一步),即使有到目前为止提到的更改,您的exit 100
也不会退出主脚本,因为它只会退出由赋值中的命令替换生成的子shell
如果希望退出脚本的exit 100
,则需要注意并重新退出脚本(检查get_conf_dir
在conf_path
赋值后出现的故障,并使用之前的退出代码退出)或者删除get_conf_dir
函数本身,只需在read_conf
中内联执行该操作,也许值得更明确地说明消息的问题请先安装一些_命令
发送到stdout而不是stderr。还有一个事实,即get_conf_dir
中的退出
只从$(get_conf_dir)
@rici中的子shell退出,这是绝对正确的。我因为那里的树木而失去了森林。我解决了你的一些问题。并使您能够正确处理exit 100
故障,因为它确实发生了。但是,正如rici指出的那样,您无法在那里单独退出脚本。它是在一个子壳里。请参阅更新答案的最后一段。谢谢@Etan Reisner&@rici,非常有趣且信息丰富。我经常使用shellcheck,但我没有对详细信息给予足够的关注,但现在我会。是的,我从未注意到$(get\u conf\u dir)
在子shell中运行。谢谢你指出这一点。