linuxBean14.04(27)Geanyとシェルスクリプトのデバッグ

前の関連記事:linuxBean14.04(26)Geanyのビルドコマンドの設定


シェルスクリプトのデバッガbashdbを見つけてDDDと組み合わせればGUIでデバッグできる、と思ったのですがDDDが思ったほど便利ではなかったので単にbashdbをGeanyのVTEから使うだけにしました。
(2016.5.25追記。もっとGUIで操作できるBashEclipseを使うことにしました。linuxBean14.04(116)BashEclipseでシェルスクリプトのデバッグ参照。)

シェルスクリプトのデバッガbashdbとDDD(Data Display Debugger)のインストール


Programing Bible:シェルスクリプトのデバッグツール、bashdb (1/3) - ITmedia エンタープライズ

bashdbの使い方についてはこのページがわかりやすかったです。
(しかしbashdbの起動はbash --debugger foo.shではできず、bash --debug /usr/bin/bashdb foo.shで起動できました。)

フィボナッチの数列のシェルスクリプトの例もついています。

早速Synapticパッケージマネージャからbashdbをインストールしました。


4.2.0.8がインストールできました。

bashdbの開発元のBASH with Debugger and Improved Debug Support and Error Handlingを見るとDDD(Data Display Debugger)と併用すればGUIで使えるみたいなのでDDDもインストールしました。


ついでにddd-docもインストールしましたが結論としてはDDDは使わないことになりました。

linuxBeanのshはbashではなくdash


Programing Bible:シェルスクリプトのデバッグツール、bashdb (2/3) - ITmedia エンタープライズにあるフィボナッチの数列のシェルスクリプトの例をfib.shというファイルに保存しました。

ファイルマネージャでfib.shファイルがあるフォルダを開いて、ツール→現在のフォルダを端末で開く。

実行のパーミッションを許可していると、./fib.shでfib.shが実行できます。

実行のパーミッションがなくても、bash fib.shかsh fib.shでfib.shが実行できます。

