Shell Scripts: Good Error and Usage messages: $0, $#, $*, and 1>&2

Ian! D. Allen – www.idallen.com

Fall 2015 - September to December 2015 - Updated 2019-04-14 18:15 EDT

1 Good Error Messages and Usage MessagesIndexup to index

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.1 Must appear on standard error, not standard output: 1>&2Indexup to index

Error messages must appear on standard error, not standard output.

Error 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).

1.2 Must contain the name of the program from $0Indexup to index

Error messages must contain the name of the program that is issuing the message (from $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!)

1.3 Must state what kind of input was expectedIndexup to index

Error messages must state how many and what kind of input was expected.

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!

1.4 Must display what input the user actually enteredIndexup to index

Error messages must display what input the user actually entered.

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.

1.5 ExampleIndexup to index

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.6 Summary: Four properties of Good Error MessagesIndexup to index

Good Error Messages must:

  1. Appear on standard error, not on standard output: 1>&2
  2. Give the name of the program (script) that is issuing the error: $0
  3. Tell the user exactly what was expected by the program (not “argument”).
  4. Display exactly what was supplied by the user (using $# and $*).

2 The Usage MessageIndexup to index

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.

2.1 Only for Usage ErrorsIndexup to index

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.

Author: 
| Ian! D. Allen, BA, MMath  -  idallen@idallen.ca  -  Ottawa, Ontario, Canada
| Home Page: http://idallen.com/   Contact Improv: http://contactimprov.ca/
| College professor (Free/Libre GNU+Linux) at: http://teaching.idallen.com/
| Defend digital freedom:  http://eff.org/  and have fun:  http://fools.ca/

Plain Text - plain text version of this page in Pandoc Markdown format

Campaign for non-browser-specific HTML   Valid XHTML 1.0 Transitional   Valid CSS!   Creative Commons by nc sa 3.0   Hacker Ideals Emblem   Author Ian! D. Allen