Arn*_*anc 181

这是上次执行的命令的退出状态.

例如,命令true始终返回状态,0false始终返回以下状态1:

true
echo $? # echoes 0
false
echo $? # echoes 1
Run Code Online (Sandbox Code Playgroud)

从手册:(通过调用man bash你的shell 无法访问)

$?       扩展到最近执行的前台管道的退出状态.

按照惯例,0手段成功的退出状态和非零退货状态意味着失败.详细了解维基百科上的退出状态 .

还有其他特殊变量,您可以在此在线手册中看到:https://www.gnu.org/s/bash/manual/bash.html#Special-Parameters


Sau*_*yan 18

$?返回上次执行的命令的退出值.echo $?在控制台上打印该值.零表示成功执行,而非零值映射到各种失败原因.

因此,当编写脚本时; 我倾向于使用以下语法

if [ $? -eq 0 ]; then
 # do something
else
 # do something else
fi
Run Code Online (Sandbox Code Playgroud)

比较是在等于0或不等于的情况下进行的0.

  • 不,这是一个反模式.任何看起来像`cmd; 如果[$?-eq 0]; 那么`应该重构为`if cmd; then`.`if`(以及shell中的其他流控制语句)的*目的*是运行命令并检查其退出状态. (15认同)
  • 现在这种说法就更错误了。`[ 1 ]` 和 `[ 0 ]` 都是 true;不带运算符的“[”检查参数是否为非空字符串。 (2认同)
  • 我要做`vendor/bin/drush status bootstrap | grep -q $(vendor/bin/drush php-eval 'if (function_exists("t")) echo t("成功");') &> /dev/null;`。如果我必须把它放在一行“if [ ... ]”中,那将是非常不可读的。我计划将该行的输出存储到一个变量中,这样我就可以稍后说“if [ $drupal_installed -eq 0 ]”。 (2认同)
  • @thirdender 正确的解决方案是将复杂的测试封装在 shell 函数中。 (2认同)

小智 9

回声$?- 给出最近执行的命令的退出状态.此EXIT STATUS很可能是一个数字,其中ZERO表示成功,任何NON-ZERO值表示失败

- 这是bash中的一个特殊参数/变量.

$? - 它给出了存储在变量"?"中的值.

BASH中的一些类似的特殊参数是1,2,*,#(通常在echo命令中看作$ 1,$ 2,$*,$#等).

希望这可以帮助....


Ned*_*der 8

它具有命令的最后一个状态代码(退出值).


Cir*_*四事件 6

最小 POSIX C 退出状态示例

要理解$?,首先要理解POSIX定义的进程退出状态的概念。在 Linux 中:

  • 当进程调用exit系统调用时,内核会存储传递给系统调用 (an int) 的值,即使在进程终止后也是如此。

    退出系统调用由exit()ANSI C 函数调用,当您returnmain.

  • 调用退出子进程(Bash)的进程,通常使用fork+ exec,可以通过wait系统调用检索子进程的退出状态

考虑 Bash 代码:

$ false
$ echo $?
1
Run Code Online (Sandbox Code Playgroud)

C“等价物”是:

假.c

#include <stdlib.h> /* exit */

int main(void) {
    exit(1);
}
Run Code Online (Sandbox Code Playgroud)

bash.c

#include <unistd.h> /* execl */
#include <stdlib.h> /* fork */
#include <sys/wait.h> /* wait, WEXITSTATUS */
#include <stdio.h> /* printf */

int main(void) {
    if (fork() == 0) {
        /* Call false. */
        execl("./false", "./false", (char *)NULL);
    }
    int status;
    /* Wait for a child to finish. */
    wait(&status);
    /* Status encodes multiple fields,
     * we need WEXITSTATUS to get the exit status:
     * http://stackoverflow.com/questions/3659616/returning-exit-code-from-child
     **/
    printf("$? = %d\n", WEXITSTATUS(status));
}
Run Code Online (Sandbox Code Playgroud)

编译并运行:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o bash bash.c
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o false false.c
./bash
Run Code Online (Sandbox Code Playgroud)

输出:

$? = 1
Run Code Online (Sandbox Code Playgroud)

在 Bash 中,当您按 Enter 键时,会像上面一样发生 fork + exec + wait,然后 bash 设置$?为分叉进程的退出状态。

注意:对于像 那样的内置命令echo,不需要生成进程,而 Bash 只需设置$?为 0 来模拟外部进程。

标准和文件

POSIX 7 2.5.2“特殊参数” http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02

? 扩展到最近管道的十进制退出状态(请参阅管道)。

man bash “特殊参数”:

shell 对几个参数进行了特殊处理。这些参数只能被引用;不允许分配给他们。[...]

? 扩展到最近执行的前台管道的退出状态。

ANSI C 和 POSIX 然后建议:

  • 0 表示程序成功

  • 其他值:程序以某种方式失败。

    确切的值可以指示失败的类型。

    ANSI C 没有定义任何 vaues 的含义,POSIX 指定大于 125 的值: “POSIX”是什么意思?

Bash 使用退出状态 if

在 Bash 中,我们经常$?隐式地使用退出状态来控制if语句,如下所示:

if true; then
  :
fi
Run Code Online (Sandbox Code Playgroud)

哪里true是一个只返回 0 的程序。

以上相当于:

true
result=$?
if [ $result = 0 ]; then
  :
fi
Run Code Online (Sandbox Code Playgroud)

在:

if [ 1 = 1 ]; then
  :
fi
Run Code Online (Sandbox Code Playgroud)

[只是一个具有奇怪名称的程序(和 Bash 内置的行为类似)1 = 1 ]及其参数,另请参见:Bash 中单方括号和双方括号的区别