どちらも同じ結果が出力されるはずですが、linuxBean、、、というかUbuntuではshはbashではなくdashが使われています。(Ubuntuの/bin/shはbashではなくdash | Siguniang's Blog)
(2016.5.30追記。Terminalのシェルはbashです。linuxBean14.04(114)「./myscript」「myscript」「source myscript」「. myscript」の違い参照。)

man shとするとbashではなくdashのマニュアルが表示されることでわかります。

bash -x fib.shとすると実行したコマンドがすべて出力されます。

前略
+++++++ '[' 0 -le 1 ']'
+++++++ echo 0
++++++ r=0
++++++ echo 1
+++++ r=1
+++++ echo 3
++++ r=3
++++ echo 8
+++ r=8
+++ echo 21
++ r=21
++ echo 55
+ result=55
+ echo 'i=10 result=55'
i=10 result=55

sh -x fib.sh

前略
+ [ 0 -le 1 ]
+ echo 0
+ r=0
+ echo 1
+ r=1
+ echo 3
+ r=3
+ echo 8
+ r=8
+ echo 21
+ r=21
+ echo 55
+ result=55
+ echo i=10 result=55
i=10 result=55

dashdbというのはないようなので、bashdbを使ってシェルスクリプトのデバッグをします。

princessleia.com/plug/2008-JP_bash_vs_dash.pdfにbashとdashの違いが書いてあります。

dashの方がbashより機能が少し少ないようですので、dashのスクリプトをbashdbでデバッグしても問題ないようです。

DDDでシェルスクリプトをデバッグする


dddは豆ボタン→プログラミング→Data Display Debuggerで起動できますがこの場合はデバッガはgdbなのでシェルスクリプトには使えません。

gdbがインストールされていない場合はデバッガーがないといわれて終了するしかありません。

ddd --debugger /usr/bin/bashdb

これでシェルスクリプトのデバッガbashdbを使ってdddが起動できました。


下の枠がTerminalになっているのでbashdbを起動します。

bash --debug /usr/bin/bashdb fib.sh

bashdb  fib.sh

いずれの方法でも起動できましたが、ディレクトリを移動する方法がわからないので、シェルスクリプトはカレントディレクトリのものかフルパスで指定しないといけません。

ペーストはできないのでちょっと不便です。


Step(Step into)とNext(Step over)はツールパネルのボタンで実行できますが、それぐらいしかできないので結局コマンドを使ったほうが便利でした。

「s」でStep into、「n」でStep over、「x 変数名」で変数内容の表示、の3つがわかればなんとかなりそうです。

終了するときはqでbashdbを終わらせてからFile→Exitにします。

DDDを使ってみたがDataウィンドウの変数の値が消えてしまうので使用を断念


GeanyのVTEで使う場合と比べてよい点は現在のコードの位置を矢印で知らせてくれることです。

GUIでのブレークポイントの設定やData Windowでの変数の表示には未対応のようです。


変数をダブルクリックしたり、右クリックでDisplayとするとDataウィンドウに変数の値が表示されるのですが、NextやStepで次の行にいくとDataウィンドウの表示が消えてしまいます。

python-pygmentsをインストールするとEdit→Bash SettingsでSyntax highlighting of source listings is on.がオンにできるようになりますが、どこに反映されているのかわかりませんでした。(Packages/bashdb – VineSeed)

Dataウィンドウで変数の値の変化が追えたら便利かな、と思いましたがそれができないのでもうDDDを使うのはあきらめました。

Geanyのビルドコマンドからbashdbを呼び出せるようにする


Geanyのメニューからbashdbを呼び出せるようにするだけでbashdbの操作自体はすべてCUIになります。

linuxBean14.04(26)Geanyのビルドコマンドの設定と同様にします。


まず実行コマンドをShコマンドで設定しました。

テスト段階でいちいちshファイルのパーミッションを変更しなくても実行できるように、sh %f で実行するようにしました。


ツールバーのコンパイルボタンをクリックするとコンパイラタブに結果が出力されます。

/usr/share/geany/filetypes.shをroot権限で編集します。
#run_cmd="./%f"

[build-menu]
EX_00_LB=bashdbでデバッグ
EX_00_CM= bash --debug /usr/bin/bashdb --highlight %f
56行目をコメントアウトして58行目以降をファイルの最後に追加します。


python-pygmentsをSynapticパッケージマネージャでインストールしておいて、bashdbを--highlightをつけて起動するとシンタックスハイライトができます。
(2016.5.22追記。pythonコマンドがPython3.xになっていると動きません。pythonコマンドの切り替え方法についてはlinuxBean14.04(115)pythonコマンドをpipコマンドとともに切り替える参照。)

Geanyを再起動します。


拡張子shのファイルを開いているときだけビルドメニューに「bashdbでデバッグ」があるはずです。

(2015.150.24追記。このままではrootのフォルダにあるファイルのデバッグができないのでrootで起動するGeanyのランチャを作成しました。


ランチャー名はGeany (root) 、コマンドはgksudo geany %F にしました。)

fib.shをbashdbでデバッグする


fib.shで「bashdbをデバッグ」を実行すると、端末にbashdbのプロンプトがでてきます。
(編集→設定、端末で、VTEでプラグラムを実行、にチェックをいれている場合)


スクリプト部分がシンタックスハイライトされていますね。

最初は端末にカーソルのフォーカスが来ていないことに注意が必要です。

私は何回もソースファイルの方を編集してしまっています。

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.

h コマンド名、でさらに詳しい解説がでてきます。

bashdbによるシェルスクリプトのデバッグ - 理想未来はどうなった?の解説がわかりやすいです。

BASH Debuggerの4. BASH Debugger Command Referenceにコマンドリファレンスがあります。

私がよく使いそうなところだけ見てみます。

エイリアスというのはコマンドの短縮形です。

とりあえずnext(エイリアスn)を最初に入力してEnterを押して進んでいきます。

4.9 Examining Data (‘print’, ‘examine’, ‘info variables’)

print expr (exprを省略すると前回と同じexprを使用。) エイリアス pr expr

echoと同様に働きます。変数名の前に$が必要です。

examine expr  (exprを省略すると前回と同じexprを使用。) エイリアス  expr

expr が変数や配列のときはdeclare -p で表示します。

expr が関数のときはdeclare -f で表示します。

expr が変数でも式でもないときはletで表示を試みて、それでエラーが返るときはprintで出力します。

V [!][pattern] 

変数一覧を出力します。

パターンなしでVだけでやってみると、デバッガとか環境変数とかがたくさん出力されました。

V JAVA* などパターンを指定して、特定の変数の値を知りたいときに使うのがよさそうですね。

出力完了まで時間もかかります。

4.10 Automatic display (‘display’, ‘undisplay’)

display expr 

expr を登録してプログラムが止まるたびにprint expr を実行してくれます。

printで出力するので変数名の前には$が必要です。

登録ID: expr = 値

この形式で出力します。

display 

引数がない場合はプログラムが止まったときと同様に登録されたリストを表示します。

undisplay 登録ID 

登録IDをリストから除去します。引数は複数もてます。

disable display 登録ID 

undisplayと違って無効にするだけで、enable displayで有効にできます。

info display エイリアス i display

disableされた登録IDも表示させます。

bashdb<(25)> info display
Auto-display statements now in effect:
Num Enb Expression        
4     0 $result
5     1 $i

Enbが0になっているNum4がdisableされた登録IDです。

enable display 登録ID

disableした登録IDを有効にさせます。

4.4.1.1 Setting breakpoints (‘break’ ‘tbreak’)

break function エイリアス b function

関数functionに入ったときに止まります。

break linenum エイリアス linenum 

指定行番号に達すると止まります。その行のコマンドが実行される前に止まります。

break function/linenum if cond  エイリアス function/linenum if cond

condが成立した場合にfunction/linenumで止まります。

tbreak function/linenum (if cond)

使い捨てのブレークポイントの設定。  

現在読み込んでいるファイル以外にブレークポイントを設定したいときはb ファイル名:行番号 という方法で設定します。

info break エイリアス i break 

ブレークポイント一覧を表示。

4.4.1.4 Deleting breakpoints (‘clear’, ‘delete’)

delete [ブレークポイント番号]

info breakで得られるブレークポイント番号を引数にした場合、そのブレークポイントを削除します。

引数がない場合はすべてのブレークポイントを削除します、、、と書いてあるのですが何も起こりませんでした。

clearでも削除できず、ブレークポイントをすべて削除するには1つずつ削除するしかないようです。

/usr/share/bashdb/lib/processor.shにすべてのブレークポイントを削除するコマンドが載っていました。
      # Delete all breakpoints.
      D | deletea | deleteal | deleteall )
      _Dbg_clear_all_brkpt
      _Dbg_last_cmd='deleteall'
      ;;
