When you execute a Linux command it can either run to completion with no errors or it can encounter some problem which prevents it from fulfilling its task. If you use a command in a shell script, it can be very useful to know which of these events occurred, so that if there is an error then some kind of remedial action can be taken. All the Linux commands are arranged so that they will return a value when they terminate. This value is called the exit status. An exit status of zero means that the command was successful, while any non-zero value means the command was unsuccessful. In the case of a pipeline, the exit status that gets returned is just the exit status of the last (right most) command in the pipeline.
Whenever you run a command or a pipeline, the shell has a special variable called $? which is assigned the value of the returned exit status:
$ cd /zz bash: /zz: No such file or directory $ echo $? 1 $ echo $? 0
In this example, trying to change directory to /zz fails because the directory does not exist. Consequently, displaying the value of $? shows that the exit status from cd was non-zero. Notice that displaying the contents of $? for a second time gives a different result. This is because the variable's value is updated after each command or pipeline is completed, and the second display is actually showing that the first echo command executed successfully.
A shell script can itself return an exit status by using the exit command. You should get into the habit of specifying explicit and appropriate exit status values to be returned by your shell scripts:
$ cat >tryexit exit 55 Ctrl-d $ chmod 700 tryexit $ tryexit $ echo $? 55
The variable $? is just one of several special variables used by bash for various status applications and which are available within a shell script. The main ones are:
This variable holds the exit status returned by the last command to be executed by the shell.
This variable contains the PID of the current shell. This value is very often used for generating unique temporary file names for use within the script (e.g. /tmp/tmp$$).
This holds the number of command line parameters that were passed to the current script. This value corresponds to the number of the $1, $2, etc., variables currently in use.
This variable contains a list of all command line parameters ($1, $2, etc.) that were passed to the current script.
Each of these special variables may only have its value read. Assignment to them is not allowed, except by the shell, which automatically updates them as given in the previous table.