31

I saw the code written somewhere online, and I wanted to know what exactly does "$?" do/give us. Googling did not help.

Here's the code I saw it in:

#!/bin/sh

ping -c 2 localhost
if [ $? != 0 ] ; then
    echo "Couldn't ping localhost, weird"
    fi

ping -c 2 veryweirdhostname.noend 
if [ $? != 0 ] ; then
    echo "Surprise, Couldn't ping a very weird hostname.."
    fi

echo "The pid of this process is $$"

Taken from: http://efod.se/writings/linuxbook/html/shell-scripts.html

Khushman Patel
  • 1,066
  • 2
  • 13
  • 23
  • 5
    http://stackoverflow.com/questions/90418/exit-shell-script-based-on-process-exit-code It gives the exit status of the last executed command – Rahul Sep 12 '11 at 03:56
  • $? is the return code from the last command – Ray Tayek Sep 12 '11 at 03:57
  • 2
    And as always, the use of `cmd; if [ $? != 0 ]; then stuff; fi` is an antipattern which is more elegantly and idiomatically written `if ! cmd ; then stuff; fi` (provided you do not need the value of `$?` in `stuff`, which which case `if cmd; then : nothing; else stuff with $?; fi`) or even `cmd || stuff` – tripleee Aug 23 '12 at 07:09

5 Answers5

42

$? is a variable holding the return value of the last command you ran.

Example C program (example.c):

int main() { return 1; }

Example Bash:

gcc -o example example.c
./example
echo $? # prints 1
Brendan Long
  • 53,280
  • 21
  • 146
  • 188
  • 3
    But only if that return value is an 8-bit integer. See [Jens' answer](http://stackoverflow.com/a/13823424/418413) and http://stackoverflow.com/a/2726480/418413 for more detail. – kojiro Mar 01 '14 at 02:34
16

Most of the answers are missing a bit of detail. A definitive answer is found in the POSIX standard for the shell, in the section on special parameters:

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

Don't be surprised by the word pipeline, because even a simple command such as ls is grammatically a pipeline consisting of a single command. But then, what is $? for a multi-command pipeline? It's the exit status of the last command in the pipeline.

And what about pipelines executing in the background, like grep foo bigfile|head -n 10 > result &?

Their exit status can be retrieved through wait once the pipeline's last command has finished. The background process pid is available as $!, and $? only reports whether the background command was correctly started.

Another detail worth mentioning is that the exit status is usually in the range 0 through 255, with 128 to 255 indicating the process exited due to a signal. Returning other values from a C program is likely to not be reflected accurately in $?.

Henk Langeveld
  • 8,088
  • 1
  • 43
  • 57
Jens
  • 69,818
  • 15
  • 125
  • 179
  • 1
    +1 This is a great, comprehensive answer. The only thing I would say is in the last sentence it's pretty clear what will happen when a C program returns a value besides 0-255: `$?` will be the low-order 8 bits of the implicit integer cast of the return value. While few programs are silly enough to exit with a double or a char, several rely on this modulo-256 behavior when they return negative values. – kojiro Mar 01 '14 at 02:26
  • (On the other hand, when invoking the `exit` command in a POSIX shell, giving it an argument other than 0-255 [is undefined](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_21_03).) – kojiro Mar 01 '14 at 02:31
  • @kojiro What's an *implicit cast*? Casts are always explicit in C. Did you perhaps mean *arithmetic conversion* or *masking*? – Jens Mar 01 '14 at 08:33
  • Yes, I abused the word *cast*. I meant *implicit conversion*. – kojiro Mar 01 '14 at 16:54
8

It's the return code from the most recently executed command.

By convention 0 is a successful exit and non-zero indicates some kind of error.

evil otto
  • 10,348
  • 25
  • 38
1

This special variable shows the exit status of the last command that was run in a script or command-line. For example, in a command-line, the user could type

 who; echo $?

The output would then be

 user  tty7         2014-07-13 19:47
 0

This shows the output of who and the exit status of the command. A script would be the same.

 #!/bin/bash
 who
 echo $?

Output: 0

0

the other answers cover bash pretty well, but you don't specify a shell in your question. In csh (and tcsh) $? can be used to query the existence of variables, e.g.

if $?my_var then
    echo my_var exists
endif
Community
  • 1
  • 1
craq
  • 1,441
  • 2
  • 20
  • 39