|
The Bash shell contains no debugger, nor even any debugging-specific
commands or constructs. Syntax errors or outright typos in the script
generate cryptic error messages that are often of no help in debugging
a non-functional script. Example 3-98. test23, a buggy script #!/bin/bash
a=37
if [$a -gt 27 ]
then
echo $a
fi
exit 0 |
Output from script:
./test23: [37: command not found |
What's wrong with the above script (hint: after the if)? What if the script executes, but does not work as expected? This is the
all too familiar logic error. Example 3-99. test24, another buggy script #!/bin/bash
# This is supposed to delete all filenames
# containing embedded spaces in current directory,
# but doesn't. Why not?
badname=`ls | grep ' '`
# echo "$badname"
rm "$badname"
exit 0 |
To find out what's wrong with Example 3-99, uncomment the
echo "$badname" line. Echo statements are useful for
seeing whether what you expect is actually what you get. Summarizing the symptoms of a buggy script,
It bombs with an error message syntax error, or It runs, but does not work as expected
(logic error) It runs, works as expected, but has nasty side effects
(logic bomb).
Tools for debugging non-working scripts include
echo statements at critical points in the script to trace the variables,
and otherwise give a snapshot of what is going on. using the tee filter to check processes or
data flows at critical points. setting option flags -n -v -x sh -n scriptname checks for syntax errors
without actually running the script. This is the equivalent of
inserting set -n or
set -o noexec into the script. Note that
certain types of syntax errors can slip past this check. sh -v scriptname echoes each command before
executing it. This is the equivalent of inserting set -v or
set -o verbose in the script. sh -x scriptname echoes the result each
command, but in an abbreviated manner. This is the equivalent of
inserting set -x or
set -o xtrace in the script. Inserting set -u or
set -o nounset in the script runs it, but
gives an unbound variable error message
at each attempt to use an undeclared variable. trapping at exit The exit command in a script actually sends a
signal 0, terminating
the process, that is, the script itself. It is often useful to trap
the exit, forcing a "printout" of
variables, for example. The trap must be the
first command in the script.
- trap
Specifies an action on receipt of a signal; also useful for debugging.
Note: A signal is simply
a message sent to a process, either by the kernel or
another process, telling it to take some specified
action (usually to terminate). For example, hitting a
Control-C,
sends a user interrupt, an INT signal, to a running
program.
trap 2 #ignore interrupts (no action specified)
trap 'echo "Control-C disabled."' 2 |
Example 3-100. Trapping at exit #!/bin/bash
trap 'echo Variable Listing --- a = $a b = $b' EXIT
# EXIT is the name of the signal generated upon exit from a script.
a=39
b=36
exit 0
# Note that commenting out the 'exit' command makes no difference,
# since the script exits anyhow after running out of commands. |
Example 3-101. Cleaning up after Control-C #!/bin/bash
# logon.sh
# A quick 'n dirty script to check whether you are on-line yet.
TRUE=1
LOGFILE=/var/log/messages
# Note that $LOGFILE must be readable (chmod 644 /var/log/messages).
TEMPFILE=temp.$$
# Create a "unique" temp file name, using process id of the script.
KEYWORD=address
# At logon, the line "remote IP address xxx.xxx.xxx.xxx" appended to /var/log/messages.
ONLINE=22
USER_INTERRUPT=13
trap 'rm -f $TEMPFILE; exit $USER_INTERRUPT' TERM INT
# Cleans up the temp file if script interrupted by control-c.
echo
while [ $TRUE ] #Endless loop.
do
tail -1 $LOGFILE> $TEMPFILE
# Saves last line of system log file as temp file.
search=`grep $KEYWORD $TEMPFILE`
# Checks for presence of the "IP address" phrase,
# indicating a successful logon.
if [ ! -z "$search" ] # Quotes necessary because of possible spaces.
then
echo "On-line"
rm -f $TEMPFILE # Clean up temp file.
exit $ONLINE
else
echo -n "." # -n option to echo suppresses newline,
# so you get continuous rows of dots.
fi
sleep 1
done
# Note: if you change the KEYWORD variable to "Exit",
# this script can be used while on-line to check for an unexpected logoff.
# Exercise: Change the script, as per the above note,
# and prettify it.
exit 0 |
Note: trap '' SIGNAL (two adjacent
apostrophes) disables SIGNAL for the remainder of the
script. trap SIGNAL restores
the functioning of SIGNAL once more. This is useful to
protect a critical portion of a script from an undesirable
interrupt.
trap '' 2 # Signal 2 is Control-C, now disabled.
command
command
command
trap 2 # Reenables Control-C
|
|