1

I am using the following code in a bash script in order to trace the code

#!/bin/bash
function trace()
{
    echo "TRACE" \
         "${BASH_SOURCE[1]}:${BASH_LINENO[0]}:${FUNCNAME[1]}:" \
         "$BASH_COMMAND"
}

set -o functrace
shopt -s extdebug
trap trace DEBUG

# Remainder of code here
exit 0

But when I run it, it eats my variables. Some clue?

Hanynowsky
  • 2,970
  • 5
  • 32
  • 43

3 Answers3

8

The best way is to use set -xv. The set -v will echo a line before it is executed. The set -x will output the line after the shell script interpolates the variables and expressions in that line.

As part of this, you can also create an environment variable called PS4 which will be the prompt printed each time your shell scripts outputs the line being executed. Most people set it to something like PS="\$LINENO: " which will print out the line number for the line being executed.

Once you're finished, you can turn off debugging by setting set +xv.

#
# Somewhere in this part of my script, I am having problems....
#
export PS4="\$LINENO> "   # Now, I'll see the line numbers while debugging
set -xv                   # Debugging is turned on
....
#
# Done with debugging
#
set +xv                   # Debugging is turned off
David W.
  • 105,218
  • 39
  • 216
  • 337
5

Here are a few recommendations:

  • You can always echo line in your shell script to see what's going on.
  • You can also use set -xv to help you debug a shell script. Simply put set -xv before the part you want to debug, and set +xv to turn off the debug. You can also use export PS4="\$LINENO> " to print out the line number in your shell script.

Here's how your script will look with the set -xv. It's a really nice tool for debugging shell scripts.

MLSC
  • 5,872
  • 8
  • 55
  • 89
1

The following setup will enable printing of the line number and function name for each command (assuming you later put set -x in front of the code you're debugging):

set -o functrace
shopt -s extdebug
PS4='+ line ${LINENO-}, in ${FUNCNAME-}(): '

Here's some code to test the above:

foo() { echo "now in $FUNCNAME"; bar; }
bar() { echo "now in $FUNCNAME"; baz; }
baz() { echo "now in $FUNCNAME";      }

set -x
foo