hana_shinのLinux技術ブログ

Linuxの技術情報を掲載しています。特にネットワークをメインに掲載していきます。

bashdbの使い方



1 bashdbとは?

bashスクリプトデバッグするときに使うデバッガです。gdbやcrashのように行単位でデバッグすることができます。

2 検証環境

AlmaLinux版数は以下のとおりです。

[root@server ~]# cat /etc/redhat-release
AlmaLinux release 8.6 (Sky Tiger)

カーネル版数は以下のとおりです。

[root@server ~]# uname -r
4.18.0-372.9.1.el8.x86_64

3 インストール方法

下記サイトよりbashdbをダウンロードしました。
https://sourceforge.net/projects/bashdb/files/bashdb/
検証で使用するbashの版数が4系なので、bashdbは4系の最新版をダウンロードしました。

[root@server ~]# wget https://sourceforge.net/projects/bashdb/files/bashdb/4.4-1.0.1/bashdb-4.4-1.0.1.tar.bz2

ダウンロードしたファイルを確認します。

[root@server ~]# ls -l bashdb-4.4-1.0.1.tar.bz2
-rw-r--r--. 1 root root 701807 11月 17  2018 bashdb-4.4-1.0.1.tar.bz2

ダウンロードした圧縮ファイルを解凍します。

[root@server ~]# tar xvfj bashdb-4.4-1.0.1.tar.bz2

INSTALLファイルの記載内容に従って、bashdbをインストールしました。ただし、configure実行時に--with-bash-srcオプションを付けるとエラーが発生するため、ここでは--with-bash-srcオプションなしでコンパイルしました。--with-bash-srcオプションは、Bashソースコードがインストールされているディレクトリを指定するためのオプションであり、検証環境ではBashソースコードをインストールしていなかったため、オプションを付けずに実行しました。

[root@server ~]# cd bashdb-4.4-1.0.1/
[root@server bashdb-4.4-1.0.1]# ./configure && make check
[root@server bashdb-4.4-1.0.1]# make install

bashdbの版数を確認します。

[root@server bashdb-4.4-1.0.1]# bashdb -V
bashdb, release 4.4-1.0.1

4 事前準備

デバッグ対象のスクリプトファイルを作成します。

[root@server ~]# vi tp.sh
[root@server ~]# cat tp.sh
#!/usr/bin/bash

function func_start() {
  echo "START"
}

function func_end() {
  echo "END"
}

func_start

dnf download bc > /dev/null 2>&1

if [ -f bc*.rpm ]; then
  rpm -qlp bc*.rpm | grep README
else
  echo "File not found"
fi

func_end

テスト用のスクリプトファイルに実行権を与えます。

[root@server ~]# chmod 700 tp.sh

5 bashdbのコマンド一覧

デバッグ対象のスクリプトファイルを引数にして、bashdbを実行します。

[root@server ~]# bashdb tp.sh
bash debugger, bashdb, release 4.4-1.0.1

Copyright 2002-2004, 2006-2012, 2014, 2016-2018 Rocky Bernstein
This is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.

(/root/tp.sh:11):
11:     func_start
bashdb<0>

helpコマンドは、bashdbのコマンド一覧を表示するコマンドです。

bashdb<6> 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..

helpに続けてコマンド名を入力すると、各コマンドの詳細情報が出力されます。

bashdb<10> help run
**run** [*args*]

Attempt to restart the program via an exec call.

See also:
---------

**set args**, **kill** and **quit**

Aliases for run: restart, R

6 ソースコードを表示する方法(list)

listコマンドは、ソースコードを表示するコマンドです。bashdbを実行した直後にlistコマンドを実行した結果を以下に示します。func_start関数の左側に"=>"の印が付いています。この印は、今から実行する行を示しています。

bashdb<11> list
  6:
  7:    function func_end() {
  8:      echo "END"
  9:    }
 10:
 11: => func_start
 12:
 13:    dnf download bc > /dev/null 2>&1
 14:
 15:    if [ -f bc*.rpm ]; then

listコマンドに引数を指定すると、引数に指定した場所からソースコードを表示できます。以下は1行目から表示した結果です。

** Line 22 is too large. File /root/tp.sh has only 21 lines.
bashdb<15> list 1
  1:    #!/usr/bin/bash
  2:
  3:    function func_start() {
  4:      echo "START"
  5:    }
  6:
  7:    function func_end() {
  8:      echo "END"
  9:    }
 10:

7 スクリプトをステップ実行する方法(step)

stepコマンドは、スクリプトをステップ実行するためのコマンドです。以下のように関数内のコードも実行します。あとで説明するnextは、関数内のコードはみかけ上実行しません。

stepコマンドを実行します。次に実行する処理がfunc_start関数であることがわかります。

