什么是$? shell脚本中的(美元问号)变量?

What is the $? (dollar question mark) variable in shell scripting?

本问题已经有最佳答案,请猛点这里访问。

我正在尝试学习shell脚本,我需要了解其他人的代码。 什么是$?变量hold? 我不能谷歌搜索答案,因为他们阻止标点字符。


$?用于查找上次执行的命令的返回值。
在shell中尝试以下内容:

1
2
ls somefile
echo $?

如果somefile存在(无论它是文件还是目录),您将获得ls命令抛出的返回值,该值应为0(默认为"success"返回值)。如果它不存在,你应该得到一个除0之外的数字。确切的数字取决于程序。

对于许多程序,您可以在相应的手册页中找到数字及其含义。这些通常被描述为"退出状态",并且可能有自己的部分。


这是最后执行的函数/程序/命令的退出状态。参考:

  • 退出/退出状态@ tldp.org
  • 特殊壳变量@tldp.org
  • 特殊字符@ tlpd.org


先前执行的进程的返回值。

10.4 Getting the return value of a program

In bash, the return value of a program is stored in a special variable
called $?.

This illustrates how to capture the return value of a program, I
assume that the directory dada does not exist. (This was also
suggested by mike)

1
2
3
4
5
        #!/bin/bash
        cd /dada &> /dev/null
        echo rv: $?
        cd $(pwd) &> /dev/null
        echo rv: $?

有关详细信息,请参阅Bash编程手册。


最小C的例子

要理解$?,您必须首先了解流程退出状态的概念。

在Linux中:

  • 当进程调用exit系统调用时,即使进程终止,内核也会存储传递给系统调用的值。

    退出系统调用由exit() ANSI C函数调用,并在从main执行return时间接调用。

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

考虑Bash代码:

1
2
3
$ false
$ echo $?
1

C"等价物"是:

false.c:

1
2
3
4
5
#include <stdlib.h> /* exit */

int main() {
    exit(1);
}

bash.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <unistd.h> /* execl */
#include <stdlib.h> /* fork */
#include <sys/wait.h> /* wait, WEXITSTATUS */
#include <stdio.h> /* printf */

int main() {
    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
", WEXITSTATUS(status));
}

在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:

? Expands to the decimal exit status of the most recent pipeline (see Pipelines).

man bash"特殊参数":

The shell treats several parameters specially. These parameters may only be referenced; assignment to them is not allowed. [...]

? Expands to the exit status of the most recently executed foreground pipeline.

ANSI C和POSIX然后建议:

  • 0表示该计划成功

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

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

    ANSI C没有定义任何vaues的含义,POSIX指定大于125的值:我从未真正理解:什么是POSIX?

Bash使用if的退出状态

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

1
2
3
if true; then
  :
fi

其中true是一个只返回0的程序。

以上相当于:

1
2
3
4
5
true
result=$?
if [ $result = 0 ]; then
  :
fi

并在:

1
2
3
if [ 1 = 1 ]; then
  :
fi

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


$?是上次执行的命令的结果(退出代码)。


$?是命令的退出状态,因此您可以菊花链式连接一系列命令。

1
command1 && command2 && command3

如果command1's $?产生success (0)command2将运行,如果$? command2将产生successcommand3将执行


它是上次执行的命令的返回错误代码。 0 =成功


如果在使用set -e的情况下退出脚本,它非常适合调试。例如,在导致它退出的命令之后放入echo $?并查看返回的错误值。


运行最后一个命令的退出代码。