【问题标题】:Bash $? Variable Assignement重击美元?变量赋值
【发布时间】:2017-06-16 10:28:43
【问题描述】:

我刚开始学习 bash,正在阅读有关 the $? variable 的信息。据我了解,$? 分配给最后执行的命令的退出状态。

例如

$ false; echo $?

将产生 1,并且

$ false; :; echo $?

将产生 0

当我将这些与 if/for 块结合使用时,事情会变得更加复杂。手册页内容如下:

for 名称 [in 单词 ...] ; do 命令; done

为列表中的每个成员执行命令。

for 循环为每个成员执行一系列命令 物品清单。如果in WORDS ...; 不存在,则in "$@" 存在 假定。对于 WORDS 中的每个元素,NAME 被设置为该元素,并且 COMMANDS 被执行。

退出状态:

返回最后执行的命令的状态。

这意味着:

$ false; for i in 1 2 3; do false; done; echo $?

将产生 1,因为最后执行的命令为假。但是

$ false; for i in; do false; done; echo $?

$ false; if false; then :; fi; echo $?

尽管 false 是最后执行的命令,但仍会产生 0。

我的猜测是$? 变量在进入 for/if 块时设置为 0。我错过了什么吗?

【问题讨论】:

    标签: bash exitstatus


    【解决方案1】:

    根据bash's manual

    if列表then 列表 ; [elif列表then 列表 ; ] ... [ else 列表 ; ]fi

    iflist 被执行。如果其退出状态为零,则执行thenlist。否则,每个eliflist 都会在 转,如果其退出状态为零,则执行相应的thenlist,命令完成。否则,elselist 会被执行,如果存在的话。 退出状态 (整个if ... fi块)是最后一个命令的退出状态 (在then , elifelse 块)执行,如果没有条件测试为真,则为零。

    【讨论】:

    • 太棒了!这很有意义。您能否提供所引用段落的链接?
    • 没有找到来自GNU's site 的手册页。链接到切特的页面。只需更新答案。
    【解决方案2】:

    是的,在 if ..;for ..;while ..; 语句之后退出状态重置为 0。

    要明确,这并不意味着在fi;done; 之后,因为退出状态是最后一个命令退出状态。

    编辑:if/elifthen 之间的命令不会影响复合语句的退出状态,而在 then/elseelif/fi 之间执行的最新命令设置退出复合语句的状态。

    在函数调用之后;退出状态将是return 返回的值或最后一个命令的退出状态。

    带有选项set -eset -o errexit; shell 在退出状态为 0 的命令后退出,除非后面跟着 || 或在 if ..; 语句内。

    必须在命令退出后检查退出状态,可以使用逻辑运算符&&||

    # to fail fast the process can't continue
    simple_command || {
        echo "failed .."
        exit 1
    }
    

    错误处理类似于异常,要问的问题是命令失败后进程如何继续?

    在管道命令中,退出状态是最后一个命令的退出状态,set -o pipefail 除外:退出状态将是管道中最新命令的退出状态,退出状态为 0。

    【讨论】:

    • 需要明确的是,复合语句不会重置退出状态。如果复合语句未执行任何命令,则退出状态定义为 0。
    • @chepner,感谢您的澄清,if list; while list; until list; 内部失败的命令不会影响退出状态
    • else关键字之后echo $?;给出了最后一个ifelif命令的退出状态:if (exit 2); then :; elif (exit 3); then :; else echo $?; fi;但是当没有else语句状态为0时:if (exit 2); then :; elif (exit 3); then :; fi;echo $?
    • 是的,因为没有一个测试条件返回 true。我认为要强调的是复合语句本身(而不是在内部执行的命令)不会影响$?的值,除非在非常特定的角落案例,
    【解决方案3】:

    命令$ false; for i in; do false; done; echo $? 给出for loop 的退出状态。因为它没有错误地退出 for 循环,所以$? 为 0。 这是一个类似的问题,可能会有所帮助。 How to get the exit status a loop in bash

    【讨论】:

    • 更准确地说,循环的退出状态是在主体中执行的最后一个命令的退出状态,除非循环从不执行其主体(如本例中,for i in; do 有一个空要迭代的列表),在这种情况下,退出状态定义为 0。
    猜你喜欢
    • 2017-07-01
    • 2013-09-13
    • 1970-01-01
    • 2017-06-20
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多