Debugging Bash Shell Scripts

Faizan Ahemad
Nov 6, 2017 · 6 min read
Bourne Again

Most of you have debugged java/js and other programming languages. But have you ever tried debugging a bash script. And no I am not talking about the echo “$my_var” style debugging of scripts.

So how do we debug bash scripts, with real break points and variable values in call stack shown in real time?

Well it seems bashdb and visual-studio code have you covered. In this post we will discover how!

There are 6 steps to this setup.

  1. Downloading bashdb
  2. Installing a newer bash version
  3. Compiling (with make) and installing bashdb
  4. Installing vs-code and vs-code bash-debug plugin
  5. Setting up debugging in vs-code
  6. Finally seeing the debugger in action

Lets run through these steps in detail. Note that I am doing these steps on Mac OSX 10.12.6.

Note: Also note that you maybe able to install bashdb without all the downloading and compiling, if you use brew/apt/yum then these should have bashdb in their repo already. See vs-code bashdb plugin page for details. Skip step 1 n 3 then. Perform step 2 before installing bashdb

Downloading bashdb

Go to sourceforge repo of bashdb. Now choose the latest folder (When this article was written the latest was 4.4-0.94) and open it. Download the *tar.gz extension file.

Now you need to extract this. In your terminal.

$> cd folder/where/you/downloaded
$> tar -xvf bashdb-*.tar.gz
$> ls
$> cd bashdb-extracted-folder-name-see-in-dir

Installing a newer bash version

Check your bash version by running in your terminal

$> bash --version
$> which bash

If your version is above 4.4.12 then skip the rest of this step. Else install latest bash.

For osx make sure you have brew. do brew install bash , check your bash version. if bash version is still old then run which bash again and see the path to bash. if it is /usr/bin/bash then your brew installation location is not in your path or comes later than /usr/bin. To remedy this add the below line to your .bashrc or .zshrc file

export PATH=/usr/local/bin:$PATH

Brew installs into the above location. Check again for bash version. If you are on Linux then apt/yum can help.

Compiling and installing bashdb

Go to the bashdb dir and configure, make, install

$> cd /bashdb/extracted/folder
$> ./configure
$> make && make check
$> sudo make install

After this run which bashdb , if this commands shows you bashdb installed then go to next step. Else

$> ls /usr/local/Cellar/bash/4.4.12/bin
# after /bash/ version maybe different in your case. use tab completions, make sure you have something above 4.4.x
# if you find bashdb executable then run the below command
$> ln -s /usr/local/Cellar/bash/4.4.12/bin/bashdb /usr/local/bin/bashdb

Note that I have given symlinking steps for Mac OSX with brew. In case you are on linux symlink steps are pretty same except for install locations. Check your package managers documentation (yum/apt) to see where they install bash and follow appropriate symlink steps.

Note: Also note that you maybe able to install bashdb without all the downloading and compiling, if you use brew/apt/yum then these should have bashdb in their repo already. See vs-code bashdb plugin page for details. Skip step 1 n 3 then. Perform step 2 before installing bashdb.

Installing VS-code and vs-code bash-debug plugin

Download vs-code from here. Next install and open vs-code. On the left sidebar click on extensions.

left side bar

The last square button is the extensions button. In search box type bash debug , install the plugin with title as Bash Debug rogalmic.bash-debug.

Setting up debugging in VS-code

A gif on plugins page shows the setup process. Open your workspace where you want to debug bash scripts. Mostly you may have a folder with all the scripts you use. Open that in VS-code.

First you will Cmd+Shift+P to go into command menu. Then you will type debug: Open launch.json, after this choose bash debug then select script from drop down (1st option). Then your launch.json file will be created.

Inside the configuration array see the object with

"type": "bashdb"

Change the line with scriptPath to

"scriptPath": "${command:SelectScriptName}",

Its “${command.SelectScriptName}” previously, note the full-stop after command instead of colon. Do not use the full stop version, use the colon version.

Note: you will need to do this setup step for each workspace since launch.json stored in your workspace .vscode folder. If someone knows how to make it a default for all workspaces please let me know.

Finally the Debugger in Action

Create a .sh file with below contents

#!/usr/bin/env bashexport NICE_VAR=10export ANOTHER_VAR=20for i in {0..25..5}do  export NICE_VAR=$NICE_VAR+$i  echo $NICE_VARdonefor ((i=1;i<=25;i+=1))do  export ANOTHER_VAR=$ANOTHER_VAR+$i  echo $ANOTHER_VARdoneif [ $ANOTHER_VAR -gt $NICE_VAR ]then  echo "ANOTHER bigger than nice"else  echo "Nice is bigger or equal"fi

Now just click left of line numbers to create debug points. I did as below

debug points in editing window

Now click on the bug button on left sidebar (above the extensions button).

Window changes to below

debug window

Click on the green play button making sure that bash-debug is selected.

it will show you a list of files. like below

File selection for debug

Choose the file you just created. and see how the debug window changes as below.

See how the debug line is at line 2 and paused. you can move ahead using the debug buttons at the top. To go to next breakpoint click on the top play button below the filename.

Now click the play button. Hover over i in the addition expression and you will be able to see its value.

You can play with this and debug your bash scripts with ease.

Note: your scripts must start with #!/usr/bin/env bash

Note: VS code crashes once the script finishes or when there is an error in the script. I have raised the issue here.

Bash script links

  1. For loop in bash
  2. For loop in bash
  3. if-else bash
  4. addition/maths in bash

Debugging using bashdb through terminal or command-line

In case the crashing of vs-code is irritating or you are ssh-ing to a server and no ui is available do this. Make sure bashdb is in your path.

Next do

➜  server git:(master) ✗ bashdb testfile.sh
bash debugger, bashdb, release 4.4-0.94
(/Users/ahemf/mygit/geek-marks/server/testfile.sh:2):
2: export NICE_VAR=10
bashdb<0> step
(/Users/ahemf/mygit/geek-marks/server/testfile.sh:3):
3: export ANOTHER_VAR=20
bashdb<1> step
(/Users/ahemf/mygit/geek-marks/server/testfile.sh:5):
5: for i in {0..25..5}
bashdb<2> step
(/Users/ahemf/mygit/geek-marks/server/testfile.sh:7):
7: export NICE_VAR=$((NICE_VAR + i))
bashdb<3> step
(/Users/ahemf/mygit/geek-marks/server/testfile.sh:8):
8: echo $NICE_VAR
bashdb<4> step
10
(/Users/ahemf/mygit/geek-marks/server/testfile.sh:5):
5: for i in {0..25..5}
bashdb<5> step
(/Users/ahemf/mygit/geek-marks/server/testfile.sh:7):
7: export NICE_VAR=$((NICE_VAR + i))
bashdb<6> print $i
5
bashdb<7>

The bold lines are what I typed, rest is output. For more detailed info about command-line debugging check the documentation of bashdb here. See sections on 4.4 Stopping and Resuming Execution and 4.9 Examining Data. There are a ton of other commands in the docs as well.

References:

  1. vs-code bashdb plugin page
  2. sourceforge repo of bashdb
  3. Download vs-code
  4. Homepage of bashdb
  5. Bashdb documentation
  6. VS code crash issue

Faizan Ahemad

Written by

Machine Learning Engineer @Amazon.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade