15.5. Tracing with Shell Options and the set Command
15.5.1 Debugging Bourne Shell Scripts
Bourne Shell Debugging Options
By using the –n option to the sh command, you can check the sytnax of your scripts without really executing any of the commands. If there is a syntax error in the script, the shell will report the error. If there are no errors, nothing is displayed.
The most commonly used method for debugging scripts is to use the set command with the –x option (set –x), or to use the –x option as an argument to the sh command (sh –x) followed by the script name. See Table 15.7 for a list of debugging options. These options allow an execution trace of your script. Each command from the script is displayed after substitution has been performed, and then the command is executed. When a line from your script is displayed, it is preceded with a plus (+) sign.
Table 15.7. Bourne Shell Debugging OptionsCommand | Option | What It Does |
---|
sh –x scriptname | Echo option | Displays each line of script after variable substitutions and before execution. | sh –v scriptname | Verbose option | Displays each line of script before execution, just as you typed it. | sh –n scriptname | Noexec option | Interprets but does not execute commands. | set –u | Unbound variables | Flags variables that have not been set. | set –x | Turns on echo | Traces execution in a script. | set +x | Turns off echo | Turns off tracing. |
With the verbose option (set –v) turned on, or by invoking the Bourne shell with the –v option (sh –v), each line of the script will be displayed just as it was typed in the script, and then executed.
The set command allows you to turn echoing on or off in a script in order to debug a portion of the script, not the whole program.
FORMAT
set -x # turns echoing on
<program statements go here>
set +x # turns echoing off
Example 15.22.
(The Script)
$ cat todebug
#!/bin/sh
1 # Scriptname: todebug
name="Joe Blow"
if [ "$name" = "Joe Blow" ]
then
echo "Hi $name"
fi
num=1
while [ $num -lt 5 ]
do
num=`expr $num + 1`
done
echo The grand total is $num
(The Output)
2 $ sh –x todebug
+ name=Joe Blow
+ [ Joe Blow = Joe Blow ]
+ echo Hi Joe Blow
Hi Joe Blow
num=1
+ [ 1 -lt 5 ]
+ expr 1 + 1
num=2
+ [ 2 -lt 5 ]
+ expr 2 + 1
num=3
+ [ 3 -lt 5 ]
+ expr 3 + 1
num=4
+ [ 4 -lt 5 ]
+ expr 4 + 1
num=5
+ [ 5 -lt 5 ]
+ echo The grand total is 5
The grand total is 5
EXPLANATION
The script is called todebug. You can watch the script run with the –x switch turned on. Each iteration of the loop is displayed and the values of variables are printed as they are set and when they change. The sh command starts the Bourne shell with the –x option. Echoing is turned on. Each line of the script will be displayed to the screen prepended with a plus sign (+). Variable substitution is performed before the line is displayed. The result of the execution of the command appears after the line has been displayed.
15.5.2 Debugging C/TC Shell Scripts
C shell scripts often fail because of some simple syntax error or logic error. Options to the csh command are provided to help you debug your programs. See Table 15.8.
Table 15.8. echo (–x) and verbose (–v)As Options to csh (Works the Same in tcsh) |
---|
csh –x scriptname | Display each line of script after variable substitution and before execution. | csh –v scriptname | Display each line of script before execution, just as you typed it. | csh –n scriptname | Interpret but do not execute commands. | As Arguments to the set Command |
---|
set echo | Display each line of script after variable substitution and before execution. | set verbose | Display each line of script before execution, just as you typed it. | As the First Line in a Script |
---|
#!/bin/csh –xv | Turns on both echo and verbose. These options can be invoked separately or combined with other csh/tcsh invocation arguments. |
Example 15.23.
(The -v and -x Options)
1 % cat practice
#!/bin/csh
echo Hello $LOGNAME
echo The date is `date`
echo Your home shell is $SHELL
echo Good-bye $LOGNAME
2 % csh -v practice
echo Hello $LOGNAME
Hello ellie
echo The date is `date`
The date is Sun May 23 12:24:07 PDT 2004
echo Your login shell is $SHELL
Your login shell is /bin/csh
echo Good-bye $LOGNAME
Good-bye ellie
3 % csh -x practice
echo Hello ellie
Hello ellie
echo The date is `date`
date
The date is Sun May 23 12:24:15 PDT 2004
echo Your login shell is /bin/csh
Your login shell is /bin/csh
echo Good-bye ellie
Good-bye ellie
EXPLANATION
The contents of the C shell script are displayed. Variable and command substitution lines are included so that you can see how echo and verbose differ. The –v option to the csh command causes the verbose feature to be enabled. Each line of the script is displayed as it was typed in the script, and then the line is executed. The –x option to the csh command enables echoing. Each line of the script is displayed after variable and command substitution are performed, and then the line is executed. Because this feature allows you to examine what is being replaced as a result of command and variable substitution, it is used more often than the verbose option.
Example 15.24.
(Echo)
1 % cat practice
#!/bin/csh
echo Hello $LOGNAME
echo The date is `date`
set echo
echo Your home shell is $SHELL
unset echo
echo Good-bye $LOGNAME
% chmod +x practice
2 % practice
Hello ellie
The date is Sun May 26 12:25:16 PDT 2004
--> echo Your login shell is /bin/csh
--> Your login shell is /bin/csh
--> unset echo
Good-bye ellie
EXPLANATION
The echo option is set and unset within the script. This enables you to debug certain sections of your script where you have run into a bottleneck, rather than echoing each line of the entire script. The ––> marks where the echoing was turned on. Each line is printed after variable and command substitution and then executed.
Example 15.25.
(Verbose)
1 % cat practice
#!/bin/csh
echo Hello $LOGNAME
echo The date is `date`
set verbose
echo Your home shell is $SHELL
unset verbose
echo Good-bye $LOGNAME
2 % practice
Hello ellie
The date is Sun May 23 12:30:09 PDT 2001
--> echo Your login shell is $SHELL
--> Your login shell is /bin/csh
--> unset verbose
Good-bye ellie
EXPLANATION
The verbose option is set and unset within the script. The ––> marks where verbose was turned on. The lines are printed just as they were typed in the script and then executed.
15.5.3 Debugging Korn Shell Scripts
By turning on the noexec option or using the –n argument to the ksh command, you can check the syntax of your scripts without really executing any of the commands. If there is a syntax error in the script, the shell will report the error. If there are no errors, nothing is displayed.
The most commonly used method for debugging scripts is to turn on the xtrace option or to use the ksh command with the –x option. These options allow an execution trace of your script. Each command from your script is displayed after variable substitution has been performed, and then the command is executed. When a line from your script is displayed, it is preceded with the value of the PS4 prompt, a plus (+) sign. The PS4 prompt can be changed.
With the verbose option turned on, or by invoking the Korn shell with the –v option (ksh –v scriptname), each line of the script will be displayed, just as it was typed in the script, and then executed. See Table 15.9 for debug commands.
Table 15.9. Korn Shell Debugging Commands and OptionsCommand | Function/How It Works |
---|
export PS4='$LINENO ' | The PS4 prompt by default is a +. You can reset the prompt. In this example, a line number will be printed for each line. | ksh –n scriptname | Invokes ksh with noexec option. Interprets but does not execute commands. | ksh -u scriptname | Checks for unset variables. Displays an error when expanding a variable that has not been set. | ksh –v scriptname | Invokes ksh with verbose option. Displays each line of the script before execution, just as you typed it. | ksh –x scriptname | Invokes ksh with echo option. Displays each line of the script after variable substitution and before execution. | set +x | Turns off echo. Turns off tracing. |
set –x or
set –o xtrace
| Turns on echo option. Traces execution in a script. | trap 'print $LINENO ' DEBUG | For each script command, the trap action is performed. See format for trap. Prints value of $LINENO for each line in the script. | trap 'print Bad input' ERR | If a nonzero exit status is returned, the trap is executed. | trap 'print Exiting from $0' EXIT | Prints message when script or function exits. | typeset –ft | Turns on tracing. Traces execution in a function. |
Example 15.26.
(The Script)
#!/bin/ksh
# Scriptname: todebug
1 name="Joe Blow"
2 if [[ $name = [Jj]* ]] then
print Hi $name
fi
num=1
3 while (( num < 5 ))
do
4 (( num=num+1 ))
done
5 print The grand total is $num
(The Command Line and Output)
1 $ ksh –x todebug
2 + name=Joe Blow
+ [[ Joe Blow = [Jj]* ]]
+ print Hi Joe Blow
Hi Joe Blow
+ num=1 # The + is the PS4 prompt
+ let num < 5
+ let num=num+1
+ let num < 5
+ let num=num+1
+ let num < 5
+ let num=num+1
+ let num < 5
+ let num=num+1
+ let num < 5
+ print The grand total is 5
The grand total is 5
EXPLANATION
The Korn shell is invoked with the –x option. Echoing is turned on. Each line of the script will be displayed on the screen, followed by the result of executing that line. Variable substitution is performed. Alternatively, the –x option can be used in the script instead of at the command line (i.e., #!/bin/ksh –x). The lines are preceded by the plus (+) sign, the PS4 prompt. The while loop is entered. It will loop 4 times. The value of num is incremented by by 1. After the while loop exits, this line is printed.
Example 15.27.
(The Script)
#!/bin/ksh
# Scriptname: todebug2
1 trap 'print "num=$num on line $LINENO"' DEBUG
num=1
while (( num < 5 ))
do
(( num=num+1 ))
done
print The grand total is $num
(The Output)
2 num=1 on line 3
num=1 on line 4
num=2 on line 6
num=2 on line 4
num=3 on line 6
num=3 on line 4
num=4 on line 6
num=4 on line 4
num=5 on line 6
num=5 on line 4
The grand total is 5
num=5 on line 8
num=5 on line 8
EXPLANATION
LINENO is a special Korn shell variable that holds the number of the current script line. The DEBUG signal, used with the trap command, causes the string enclosed in single quotes to be executed every time a command in the script is executed. As the while loop executes, the value of the variable num and the line of the script are displayed.
15.5.4 Debugging Bash Scripts
By using the –n option to the bash command, you can check the syntax of your scripts without really executing any of the commands. If there is a syntax error in the script, the shell will report the error. If there are no errors, nothing is displayed.
The most commonly used method for debugging scripts is the set command with the –x option, or bash invoked with the –x option and the script name. See Table 15.10 for a list of debugging options. These options allow an execution trace of your script. Each command from your script is displayed after substitution has been performed, and then the command is executed. When a line from your script is displayed, it is preceded with a plus (+) sign.
Table 15.10. Bash Debugging OptionsCommand | Option | What It Does |
---|
bash –x scriptname | Echo option | Displays each line of script after variable substitutions and before execution. | bash –v scriptname | Verbose option | Displays each line of script before execution, just as you typed it. | bash –n scriptname | Noexec option | Interprets but does not execute commands. | set –x | Turns on echo | Traces execution in a script. | set +x | Turns off echo | Turns off tracing. |
With the verbose option turned on, or by invoking the shell with the –v option (bash –v scriptname), each line of the script will be displayed just as it was typed in the script, and then executed.
Bash Invocation Options
When the shell is started using the bash command, it can take options to modify its behavior. There are two types of options: single-character options and multicharacter options. The single-character options consist of a single leading dash followed by a single character. The multicharacter options consist of two leading dashes and any number of characters. Multicharacter options must appear before single-character options. An interactive login shell normally starts up with –i (start an interactive shell), –s (read from standard input), and –m (enable job control). See Table 15.11.
Table 15.11. Additional bash Options to Assist in DebuggingOption | Meaning |
---|
–i | Shell is in the interactive mode. TERM, QUIT, and INTERRUPT are ignored. | –r | Starts a restricted shell. | –– | Signals the end of options and disables further option processing. Any arguments after –– or – are treated as filenames and arguments. | ––help | Displays a usage message for a built-in command and exits. | ––noprofile | When starting up, bash does not read the initialization files:/etc/profile, ~/.bash_profile, ~/.bash_login, or ~/.profile. | ––norc | For interactive shells, bash will not read the ~/.bashrc file. Turned on by default, if running shell as sh. | ––posix | Changes the behavior of bash to match the POSIX 1003.2 standard, if otherwise it wouldn't. | ––quiet | Displays no information at shell startup, the default. | ––rcfile file | If bash is interactive, uses this intialization file instead of ~/.bashrc. | ––restricted | Starts a restricted shell. | ––verbose | Turns on verbose; same as –v. | ––version | Displays version information about this bash shell and exit. |
The set Command and Options
The set command can be used to turn shell options on and off, as well as for handling command-line arguments. To turn an option on, the dash (–) is prepended to the option; to turn an option off, the plus sign (+) is prepended to the option.
Table 15.12. The Built-In set Command OptionsName of Option | Shortcut Switch | What It Does |
---|
allexport | –a | Automatically marks new or modified variables for export from the time the option is set until unset. | braceexpand | –B | Enables brace expansion, and is a default setting. | emacs | | For command-line editing, uses the emacs built-in editor, and is a default setting. | errexit | –e | If a command returns a nonzero exit status (fails), exits. Not set when reading initialization files. | histexpand | –H | Enables ! and !! when performing history substitution, and is a default setting.[a] | history | | Enables command-line history; on by default.[a] | ignoreeof | | Disables EOF (Ctrl-D) from exiting a shell; must type exit. Same as setting shell variable, IGNOREEOF=10. | keyword | –k | Places keyword arguments in the environment for a command.[a] | interactive-comments | | For interactive shells, a leading # is used to comment out any text remaining on the line. | monitor | –m | Allows job control. | noclobber | –C | Protects files from being overwritten when redirection is used. | noexec | –n | Reads commands, but does not execute them. Used to check the syntax of scripts. Not on when running interactively. | noglob | –d | Disables pathname expansion (i.e., turns off wildcards). | notify | –b | Notifies user when background job finishes. | nounset | –u | Displays an error when expanding a variable that has not been set. | onecmd | –t | Exits after reading and executing one command.[a] | physical | –P | If set, does not follow symbolic links when typing cd or pwd. The physical directory is used instead. | posix | | Shell behavior is changed if the default operation doesn't match the POSIX standard. | privileged | –p | When set, the shell does not read the .profile or ENV file and shell functions are not inherited from the environment; automatically set for setuid scripts. | verbose | –v | Turns on the verbose mode for debugging. | vi | | For command-line editing, uses the vi built-in editor. | xtrace | –x | Turns on the echo mode for debugging. |
The shopt Command and Options
The shopt (bash 2.x) command can also be used to turn shell options on and off.
Table 15.13. The shopt Command OptionsOption | Meaning |
---|
cdable_vars | If an argument to the cd built-in command is not a directory, it is assumed to be the name of a variable whose value is the directory to change to. | cdspell | Corrects minor errors in the spelling of a directory name in a cd command. The errors checked for are transposed characters, a missing character, and a character too many. If a correction is found, the corrected path is printed, and the command proceeds. Only used by interactive shells. | checkhash | Bash checks that a command found in the hash table exists before trying to execute it. If a hashed command no longer exists, a normal path search is performed. | checkwinsize | Bash checks the window size after each command and, if necessary, updates the values of LINES and COLUMNS. | cmdhist | Bash attempts to save all lines of a multiple-line command in the same history entry. This allows easy re-editing of multiline commands. | dotglob | Bash includes filenames beginning with a dot (.) in the results of filename expansion. | execfail | A noninteractive shell will not exit if it cannot execute the file specified as an argument to the exec built-in command. An interactive shell does not exit if exec fails. | expand_aliases | Aliases are expanded. Enabled by default. | extglob | The extended pattern matching features (regular expression metacharacters derived from Korn shell for filename expansion) are enabled. | histappend | The history list is appended to the file named by the value of the HISTFILE variable when the shell exits, rather than overwriting the file. | histreedit | If readline is being used, a user is given the opportunity to re-edit a failed history substitution. | histverify | If set, and readline is being used, the results of history substitution are not immediately passed to the shell parser. Instead, the resulting line is loaded into the readline editing buffer, allowing further modification. | hostcomplete | If set, and readline is being used, bash will attempt to perform hostname completion when a word containing an @ is being completed. Enabled by default. | huponexit | If set, bash will send SIGHUP (hangup signal) to all jobs when an interactive login shell exits. | interactive_comments | Allows a word beginning with # to cause that word and all remaining characters on that line to be ignored in an interactive shell. Enabled by default. | lithist | If enabled, and the cmdhist option is enabled, multiline commands are saved to the history with embedded newlines rather than using semicolon separators where possible. | mailwarn | If set, and a file that bash is checking for mail has been accessed since the last time it was checked, the message The mail in mailfile has been read is displayed. | nocaseglob | If set, bash matches filenames in a case-insensitive fashion when performing filename expansion. | nullglob | If set, bash allows filename patterns that match no files to expand to a null string, rather than themselves. | promptvars | If set, prompt strings undergo variable and parameter expansion after being expanded. Enabled by default. | restricted_shell | The shell sets this option if it is started in restricted mode. The value may not be changed. This is not reset when the startup files are executed, allowing the startup files to discover whether or not a shell is restricted. | shift_verbose | If this is set, the shift built-in prints an error message when the shift count exceeds the number of positional parameters. | sourcepath | If set, the source built-in uses the value of PATH to find the directory containing the file supplied as an argument. Enabled by default. | source | A synonym for dot (.). |
|