How to debug bash scripts with two tools

Bash scripts have you in a funk? Find out how to start the process of debugging those scripts, with the help of tools that work seamlessly with your code.

How to debug bash scripts with two easy tools Bash scripts have you in a funk? Find out how to start the process of debugging those scripts, with the help of tools that work seamlessly with your code.

For many Linux administrators, bash scripts are a must-use. These handy scripts help make Linux one of the most flexible operating systems on the planet. There's very little you cannot do with a well-written script. But what happens when you've carefully constructed that script, only to find it doesn't run as planned? Something is amiss. If the script is lengthy and complicated, you might have a heck of a time tracking down the issue(s).

Fortunately, there are plenty of tools available to help you debug your bash scripts. One such tool is set x. This particular debugging tool allows you to mark in a script where you want to focus your debugging efforts. With set x you can either debug an entire script, a section of a script, or a single line. A second handy tool allows you to log output of script to a file. This comes in quite handy, especially when your script is longer than usual (or you want to debut the output later).

SEE: System update policy template download (Tech Pro Research)

Let's take a look at how these two tools are used in a simple bash script.

What you need

The only thing you need for this is a Linux distribution. Most every distribution will contain the necessary tools, however, the distribution must include bash version 5.0 or better. You can find out which version of bash your distribution includes with the command bash —version. Because we're working with the command line, it doesn't matter if you use a desktop or a server distribution.

The script

The basic script we'll use for this test is:

#!/bin/bash

var="Hello World"

# print it
echo "$var"

# Another way of printing it
printf "%s\n" "$var"

echo "Your home is: $HOME"

That's a fairly straightforward script. Create a new file with the command nano hello.world with the above contents. Save and close the file. Give the new file executable permissions with the command:

chmod u+x hello.world

Now execute the script with the command:

sh ./hello.world

You should see exactly the output you expect (Figure A).

Figure A

Figure A: Our bash script output.

Of course, there's nothing wrong with this script, but it makes for an excellent example.

The modified script

Now we're going to modify the script, to include our debugging tools. The first is the logging entry. Under #!/bin/bash, add the following:

exec 5> debug_output.txt
BASH_XTRACEFD="5"
PS4='$LINENO: '

The first line names our debugging file, debug_output.txt. The second line tells bash where to write its xtrace information (which will be declared with set x). Finally, the third line will print out line numbers, to make our debugging even easier.

Next, we need to use set x to indicate which code we want to debug. Let's say the echo $HOME section of the script is working as expected, whereas the echo $var isn't. Let's encase that section with set x so we can only debug that portion of the script. We declare the beginning of the section to be debugged with set -x and the end with set +x. So the new section of code will look like:

set -x

var="Hello World"

# print it
echo "$var"

# Another way of printing it
printf "%s\n" "$var"

set +x

Save and close that file.

Now run the sh ./hello.world command. This time around, the output is quite different (Figure B).

Figure B

Figure B: Our debugged output.

As you see, every line of command begins with a : character, and the output generated by the lines of code immediately follows and does not include the : character. This makes it far easier to debug what is going on.

If you don't find any errors in the code that you marked with set -x and set +x, move those lines to another section and run the command again.

Debugging via log file

If you're dealing with a bash script that is too long for standard output, you'll want to take a look at that debugging log file we declared. However, you'll find that file empty. Why? Because we've run the script with the help of the sh shell, and the sh shell isn't compatible with the BASH_XTRACEFD command. Instead of running the script with sh ./hello.world, simply issue the command ./hello.world. This will use bash, instead of sh, and our debugging output can then be viewed (Figure C) with the command:

less debug_output.txt
Figure C

Figure C: Our debugging output read from the file.

Because we've written our script in such a way, we can:

  • Run the script with sh ./hello.world to see our debugging information sent to standard output (which means it is printed in the terminal window after you run the command).
  • Run the script with ./hello.world to have our debugging information written to the debug_output.text file.

You might also notice, if you run the script with the command ./hello_world, the debugging information is not sent to standard output, and will look exactly as it did in Figure A.

Baby steps

And this is a very simple way to begin the process of debugging your bash scripts. To many, this will seem like baby steps, but once you get the hang of using these tools, you'll find them an invaluable means to debugging those scripts.

Also See

Image: Jack Wallen