bashdb<0> step
(/root/tp.sh:3):
3:      function func_start() {

stepコマンドを実行します。次に実行する処理echoコマンドであることがわかります。

bashdb<1> step
(/root/tp.sh:4):
4:        echo "START"

stepコマンドを実行します。echoコマンドを実行して、次にdnfコマンドを実行することがわかります。

bashdb<2> step
START
(/root/tp.sh:13):
13:     dnf download bc > /dev/null 2>&1

次に、stepコマンドに引数を指定してみます。引数はstepコマンドの実行回数を表します。ここでは、6行分実行してみます。

bashdb<3> step 6
/usr/share/doc/bc/README
(/root/tp.sh:8):
8:        echo "END"

8 スクリプトをステップ実行する方法(next)

nextコマンドはstepコマンドと違って、関数内のコードはみかけ上実行しません。まず、初期状態を確認します。func_start関数を実行するところです。

bashdb<0> list
  6:
  7:    function func_end() {
  8:      echo "END"
  9:    }
 10:
 11: => func_start
 12:
 13:    dnf download bc > /dev/null 2>&1
 14:
 15:    if [ -f bc*.rpm ]; then

次に、nextコマンドを実行します。func_start関数内のコードは表示されず、dnf コマンドを実行しようとしていることがわかります。

bashdb<1> next
START
(/root/tp.sh:13):
13:     dnf download bc > /dev/null 2>&1

9 スクリプトを最初から実行する方法(run)

runコマンドは、次に実行する処理をスクリプト先頭に変更するコマンドです。runコマンドを実行すると、スクリプト先頭のfunc_start関数を次に実行することがわかります。

bashdb<0> run
Restarting with: /usr/bin/bashdb tp.sh
bash debugger, bashdb, release 4.4-1.0.1

Copyright 2002-2004, 2006-2012, 2014, 2016-2018 Rocky Bernstein
This is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.

(/root/tp.sh:11):
11:     func_start

10 ブレークポイントを設定、削除する方法(break,delete)

10. 1 ブレークポイントを設定する方法(break)

4行目にブレークポイントを設定します。

bashdb<0> b 4
Breakpoint 1 set in file /root/tp.sh, line 4.

8行目にブレークポイントを設定します。

bashdb<1> b 8
Breakpoint 2 set in file /root/tp.sh, line 8.

設定したブレークポイントを確認します。ブレークポイント4行目と8行目に設定されていることがわかります

bashdb<5> info b
Num Type       Disp Enb What
----------------------------
1   breakpoint keep y   /root/tp.sh:4
2   breakpoint keep y   /root/tp.sh:8

10. 2 ブレークポイントを削除する方法(delete)

ブレークポイントの削除は、deleteコマンドで行います。deleteコマンドには、ブレークポイントの番号(Num)を指定します。

1番(Numが1)のブレークポイントを削除します。

bashdb<10> delete 1
Deleted breakpoint 1

ブレークポイントを確認すると、1番のブレークポイントが削除されたことがわかります。

bashdb<11> info b
Num Type       Disp Enb What
----------------------------
2   breakpoint keep y   /root/tp.sh:8

2番(Numが2)のブレークポイントを削除します。

bashdb<18> delete 2
Deleted breakpoint 2

ブレークポイントを確認すると、2番のブレークポイントが削除されたことがわかります。

bashdb<19> info b
No breakpoints have been set.

10. 3 ブレークポイントを一括削除する方法(delete)

ブレークポイントを一括で削除する場合は、deleteコマンドを引数なしで実行します。この方法で実行すると、全てのブレークポイントを一括で削除することができます。

ブレークポイントを確認します。ブレークポイントが2つ設定されていることがわかります。

bashdb<2> info b
Num Type       Disp Enb What
----------------------------
5   breakpoint keep y   /root/tp.sh:4
6   breakpoint keep y   /root/tp.sh:8

deleteコマンドを引数なしで実行して、ブレークポイントを一括で削除します。

bashdb<3> delete
Delete all breakpoints? (y/N): y
Deleted breakpoints: 5 6

ブレークポイントを確認します。ブレークポイントが全て削除されたことがわかります。

bashdb<6> info b
No breakpoints have been set.

11 プログラムの実行を再開する方法(continue)

continueコマンドは一時停止しているスクリプトの実行を再開するコマンドです。一時停止している状態で、continueコマンドを実行すると、スクリプトの実行が再開され、停止した場所から次のブレークポイント、もしくはスクリプトの終了まで実行されます。

listコマンドを実行して、これから実行するところを確認します。11行目のfunc_start関数であることがわかります。

bashdb<0> list
  6:
  7:    function func_end() {
  8:      echo "END"
  9:    }
 10:
 11: => func_start
 12:
 13:    dnf download bc > /dev/null 2>&1
 14:
 15:    if [ -f bc*.rpm ]; then

15行目にブレークポイントを設定します。

bashdb<1> b 15
Breakpoint 4 set in file /root/tp.sh, line 15.

continueコマンドを実行します。15行目まで処理が進んで停止したことがわかります。

bashdb<2> continue
START
Breakpoint 4 hit (1 times).
(/root/tp.sh:15):
15:     if [ -f bc*.rpm ]; then

12 変数の値を表示する方法(print)

printコマンドは、変数の値を表示するコマンドです。

デバッグ対象のスクリプトファイルを作成します。

[root@server ~]# vi tp.sh
[root@server ~]# cat tp.sh
#!/usr/bin/bash

x=10
for count in $(seq 5)
do
  echo $count
done

デバッグ対象のスクリプトファイルを引数にして、bashdbを実行します。

[root@server ~]# bashdb tp.sh

continueコマンドを実行して、スクリプトを最後まで実行します。

bashdb<0> continue
1
2
3
4
5
Debugged program terminated normally. Use q to quit or R to restart.

変数xの値を確認すると、10であることがわかります。

bashdb<1> print $x
10

変数countの値を確認すると、5であることがわかります。

bashdb<2> print $count
5

Z 参考情報

私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