< Previous | Contents | Next >
Defensive Programming
It is important to verify assumptions when programming. This means a careful evaluation of the exit status of programs and commands that are used by a script. Here is an exam- ple, based on a true story. An unfortunate system administrator wrote a script to perform a maintenance task on an important server. The script contained the following two lines of code:
cd $dir_name rm *
cd $dir_name rm *
There is nothing intrinsically wrong with these two lines, as long as the directory named in the variable, dir_name, exists. But what happens if it does not? In that case, the cd command fails and the script continues to the next line and deletes the files in the current working directory. Not the desired outcome at all! The hapless administrator destroyed an important part of the server because of this design decision.
Let’s look at some ways this design could be improved. First, it might be wise to make the execution of rm contingent on the success of cd:
cd $dir_name && rm *
cd $dir_name && rm *
This way, if the cd command fails, the rm command is not carried out. This is better, but still leaves open the possibility that the variable, dir_name, is unset or empty, which would result in the files in the user’s home directory being deleted. This could also be avoided by checking to see that dir_name actually contains the name of an existing di- rectory:
[[ -d $dir_name ]] && cd $dir_name && rm *
[[ -d $dir_name ]] && cd $dir_name && rm *
Often, it is best to include logic to terminate the script and report an error when an situa- tion such as the one above occurs:
# Delete files in directory $dir_name if [[ ! -d "$dir_name" ]]; then
echo "No such directory: '$dir_name'" >&2 exit 1
fi
if ! cd $dir_name; then
echo "Cannot cd to '$dir_name'" >&2 exit 1
fi
if ! rm *; then
echo "File deletion failed. Check results" >&2 exit 1
fi
# Delete files in directory $dir_name if [[ ! -d "$dir_name" ]]; then
echo "No such directory: '$dir_name'" >&2 exit 1
fi
if ! cd $dir_name; then
echo "Cannot cd to '$dir_name'" >&2 exit 1
fi
if ! rm *; then
echo "File deletion failed. Check results" >&2 exit 1
fi
Here, we check both the name, to see that it is that of an existing directory, and the suc-
Logical Errors
cess of the cd command. If either fails, a descriptive error message is sent to standard er- ror and the script terminates with an exit status of one to indicate a failure.