Winter 2017 - January to April 2017 - Updated 2019-04-14 18:15 EDT
System administrators see a lot of errors. That’s part of their job. When you write a script or a program, the better you make your error messages, the easier it is on your sysadmin.
Good shell script error messages must obey these four rules:
1>&2
IndexError messages must not get redirected into output files; they must appear on your terminal so that you know something went wrong. You can use the shell syntax 1>&2
to send to stderr any output normally destined for stdout. See the examples below.
Shell scripts often need to produce their own error messages. Error messages should always be sent to standard error so that they appear on your screen and don’t get redirected into pipes and output files.
Usually 1>&2
is used on output statements, such as echo
, to send the output text to standard error instead of standard output:
echo 1>&2 "$0: Error: expecting one pathname, found $# ($*)"
When error messages appear on standard error, they don’t get redirected into output files:
$ ./myscript.sh >out
./myscript.sh: Error: expecting one pathname, found 0 ()
We use the shell redirection syntax 1>&2
to re-route echo
output normally headed for unit 1 (standard output) to actually appear on unit 2 (standard error).
$0
Index$0
).Do not put the name of the script into the script; use $0 instead.
Scripts get renamed. Never use the actual name of the script in any of the script command lines. Get the name from the $0
variable:
echo 1>&2 "$0: Error: expecting one pathname, found $# ($*)"
(For school assignments, you must use the actual name of the script in your submission comment and in the KEY
line comment, but never in any text that is output by the script. Only in the school comments!)
Do not say only “expecting one argument” or “missing parameter”, since that doesn’t say what kind of argument or parameter is needed. Be explicit about exactly what is expected. Examples: expecting one file name
, or expecting two email addressses
. Avoid using only the vague words “argument” and “parameter” in any error message.
echo 1>&2 "$0: Error: expecting one pathname, found $# ($*)"
Never say just missing argument
or illegal input
or invalid input
or too many
. Always specify exactly what is needed and how many is “too many” or “too few”. Make your error messages useful!
Display both the number of arguments $#
and their values $*
(e.g. found 3 (a b c)
. Here are examples of good error messages:
echo 1>&2 "$0: Expecting 3 file names; found $# ($*)"
echo 1>&2 "$0: Student age '$student_age' is not between $min_age and $max_age"
echo 1>&2 "$0: Modify days '$moddays' must be greater than zero"
echo 1>&2 "$0: File '$file' does not exist; expecting accounting file"
Put quotes around anything entered by a user, otherwise your error messages may be confusing. Compare these example messages without and with quotes around the user input file name:
$ ./total.sh still
./total.sh: File still does not exist; expecting accounting file
Usage: ./total.sh account_file
$ ./total.sh system
./total.sh: File system does not exist; expecting accounting file
Usage: ./total.sh account_file
$ ./total.sh still
./total.sh: File 'still' does not exist; expecting accounting file
Usage: ./total.sh account_file
$ ./total.sh system
./total.sh: File 'system' does not exist; expecting accounting file
Usage: ./total.sh account_file
The quotes make it clearer that still
and system
are user file names, not just words that are part of the error message.
A typicall shell script error message:
echo 1>&2 "$0: Expecting one file name; found $# ($*)"
There are many good properties of the above error message. It gives the user all the information they may need to see what is wrong:
1>&2
$0
is the name used to invoke the script (remember, files can have more than one name so script names shouldn’t be hard-coded into the script)$#
is the number of arguments the user actually gave to the script$*
shows the actual arguments given to the script, put in parentheses so the user can see spaces, etc.Good Error Messages must:
1>&2
$0
After detecting an error in script usage, the usual thing to do is print a Good Error Message explaining the error, followed by a Usage message telling how to use the script, then exit the script with a non-zero return code. Don’t keep processing bad data!
The Usage message gives the syntax for correctly using the script, using man
page syntax to indicate optional and repeated arguments, e.g.:
Usage: ./script.sh [ first_line [ last_line ] ]
Usage: ./script.sh filename...
The name of the script is output using the $0
variable. Do not hard-code the name of a script into any command inside the script.
Do not print a Usage message for errors unrelated to script usage.
If the user of the script used the script correctly, but the script detects an error that is unrelated to correct usage (e.g. no permission, missing file, etc.), then don’t print the Usage message (because the user did use the script correctly).
Only print a Usage message if the script is being used incorrectly.