Whenever you run a command in a Linux terminal, a numeric exit code is generated – even if you see no sign of it. The code reports the success or failure of the command. And, if the command fails, it provides a value that hints at the problem. If the exit code is 0, all is well. You will just see the normal output from the command you ran. Otherwise, you should see some type of error reported – like “permission denied” or “command not found”.
If you want to display the numeric exit code, you can use the echo $? command as shown in the examples below.
$ echo Linux is wonderful
Linux is wonderful
$ echo $?
0
$ cat nosuchfile
cat: nosuchfile: No such file or directory
$ echo $?
1
$ ls /root
ls: cannot open directory '/root': Permission denied
$ echo $?
2
Notice that the first command ran successfully (exit code of 0). The other two commands failed (exit codes of 1 and 2), but with different problems, thus different exit codes. The commands below result in some other exit codes – 126 and 127 due to even different problems.
$ guess
-bash: ./guess: Permission denied
$ echo $?
126
$ findme
bash: findme: command not found...
$ echo $?
127
The exit code 126, for example, means that an issued command could not be executed. An exit code of 127 means the command cannot be found. This might be because the file doesn’t exist or simply because its location is not on your search path.
For commands run on the command line, the error messages themselves are enough to let you know what to do next. For scripts, things can be a little different. The script below, for example, runs a test to determine if the year provided is in the expected range. If not, it issues both an error message and an exit code. The exit code is of little value unless some other process is checking on whether the script ran successfully.
#!/bin/bash
# year out of range?
if [ $year -lt 1901 -o $year -gt `date +%Y` ]; then
echo Year "$year" is out of range
exit 1
fi
Any exit code other than 0 is recognized as an indication that a script (or a command on the command line) failed in some way. To verify the successful completion of one script from another script, one can use a simple if statement like this:
#!/bin/bash
checkParms
if [ $? != 0 ]; then
echo Exiting: checkParms failed
exit 1
fi
Keep in mind that the exit code when a script ends depends on the last command that is run. The script below would end with an exit code of 0 if the exit command weren’t included since the if/then command doesn’t generate any errors.
#!/bin/bash
touch /tmp/log 2> /dev/null
if [ $? -eq 0 ]
then
echo "File successfully created"
else
echo "Could not create file"
exit 1
fi
Exit code numeric range
The range of values for exit codes runs from 0 to 255. If you issue an “exit 256” command in a script and then check the exit status, you’ll notice that it’s equal to 0! Since the exit code is only going to occupy a single byte, you can think of it as a modulo 256. “Exit 258”, similarly, will leave you with an exit code of 2.
Other special exit codes include 2 (meant to indicate the misuse of a shell builtin), 127 (command not found), 128 (invalid exit code), a whole bunch of exit codes above 128 (128 + a signal for fatal errors) and 130 (control C fatal error). Exit code 1, on the other hand, is a catchall for various errors. If you want to define exit codes to indicate various problems in your own scripts, you’re probably better off using codes between 3 and 125 or, as has been suggested by some contributors to the furtherance of good return code usage, 64 to 113. In either case, you have a wide range of possible return codes at your disposal. Standardizing on a set that suits your needs might streamline your coding a bit.
Here’s a list of exit codes and the types of errors they represent:
- 0: Success. The command or script executed without any error.
- 1: General error. The command or script failed for some unspecified reason (e.g., no such file).
- 2: This indicates misuse of a shell builtin, such as passing an invalid option.
- 126: Not executable
- 127: Command not found
- 128: Invalid argument to exit
- 128+N: Fatal error signal N. The command or script was terminated by a signal N.
- 130: Command terminated with ^C
- 255: Exit status out of range. The command or script tried to exit with a value greater than 255.
Wrap-up
Poorly written scripts may perform some action on behalf of the person running the script and then blithely continue on without ever checking whether the action taken was successful. For example, a script might echo issue a sequence of “installing …” messages without ever checking whether the various packages that the script was intended to install were available for installing or whether the installations completed successfully. Others exit with a non-zero status code whenever something goes wrong, but then ignore the resultant status code when one script calls another. In fact, I have seen some scripts which issue “successfully installed” messages in spite of the fact that the software installation was anything but successful.
Remember to like our facebook and our twitter @WindowsMode for a chance to win a free Surface Pro every month!