关于脚本:$的含义? shell脚本中的(美元问号)

Meaning of $? (dollar question mark) in shell scripts

是什么

1
echo $?

shell编程意味着什么?


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

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

1
2
3
4
true
echo $? # echoes 0
false
echo $? # echoes 1

从手册:(通过在shell中调用man bash访问)

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

按照惯例,退出状态0表示成功,非零返回状态表示失败。详细了解维基百科上的退出状态。

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


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

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

1
2
3
4
5
if [ $? -eq 0 ]; then
 # do something
else
 # do something else
fi

比较将在等于0或不等于0时进行。

**更新根据评论:理想情况下,您不应使用上述代码块进行比较,请参阅@tripleee评论和解释。


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

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

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

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


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


来自http://www.gnu.org/s/bash/manual/bash.html#Special-Parameters

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

最小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中单方括号和双方括号之间的区别


输出上次执行的unix命令的结果

1
2
0 implies true
1 implies false

参见3.4.2特殊参数下的Bash手册:

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

它有点难以找到,因为它没有列为$?(变量名称是"just"?)。当然也参见退出状态部分;-)

快乐的编码。