One of the most common questions asked by a new sysadmin or UNIX user is: How to debug a shell script?
Before proceeding further, let’s use the following sample script for this tutorial. The script is supposed to add two variables and print the result. Obviously, there is an error in the script and it will not print the expected result.
#!/bin/sh one=1 two=2 result="" results=<code>expr $one + $two</code> echo result is $result
Now, let’s look at some of the shell script debugging techniques.
Shell Options -v, -x to Debug a Shell Script
The “-x
” option is the easiest and one of the most common options to debug shell scripts. It will print the commands and their arguments as they are executed.
1 2 3 4 5 6 7 8 |
$ sh -x script.sh + one=1 + two=2 + result= ++ expr 1 + 2 + results=3 + echo result is result is |
To print just the lines read by the shell, we can use the “-v
” option.
1 2 3 4 5 6 7 8 9 10 11 12 |
$ sh -v script.sh #!/bin/sh one=1 two=2 result="" results=`expr $one + $two` expr $one + $two echo result is $result result is |
You can also enable debugging by changing the default shebang line from:
1 |
#!/bin/sh |
to:
1 |
#!/bin/sh -x |
Debug a Portion Of a Shell Script
If you want to debug just a certain portion of a script, you can use the built-in set
command to turn debugging on and off.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/bin/sh one=1 two=2 result="" # turn on debugging mode set -x results=`expr $one + $two` # turn off debugging mode set +x echo result is $result |
When the sript is run, you will get the following output.
1 2 3 4 5 |
$ ./script.sh ++ expr 1 + 2 + results=3 + set +x result is |
Do you notice that after the “set +x
” line, the debug statements have been turned off?
Custom Function to Debug Shell Script
This is usually my preferred way of debugging shell scripts. The idea is to add a variable that controls whether debugging is on or off. This variable is then checked in a custom function to print the relevant debug messages. Confused? Let’s look at an example.
Add a variable called “_debugmode
” to the script. Set the variable to “1” if you want to turn on debugging.
Next, add a debugprint
function to the script at the top of the script.
1 2 3 4 |
function debugprint () { [ $_debugmode -eq 1 ] && echo "debug: $@" } |
Once done, add debug statements wherever needed within the script.
1 |
debugprint "some debug statement" |
Let’s look at the modified sample script with the custom debug function.
#!/bin/sh _debugmode=1 one=1 two=2 result="" function debugprint () { [ $_debugmode -eq 1 ] && echo "debug: $@" } results=<code>expr $one + $two</code> debugprint "result = $results" echo result is $result debugprint "End of script"
The newly introduced code is highlighted. You will get the following output if you run the script with debugging on.
1 2 3 4 |
$ ./script.sh debug: result = 3 result is debug: End of script |
To turn off debugging, simply set _debugmode
variable to “0
“. You do not need to remove the debugprint
function or the calls to the debugprint
function.