Output debugging information in shell scripts is commonly used in the following ways:
1.trap command
The trap command is used to capture the specified signal and execute a pre-defined command. The basic syntax is: trap ' command ' signal. Where signal is the signal to be captured, the command is captured to the specified signal after the commands to be executed. You can use the Kill-l command to view all the available signal names in the system.
The command executed after capture can be any one or more valid shell statements, or a function name. When the shell executes the script, it produces three so-called "pseudo-signals" (only so called pseudo-signals, because the three signals are generated by the shell, and the other signals are generated by the operating system).
Use the trap command to capture these three "pseudo-signals" and output relevant information. The "pseudo-signal" generated by the shell script at execution time is as follows:
Exit exits from a function or the entire script executes the resulting signal
ERR a signal generated when a command returns a non-0 state (on behalf of unsuccessful command execution)
The signal generated before each command in the DEBUG script executes
By capturing the exit signal, we can output some of the variables we want to track when the shell script aborts execution or exits from the function, and thus determine the execution state of the script and the cause of the error, using the trap ' command ' EXIT or trap ' command ' 0; By capturing the err signal, we can easily trace the execution of the unsuccessful command or function, and output the relevant debugging information, here is a sample program to capture the Err signal, where $lineno is a shell built-in variable that represents the current line number of the shell script To capture the debug signal, we only need a trap statement to complete the full tracking of the relevant variables.
For example:
1.
Errortrap () {
echo "line:$1 Error:command or function exited with status $?"
}
Test () {
Echo 1111111;
}
Trap ' errortrap $LINENO ' ERR
SDFASDF #随便写的命令
Foo
2.
Trap ' echo ' before execute line: $LINENO, a= $a, b= $b, c= $c "' DEBUG
A=1
If ["$a"-eq 1]
Then
b=2
Else
B=1
Fi
C=3
echo "End"
#使用DEBUG可以清晰的看到每执行一条命令之后, changes in the value of the related variable. At the same time, from the running results of the printed line number to analyze, you can see the entire script execution trajectory, can determine which conditions branch execution, which conditional branches are not executed.
Tee command
In shell scripts, pipelines and input and output redirects are used very much, and the results of the execution of some commands in the pipeline become the input to the next command directly. If an error occurs, you need to step through the execution of each command to determine where the problem occurs, but because the pipeline is used, these intermediate results are not displayed on the screen and are difficult to debug, so you can use the tee command. The tee command reads the data from the standard input, prints its contents to the standard output device, and saves the contents to the file.
For example:
1.
/sbin/ifconfig | grep ' inet addr: ' | Grep-v ' 127.0.0.1 ' | Tee Temp.txt | Cut-d:-f3 | awk ' {print '} '
#然后可以通过查看temp the contents of a. txt file to view the contents of the output
Using the "Debug hooks"
In a C language program, we often use debug macros to control whether or not to output debug information, which can be used in shell scripts, as shown in the following code:
If ["$DEBUG" = "true"]; Then
echo "Debugging" #此处可以输出调试信息
Fi
Such blocks of code are often referred to as "debug hooks" or "Debug blocks". Inside the debug hook can output any of the debugging information you want to output, the advantage of using the debug hook is that it can be controlled by the debug variable, in the development and debugging stage of the script, you can first execute the Export debug=true command to open the debug hook, so that it output debugging information.
For example:
1.
Debug= "true" #来控制是否输出调试信息
DEBUG () {
If ["$DEBUG" = "true"]; Then
[Email protected]
Fi
}
A=1
DEBUG echo "a= $a"
If ["$a"-eq 1]
Then
b=2
Else
B=1
Fi
DEBUG echo "b= $b"
C=3
DEBUG echo "c= $c"
Using the shell's execution options
The above three debugging methods are to locate the error by modifying the source code of the shell script to output the corresponding debugging information. Here are some ways to debug a shell script without modifying the source code.
-N
Only the shell script is read, but not actually executed, and can be used to test for syntax errors in the shell script. A good habit is to use-n after writing a shell script to test whether the script has
Syntax error.
-X
Enter the tracking mode, which displays each command executed, which causes the shell to display each command line it actually executes during the execution of the script, and displays a "+" sign at the beginning of the row. The "+" sign is followed by the contents of the command line after the variable substitution, helping to analyze what commands were actually executed.
-C
"String" reads the command from strings and causes the shell interpreter to read and execute the shell command from a string rather than from a file. When you need to temporarily test the execution results of a small piece of script,
You can use this option as follows:
Sh-c ' A=1;b=2;let c= $a + $b; echo "C= $c"
The shell's execution options can be specified in the script, in addition to being specified when the shell is started. Set-parameter means that an option is enabled, and set + parameter means that an option is turned off. Sometimes we don't need to use the "-X" option at startup to keep track of all the command lines, so we can work with the set command in the script.
For example:
1.
1 #!/bin/bash
IsRoot () {
If ["$UID"-ne 0]
Return 1
Else
return 0
Fi
}
IsRoot
If ["$?"-ne 0]
Then
echo "must is root to run this script"
Exit 1
Else
echo "Welcome root user"
#do something
Fi
#首先使用sh-n test.sh check for syntax errors. If there is one, then SH test.sh executes the script and, if there is an error, debug it in the following way:
Export ps4= ' +{$LINENO: ${funcname[0]} '
Sh-x test.sh
which
$LINENO:
Represents the current line number of the shell script, similar to the built-in macro __line__ in the C language;
$FUNCNAME:
The name of the function, similar to the built-in macro __func__ in C, but the macro __func__ can only represent the current function name, and $funcname is more powerful, it is an array variable,
It contains the name of all functions on the entire call chain, so the variable ${funcname[0]} represents the name of the function that the shell script is currently executing, and the variable ${funcname[1]}
The name of the function representing the calling function ${funcname[0]}, the remainder can be and so on;
$PS 4:
The main prompt variable $PS1 and the second-level prompt variable $ps2 are more common, but few people notice the effect of the fourth-level prompt variable $PS4. We know that using the "-X" execution option will
Displays each command that was actually executed in the shell script, and the value of $PS4 is displayed in front of each command output by the "-X" option. In bash shell, the default value of $PS4
is the "+" sign. (Now that you know why the "-X" option is used, the output command has a "+" sign in front of it?) );
Using the $PS4 feature, we can enhance the output information of the "-X" option by redefining the value of the $PS4 using some built-in variables. For example, execute the export ps4= ' +{$LINENO: ${funcname[0]} ' and then execute the script using the '-X ' option to display its line number and the name of the function it belongs to in front of each actually executed command.
Summarize
First use the "-N" option to check for syntax errors, then use the "-X" option to track the execution of the script, and before using the "-X" option, do not forget to customize the value of the PS4 variable to enhance the output of the "-X" option, at least to output line number information (first execute export ps4= ' +[$LINENO ] ', more than once, add this statement to your home directory's. bash_profile file, which will make your debugging journey easier. You can also use traps, debug hooks and other means to output key debugging information, quickly reduce the scope of troubleshooting errors, and in the script using "Set-x" and "set +x" to focus on some blocks of code tracking. This way, I believe you can easily catch the bug in your shell script. If your script is complex enough and requires more debugging power, you can use the Shell debugger Bashdb, a debugging tool similar to GDB that can perform many functions such as breakpoint settings for shell scripts, stepping, variable observation, and so on.
Resources:
http://www.ibm.com/developerworks/cn/linux/l-cn-shell-debug/
Common debug methods for shells