The exit status of a process is encoded as a value between 0 and 255, so that's all you can use as an exit code. If you pass a value outside that range, most shells use the remainder modulo 256. Some shells allow a wider range of integer values for functions.
The only rule for exit codes is that 0 means success and any other value means failure. This rule goes beyond unix: it's also a common convention on other operating systems (including DOS, Windows, and many embedded systems that have a notion of exit code, but VMS does things differently). In unix systems, it's baked into the shell's boolean constructs (if
, while
, &&
, ||
, !
, set -e
, …), into make
, and followed by all the standard utilities. In POSIX C programs,EXIT_SUCCESS
is 0 and EXIT_FAILURE
is some non-zero value (usually 1).
There is no rule (de facto or de jure) regarding the choice of exit codes for failure. Only a few POSIX utilities mandate specific failure status codes:
- The
!
shell operator returns 1 if its operand returns 0. The &&
and ||
operator pass the status from the last command.
cmp
and diff
return 1 for different files and ≥2 for error conditions.
expr
returns 1
if the expression evaluates to zero or null, 2 for an invalid expression, and ≥3 for other errors.
grep
returns 1 for “not found” and ≥2 for error conditions. Many search commands follow this (but not find
, which returns 0 if no file matches).
mesg
returns 0 for yes, 1 for no, and ≥2 for error.
patch
returns 1 if a hunk was rejected and ≥2 for other errors.
sort -c
returns 1 if the file data isn't sorted and ≥2 for errors.
compress
and localedef
define some small values for specific errors.
There is a common, but not universal idea that larger values mean worse failures. For commands that test a boolean condition such as grep
(is this pattern present?) and diff
(are these files identical?), 1 means “no” and higher values indicate an error. In addition, values from 126 up are rarely used, as they are baked into the shell (and POSIX commands command
, env
, nice
, nohup
and time
):
- 126 and 127 indicate a failure to invoke an external command;
- values above 128 in
$?
indicate a command that was terminated by a signal.
/usr/include/sysexits.h
lists some values with their meanings, but it's from sendmail and I've never seen it outside programs that are unrelated to email delivery.
In summary, return 0 for success, and either 1 or 2 for failure. If you need to distinguish between failure cases, start at 1 and increase the value for worse failures.