4.8 KiB
Exit Status
- exit code
- return status
Purpose
The exit status is a numeric value that is returned by a program to the
calling program or shell. In C programs, this is represented by the
return value of the main()
function or the value you give to
exit(3)
. The only part of the number that matters are the least
significant 8 bits, which means there are only values from 0 to 255.
In the shell, every operation generates an exit status (return status), even if no program is called. An example for such an operation is a redirection.
The parameter to the
exit
(exit the shell/script)return
(return from a function)
builtin commands serve the purpose of giving the exit status to the calling component.
This - and only this - makes it possible to determinate the success or failure of an operation. For scripting, always set exit codes.
Values
The code is a number between 0 and 255, where the part from 126 to 255 is reserved to be used by the Bash shell directly or for special purposes, like reporting a termination by a signal:
Code | Description |
---|---|
0 | success |
1-255 | failure (in general) |
126 | the requested command (file) can't be executed (but was found) |
127 | command (file) not found |
128 | according to ABS it's used to report an invalid argument to the exit builtin, but I wasn't able to verify that in the source code of Bash (see code 255) |
128+N | the shell was terminated by the signal N (also used like this by various other programs) |
255 | wrong argument to the exit builtin (see code 128) |
The lower codes 0 to 125 are not reserved and may be used for whatever
the program likes to report. A value of 0 means successful
termination, a value not 0 means unsuccessful termination. This
behavior (== 0, != 0) is also what Bash reacts on in some code flow
control statements like if
or while
.
Portability
Tables of shell behavior involving non-portable side-effects or common
bugs with exit statuses. Note heirloom doesn't support pipeline
negation (! pipeline
).
Misc
test | bash 4.2.45 | bash (POSIX) | zsh 5.0.2 (emulate ksh) | ksh93 93v- 2013-03-18 | mksh R44 2013/02/24 | posh 0.11 | dash 0.5.7.3 | busybox 1.2.1 | heirloom 050706 |
---|---|---|---|---|---|---|---|---|---|
:; : `false` `echo $? >&2` |
1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
false; eval; echo $? |
0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
x=`false` eval echo $? |
1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
eval echo $? <&0`false` |
1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
while :; do ! break; done; echo $? |
1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | - |
false; : |
echo $? discussion |
1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 |
(exit 2); for x in "`exit 3`"; do echo $?; done |
3 | 3 | 3 | 3 | 2 | 2 | 0 | 0 | 3 |
functions
Measuring side-effects during the function call, during return, and transparency of the return builtin.
test | bash | bash (POSIX) |
zsh (emulate ksh) |
ksh93 | mksh | posh | dash | busybox | heirloom |
---|---|---|---|---|---|---|---|---|---|
f() { echo $?; }; :; f `false` |
1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
f() { return; }; false; f; echo $? |
1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 |
f() { return |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
f() { ! return; }; f; echo $? |
0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | - |
f() { ! return; }; false; f; echo $? |
1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | - |
f() { return; }; x=`false` f; echo $? |
1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
f() { return; }; f <&0`false`; echo $? |
1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
f() { x=`false` return; }; f; echo $? |
1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
f() { return <&0`false`; }; f; echo $? |
1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
f() { x=`false` return <&0`false`; }; f; echo $? |
1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |
case..esac
Statuses measured within the command and after, with matching and non-matching patterns.
test | bash | bash (POSIX) |
zsh (emulate ksh) |
ksh93 | mksh | posh | dash | busybox | heirloom |
---|---|---|---|---|---|---|---|---|---|
(exit 2); case x in x) echo $?;; esac |
2 | 2 | 0 | 2 | 2 | 2 | 0 | 0 | 2 |
(exit 2); case `exit 3`x in x) echo $?;; esac |
3 | 3 | 0 | 3 | 2 | 2 | 0 | 0 | 3 |
(exit 2); case x in `exit 4`x) echo $?;; esac |
4 | 4 | 4 | 4 | 2 | 2 | 0 | 0 | 4 |
(exit 2); case `exit 3`x in `exit 4`x) echo $?;; esac |
4 | 4 | 4 | 4 | 2 | 2 | 0 | 0 | 4 |
(exit 2); case x in x);; esac; echo $? |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 |
(exit 2); case x in "");; esac; echo $? |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 |
(exit 2); case `exit 3`x in x);; esac; echo $? |
0 | 0 | 0 | 3 | 0 | 0 | 0 | 0 | 3 |
(exit 2); case `exit 3`x in "");; esac; echo $? |
0 | 0 | 0 | 3 | 0 | 0 | 0 | 0 | 3 |
(exit 2); case x in `exit 4`x);; esac; echo $? |
0 | 0 | 0 | 4 | 0 | 0 | 0 | 0 | 4 |
(exit 2); case x in `exit 4`);; esac; echo $? |
0 | 0 | 4 | 4 | 0 | 0 | 0 | 0 | 4 |
(exit 2); case `exit 3`x in `exit 4`);; esac; echo $? |
0 | 0 | 4 | 4 | 0 | 0 | 0 | 0 | 4 |
(exit 2); case `exit 3`x in `exit 4`x);; esac; echo $? |
0 | 0 | 0 | 4 | 0 | 0 | 0 | 0 | 4 |