Sometimes when I have a problem with a bash script I want the ability to run each line of the script one by one to see what is wrong. There is a debugger called bashdb that can be used in this way. It behaves similarly to gdb (used for debugging C and C++ programs) and pdb (used for debugging Python programs).
First you need to determine what version of bash you are running, since you need to use a corresponding version of bashdb:
# bash --version
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
This version of bash is 5.1.16, so we need a bashdb version 5.1.x. Let’s download it:
NOTE: The following commands are written for an Ubuntu- or Debian-based Linux distribution. Also, you may need to prefix some commands with sudo
to avoid permission errors.
# apt-get update
# apt-get install git -y
# git clone https://git.code.sf.net/p/bashdb/code bashdb-code
# cd bashdb-code/
# git checkout bash-5.1
For bashdb >= 5.1.x, you’ll need to build the configure
and bashdb
files:
# apt-get update
# apt-get install autoconf -y # to run autogen.sh
# apt-get install binutils -y # to install "strings" tool, for autogen.sh
# apt-get install make -y # to install "make" tool
# apt-get install texinfo -y # to install "makeinfo" tool, for make
# ./autogen.sh
You should now have a bashdb
file in the current directory:
# ls | grep bashdb
bashdb
bashdb-main.inc
bashdb-main.inc.in
bashdb-part2.sh
bashdb-trace
bashdb-trace.in
bashdb.in
(Optional) If you have root permissions, you can install bashdb:
# make install
Let’s create an example script to debug:
# cat << EOF > /tmp/hello.sh
echo 1
echo 2
echo 3
echo 4
EOF
If you did install bashdb in the step above, start the debugger on a Bash script at /tmp/hello.sh
with:
# bash --debugger /tmp/hello.sh
...
(/tmp/hello.sh:1):
1: echo 1
bashdb<0>
If you did not install bashdb, you can run the debugger by calling the bashdb script manually:
# bash ./bashdb /tmp/hello.sh
...
(/tmp/hello.sh:1):
1: echo 1
bashdb<0>
See all debugger commands using help
:
bashdb<0> help
Available commands:
-------------------
action condition edit frame load run source unalias
alias continue enable handle next search step undisplay
backtrace debug eval help print set step+ untrace
break delete examine history pwd shell step- up
clear disable export info quit show tbreak watch
commands display file kill return signal trace watche
complete down finish list reverse skip tty
Readline command line editing (emacs/vi mode) is available.
Type "help" followed by command name for full documentation.
bashdb<1>
See where you are in the script using list
:
bashdb<1> list
1: => echo 1
2: echo 2
3: echo 3
4: echo 4
5:
bashdb<2>
You can step over the current line using next
or n
:
bashdb<3> next
1
(/tmp/hello.sh:2):
2: echo 2
bashdb<4> list
1: echo 1
2: => echo 2
3: echo 3
4: echo 4
5:
bashdb<5>
You can step into the current line using step
or s
. This is useful to enter into a function call or a line that uses source
to call another script:
bashdb<6> step
2
(/tmp/hello.sh:3):
3: echo 3
bashdb<7> list
1: echo 1
2: echo 2
3: => echo 3
4: echo 4
5:
bashdb<8>
You can step out of the current function with finish
.
Other common commands include:
eval STATEMENT
- Run a statement.
eval X=1
print EXPR
- Print an expression, such as a variable.
print $X
break
- Set a breakpoint.
break 3
(set breakpoint on line 3)break /tmp/hello.sh:4
(set breakpoint on line 4 of file /tmp/hello
)continue
, cont
, c
- Step continuously until a breakpoint is hit or the script ends.exit
- Stop the script and exit the debugger.