D/deletea/deleteal/deleteall ですべてのブレークポイントが削除できました。
  _Dbg_write_journal_eval "_Dbg_brkpt_count=0"
  _Dbg_msg "All Breakpoints have been cleared"
}
削除しても何もメッセージがでないのは/usr/share/bashdb/lib/break.shの195行目に上記を追加するとよいです。

4.4.1.5 Disabling breakpoints (‘disable’, ‘enable’)

disable [ブレークポイント番号]

一時的にブレークポイントを無効にします。

enable [ブレークポイント番号]

無効にしたブレークポイント有効にします。

4.4.1.6 Break conditions (‘condition’)

条件付ブレークポイントの条件変更ができるようですが、私が自分でやる程度ではブレークポイントの設定をし直せば事足りるように思います。

4.4.1.2 Setting watchpoints (‘watch’, ‘watche’)

watch var エイリアス W var

var の変数が変化すると止まります。

fib.shでwatch iとするとうまく動きませんでした。代入文がないからでしょうか。

watch resultはちゃんと動きました。

次のwatcheは変数指定でも動くのでwatchは使わずwatcheだけで事足りそうです。

watche expr エイリアス We expr

expr が成立したときに止まります。

exprが変数のときはwatchと同じように動作します。

fib.shでやってみるとwatchのときと同様にwatchではちゃんと動きましたが、iではうまく動きませんでした。

info watch (4.4.1.1 Setting breakpoints (‘break’ ‘tbreak’)) エイリアス i watch

ウォッチポイント一覧を表示します。

delete [ウォッチポイント番号]w

番号で指定したウォッチポイントの削除ができます。

削除しても何もメッセージがでないのをでるようにするには、/usr/share/bashdb/lib/break.shの448行目に以下を追加します。
    _Dbg_write_journal_eval "unset _Dbg_watch_count[$del]"
    _Dbg_msg "Watchpoint entry $del has been deleted."
  else
watchを引数無しで実行するとすべてのウォッチポイントが削除できました。

disable/enable [ウォッチポイント番号]w

ブレークポイントと同様にウォッチポイントの無効/有効の切替ができるのですが、ソースの修正が必要でした。

/usr/share/bashdb/lib/break.shの154行目のdelをiに書き換えます。
        _Dbg_enable_disable_watch $on $en_dis ${i:0:${#i}-1}#_Dbg_enable_disable_watch $on $en_dis ${del:0:${#del}-1}
書き換えはrootで行う必要があります。

4.4.2 Resuming Execution (‘step’, ‘next’, ‘finish’, ‘skip’, ‘continue’, ‘debug’, ‘return’)

step エイリアス s

ステップイン。

next エイリアス n

ステップオーバー。

continue エイリアス c/cont

リジューム。

3.1 Starting your script

run エイリアス R/restart

デバッグしているスクリプトの再起動。

4.6 Examining Source Files (‘list’)

list エイリアス l

現在のスクリプトの位置を示します。

4.3 Quitting the BASH debugger (‘quit’, ‘kill’)

quit エイリアス q/exit

bashdbの終了。

参考にしたサイト


Programing Bible:シェルスクリプトのデバッグツール、bashdb (1/3) - ITmedia エンタープライズ
フィボナッチの数列の例を実際にbashdbでデバッグしています。

BASH with Debugger and Improved Debug Support and Error Handling
Bashのデバッガーbashdbの開発元。

DDD - Data Display Debugger - GNU Project - Free Software Foundation (FSF)
デバッガーのGUIフロントエンド。思ったように動きませんでした。

Ubuntuの/bin/shはbashではなくdash | Siguniang's Blog
linuxBeanのシェルもUbuntuと同じdashです。

princessleia.com/plug/2008-JP_bash_vs_dash.pdf
dashとbashの違い。dashの方がbashより機能が少し少ないようです

Packages/bashdb – VineSeed
python-pygmentsをインストールしてbash --highlightで起動するとシンタックスハイライトできました。

Man page of BASH
bashのマニュアル。

dash(1) - Linux manual page
dashのマニュアル。

bashdbによるシェルスクリプトのデバッグ - 理想未来はどうなった?
bashdbの使い方の解説。

BASH Debugger
bashdbのマニュアル。

次の関連記事:linuxBean14.04(28)シェルスクリプトbashdb

PR

0 件のコメント:

コメントを投稿