开发者

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

What does

echo $?

mean in sh开发者_StackOverflowell programming?


This is the exit status of the last executed command.

For example the command true always returns a status of 0 and false always returns a status of 1:

true
echo $? # echoes 0
false
echo $? # echoes 1

From the manual: (acessible by calling man bash in your shell)

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

By convention an exit status of 0 means success, and non-zero return status means failure. Learn more about exit statuses on wikipedia.

There are other special variables like this, as you can see on this online manual: https://www.gnu.org/s/bash/manual/bash.html#Special-Parameters


$? returns the exit value of the last executed command. echo $? prints that value on console. zero implies a successful execution while non-zero values are mapped to various reason for failure.

Hence when scripting; I tend to use the following syntax

if [ $? -eq 0 ]; then
 # do something
else
 # do something else
fi

The comparison is to be done on equals to 0 or not equals 0.

** Update Based on the comment: Ideally, you should not use the above code block for comparison, refer to @tripleee comments and explanation.


echo $? - Gives the EXIT STATUS of the most recently executed command . This EXIT STATUS would most probably be a number with ZERO implying Success and any NON-ZERO value indicating Failure

? - This is one special parameter/variable in bash.

$? - It gives the value stored in the variable "?".

Some similar special parameters in BASH are 1,2,*,# ( Normally seen in echo command as $1 ,$2 , $* , $# , etc., ) .


It has the last status code (exit value) of a command.


Minimal POSIX C exit status example

To understand $?, you must first understand the concept of process exit status which is defined by POSIX. In Linux:

  • when a process calls the exit system call, the kernel stores the value passed to the system call (an int) even after the process dies.

    The exit system call is called by the exit() ANSI C function, and indirectly when you do return from main.

  • the process that called the exiting child process (Bash), often with fork + exec, can retrieve the exit status of the child with the wait system call

Consider the Bash code:

$ false
$ echo $?
1

The C "equivalent" is:

false.c

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

int main(void) {
    exit(1);
}

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));
}

Compile and run:

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

Output:

$? = 1

In Bash, when you hit enter, a fork + exec + wait happens like above, and bash then sets $? to the exit status of the forked process.

Note: for built-in commands like echo, a process need not be spawned, and Bash just sets $? to 0 to simulate an external process.

Standards and documentation

POSIX 7 2.5.2 "Special Parameters" 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 "Special Parameters":

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 and POSIX then recommend that:

  • 0 means the program was successful

  • other values: the program failed somehow.

    The exact value could indicate the type of failure.

    ANSI C does not define the meaning of any vaues, and POSIX specifies values larger than 125: What is the meaning of "POSIX"?

Bash uses exit status for if

In Bash, we often use the exit status $? implicitly to control if statements as in:

if true; then
  :
fi

where true is a program that just returns 0.

The above is equivalent to:

true
result=$?
if [ $result = 0 ]; then
  :
fi

And in:

if [ 1 = 1 ]; then
  :
fi

[ is just an program with a weird name (and Bash built-in that behaves like it), and 1 = 1 ] its arguments, see also: Difference between single and double square brackets in Bash


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

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


See The Bash Manual under 3.4.2 Special Parameters:

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

It is a little hard to find because it is not listed as $? (the variable name is "just" ?). Also see the exit status section, of course ;-)

Happy coding.


Outputs the result of the last executed unix command

0 implies true
1 implies false
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