Exit Status

All of the control flow mechanisms we are about to discuss condition their behavior on the exit status of a command. All commands, including compound commands, have an exit status that is well-defined. Fundamentally, simple commands have an exit status based on the utility that is executed (or an error status on failure to execute). All other command constructs derive their exit statuses from the simple commands that they are comprised of. As we introduce each construct, take note of how these exit statuses are defined for each.

Exit Status Semantics

An exit value of zero (0) indicates successful termination, while a non-zero exit value indicates failure. For this reason, zero (0) is logically treated as a true value in shell scripting, while non-zero values are logically treated as false. For example, the while loop construct will execute its body as long as the exit status of the controlling command is zero.

There are two simple utilities–true and false–which exit with values 0 and 1, respectively. Thus, for example, an infinite loop can be written in plain english as while true; do...; done

Exit status parameter

The shell special parameter ? can be used to query the exit status of the most recent foreground command,

$ true
$ echo $?
0
$ false
$ echo $?
1

Familiar Constructs

Let’s look at the exit status of the three constructs we have already discussed previously, simple commands, pipelines, and asynchronous commands:

Simple Commands

The exit status of a simple command is the exit status of the utility that is executed, if a command name is present. If an error occurs before execution, such as an illegal redirection or if the command is not found, the exit status of the simple command is non-zero. If no command name is present, the exit status of a simple command is the exit status of the last command substitution, or zero (0) if no command substitution is present.

Pipelines

In the previous module, we introduced pipelines as a series of one or more commands separated by the | pipe operator. A pipeline can also optionally be preceded by the ! (bang) reserved word (e.g. $ ! echo 'Hello World' | cat).

If the reserved word ! does not precede the pipeline, the exit status of the pipeline is the exit status of the last command in the pipeline. Otherwise, the exit status is the logical NOT of the exit status of the last command. That is, if the last command returns zero, the exit status of the pipeline is one; if the last command returns non-zero, the exit status of the pipeline is zero.

Asynchronous Commands

In the previous module, we covered how the & control operator could be used to run commands as background jobs. Any command can be run in the background, including compound commands, and the exit status of a background command is always set to 0.

Note

The exit status of the entire background command at the time of execution is zero; however, the command which is run in the background will still have an exit status when it completes. This exit status can be queried with the wait builtin utility.