Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash脚本在第一次退出时不退出";退出“;使用$(func)调用有问题的函数时调用_Bash_Function_Error Handling - Fatal编程技术网

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中运行。谢谢你指出这一点。