Search Web......

Debugging Shell Scripts on Unix/Linux environment

I have seen many unix platform beginners struggling with shell scripts, and many of them have asked this question to me

"How can I Debug a shell script?"

As you may already know that shell scripts are interpreted, and every statement in your script is interpreted just before running it. So locating the problem can be easier then other languages where code is converted to binary and matching line of code with a binary code becomes difficult. Still, many people don't know that there can be different ways to debug a shell script on unix platform. I am trying to list them all as it may depend on your usage.

-x option to debug a shell script



Running a shell script with -x option enables the display of commands and its arguments when they are executed.

  
$ bash -x [script-name]


Look at the test.sh example below. test.sh is a a simple test shell script, which sets the path with a bin directory in my home



#!/bin/bash
echo 'Hi'
export PATH=$PATH:/export/home/swiki/bin
echo $PATH



Here is the output of running this script in a debug mode using -x option for bash command.



$ /bin/bash -x test.sh

+ echo Hi
Hi
+ export PATH=:/export/home/swiki/bin
+ PATH=:/export/home/swiki/bin
+ echo :/export/home/swiki/bin
:/export/home/swiki/bin



Using "set" command debug options



Bash shell offers debugging options which can be turn on or off using set command.
Below are the two options, which can be used to debug any script in a bash shell.

- set -x : Print commands and their arguments as they are executed.
- set -v : Print shell input lines as they are read.

You can use above two command in shell script itself like below:



#Turn on Debug mode
set -x
set -v
echo 'Hi'
export PATH=$PATH:/export/home/swiki/bin
echo $PATH
#Turn off Debug mode
set +x
set +v



The output of running this script with bash will be



$ /bin/bash test.sh

+ set -v
+ echo Hi
Hi
+ export PATH=:/export/home/swiki/bin
+ PATH=:/export/home/swiki/bin
+ echo :/export/home/swiki/bin
:/export/home/swiki/bin



Use of a DEBUG function



Add a variable DEBUG_ENABLE on top of your script and set it to parameter value from command line. In this example I am taking the first parameter of the script.




#!/bin/bash
DEBUG_ENABLE=$1
function DEBUG()
{
if [ "$DEBUG_ENABLE" == "debug" ]
then
$@
fi
}

DEBUG set -x
DEBUG set -v
echo 'Hi'
export PATH=$PATH:~/bin
echo $PATH



All the calls to debug related setting should be prefixed by DEBUG function call, this will make sure you don't execute them when you are not debugging.
In this example, when you are running the script you just need to pass a parameter "debug" on the command line and the script will run in debug mode.




$ /bin/bash test.sh debug

+ DEBUG set -v
+ '[' debug == debug ']'
+ set -v
+ echo Hi
Hi
+ export PATH=:/export/home/swiki/bin
+ PATH=:/export/home/swiki/bin
+ echo :/export/home/swiki/bin
:/export/home/swiki/bin



Externalizing the Debugging to a debug script



The above mentioned DEBUG function technique can be commonly used to debug many scripts. So it will not make sense to keep the same DEBUG function inside each script.
A simple way is to create a debug.sh script and source it while running a script. The command line parameter will still stand good for this.

Below are the content of debug.sh script



$ cat debug.sh

#!/bin/bash
_DEBUG=$1
function DEBUG()
{
if [ "$_DEBUG" == "debug" ]
then
$@
fi
}

DEBUG set -x
DEBUG set -v



To use this debug script in your actual script you just need to make a call to the debug.sh as shown below



source ./debug.sh



So now our original test.sh script looks like this



#!/bin/bash
source ./debug.sh
echo 'Hi'
export PATH=$PATH:~/bin
echo $PATH



Now if you run the script with "debug" option then this will be the output.


$ /bin/bash test.sh debug

++ DEBUG set -v
++ '[' debug == debug ']'
++ set -v

echo 'Hi'
+ echo Hi
Hi
+ export PATH=:/export/home/swiki/bin
+ PATH=:/export/home/swiki/bin
+ echo :/export/home/swiki/bin
:/export/home/swiki/bin


If you have noticed the two plust signs (++) at the beginning of outuput, it shows that a script is called inside another script.

Personally I like the last option of externalizing the scripts debugging in case you are writing many scripts. If you write a script once in a while then using the "set -x" option would be easiest/quickest thing to do debugging.

Hope this will make your unix script debugging simpler than before. Don't forget to share with us if you know a better way of debugging unix scripts.




unix debug script, shell script debug, linux script debug, linux debug script, debugging shell script, debug bash script on linux,debug bash script on unix, debug function to debug linux scripts, debug script for debugging scripts