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?

3

3 Answers 3

10

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
Sign up to request clarification or add additional context in comments.

1 Comment

Thx! You saved me a lot of time!
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.

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.