Debugging your scripts

What are bugs? None of our scripts are going to have bugs!!!! Of course not! We're far too good at scripting for that. Having said this however, we still need to understand how to debug other people's scripts! How do you debug a script?

There are many techniques to debugging a script, but the place to begin is by adding the -x switch at the top of your script:

#!/bin/bash -x

Alternatively you can type the following on the command line:

bash -x 

This is a very primitive form of debugging so you cannot step though your script line by line. It will produce your whole script output but it should produce it with more information than what you saw before.

Another technique is to place echo statements strategically throughout your script to indicate the values of variables at certain points.

If, for example, a test is performed, then an:

echo $?

will show the outcome of the test, prior to performing some condition on this outcome.

Along with echo statements, one can also place read or sleep commands to pause the execution of the script. This will allow one time to read the outcome of a set of commands, before continuing the execution.

Thus a command set as follows:

[ -f somefile ]
echo $?
echo "Hit any key to continue..."

will pause the script, giving the author time to consider the output from the pervious test.

The NULL command

In the script, we may want to do a null command. There is a special command:

if : 	#This condition will always be true (as : is always true)#

The null command is a colon. We could for example produce a never-ending while loop using nloop by saying:

while :
do		echo "hello $NAME"

"noop" is always TRUE! Earlier on we tried

`date | cut...`

in order to obtain 'SAST' (SA std time) as output. Doing this on the command line, it said:

SAST: command not found

Modifying this however to:

: `date |cut...`

would have not produced an error, since the colon will always produces TRUE output. The shell thus executes the no-op instead of the output of the date/cut command.

If you said:

if :

It would always do the THEN part of the IF statement.

The || and && commands

You can achieve multiple commands on the same line by using the && and ||. How does this work? By way of example, you could say:

grep italian restaurants.txt || echo "sorry no italians here"

What this means is:

"if there are italians inside resturants.txt then return them
	OR [else]
return the string 'sorry, no italians here'"

In shell terms, it means:

if the result of the grep command is TRUE (0), 
then you  will get the lines from the file resturants.txt containing the word italian 
BUT if  there are no lines in the file containing the word italian 
(i.e.the outcome of the grep is FALSE (1)) 
	then print
 'sorry no italians here'

As before, this is a shortcut way of doing things. Enclosing this command in parentheses can change the order of execution as in:

\( grep italian restaurants.txt || echo "sorry no italians here" \) 

which could also allow:

\( cmd1 || cmd2 \) && \( cmd3  && cmd4 \)

Here is another example:

echo "Oh, you're looking for italian, here they are: " \
&& grep italian restaurants.txt

Echo will always return TRUE(0), so it would print out the echo statement and then the list of italian restaurants, if there are any. Very useful!


Using the || and && constructs, perform the following operations:

  1. If your free memory is less than 50M, issue a warning on the console

  2. If free disk space is less than 10%, issue a warning on the syslog file (HINT: There is an application called logger(1) which will assist with logging to the syslog file)

  3. Using your resturants.txt file, write a condition that will print the italian resturants, or a message indicating there are none in the file. Ensure that you inform the user in the following way:

    The <italian> restaurants you might like to eat at are:

    or if there are none, then:

    The <italian> restaurants you might like to eat at are:
    Sorry. We don't have any listings of <italian> resturants.

    Replace the <> with the values the user enters on the command line when running the script.