[bash] How to debug a bash script?

Is there any way to debug a bash script? E.g something that prints a sort of execution log like "calling line 1", "calling line 2" etc.

This question is related to bash shell

The answer is


Install VSCode, then add bash debug extension and you are ready to debug in visual mode. see Here in action.

enter image description here


Use eclipse with the plugins shelled & basheclipse.

https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory

For shelled: Download the zip and import it into eclipse via help -> install new software : local archive For basheclipse: Copy the jars into dropins directory of eclipse

Follow the steps provides https://sourceforge.net/projects/basheclipse/files/?source=navbar

enter image description here

I wrote a tutorial with many screenshots at http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html


This answer is valid and useful: https://stackoverflow.com/a/951352

But, I find that the "standard" script debugging methods are inefficient, unintuitive, and hard to use. For those used to sophisticated GUI debuggers that put everything at your fingertips and make the job a breeze for easy problems (and possible for hard problems), these solutions aren't very satisfactory.

What I do is use a combination of DDD and bashdb. The former executes the latter, and the latter executes your script. This provides a multi-window UI with the ability to step through code in context and view variables, stack, etc., without the constant mental effort to maintain context in your head or keep re-listing the source.

There is guidance on setting that up here: http://ubuntuforums.org/showthread.php?t=660223


Some trick to debug scripts:

Using set -[nvx]

In addition to

set -x

and

set +x

for stopping dump.

I would like to speak about set -v wich dump as smaller as less developped output.

bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21

for arg in x v n nx nv nvx;do echo "- opts: $arg"
    bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
        set -$arg
        for i in {0..9};do
            echo $i
          done
        set +$arg
        echo Done.
eof
    sleep .02
  done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5

Dump variables or tracing on the fly

For testing some variables, I use sometime this:

bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args

for adding:

declare >&2 -p var1 var2

at line 18 and running resulting script (with args), without having to edit them.

of course, this could be used for adding set [+-][nvx]:

bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args

will add declare -p v1 v2 >&2 after line 18, set -x before line 22 and set +x before line 26.

little sample:

bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
        seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8

Note: Care about $LINENO will be affected by on-the-fly modifications!

( To see resulting script whithout executing, simply drop bash <( and ) arg1 arg2 )

Step by step, execution time

Have a look at my answer about how to profile bash scripts


You can also write "set -x" within the script.


set +x = @ECHO OFF, set -x = @ECHO ON.


You can add -xv option to the standard Shebang as follows:

#!/bin/bash -xv  

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


ltrace is another Linux Utility similar to strace. However, ltrace lists all the library calls being called in an executable or a running process. Its name itself comes from library-call tracing. For example:

ltrace ./executable <parameters>  
ltrace -p <PID>  

Source


I built a Bash debugger. Just give it a try. I hope it will help https://sourceforge.net/projects/bashdebugingbash


I found shellcheck utility and may be some folks find it interesting https://github.com/koalaman/shellcheck

A little example:

$ cat test.sh 
ARRAY=("hello there" world)

for x in $ARRAY; do
  echo $x
done

$ shellcheck test.sh 

In test.sh line 3:
for x in $ARRAY; do
         ^-- SC2128: Expanding an array without an index only gives the first element.

fix the bug, first try...

$ cat test.sh       
ARRAY=("hello there" world)

for x in ${ARRAY[@]}; do
  echo $x
done

$ shellcheck test.sh

In test.sh line 3:
for x in ${ARRAY[@]}; do
         ^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.

Let's try again...

$ cat test.sh 
ARRAY=("hello there" world)

for x in "${ARRAY[@]}"; do
  echo $x
done

$ shellcheck test.sh

find now!

It's just a small example.


I think you can try this Bash debugger: http://bashdb.sourceforge.net/.


I've used the following methods to debug my script.

set -e makes the script stop immediately if any external program returns a non-zero exit status. This is useful if your script attempts to handle all error cases and where a failure to do so should be trapped.

set -x was mentioned above and is certainly the most useful of all the debugging methods.

set -n might also be useful if you want to check your script for syntax errors.

strace is also useful to see what's going on. Especially useful if you haven't written the script yourself.


There's good amount of detail on logging for shell scripts via global varaibles of shell. We can emulate the similar kind of logging in shell script: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html

The post has details on introdducing log levels like INFO , DEBUG, ERROR. Tracing details like script entry, script exit, function entry, function exit.

Sample log:

enter image description here