136
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Organization

byebugでRubyスクリプトをコマンドラインデバッグする

2016-01-16時点の情報。Rubyでコマンドラインデバッグする方法は何種類かあって、けっこう変化が大きいので最新情報を確認するようにしたい。byebugも半年でバージョンが5.0から8.2.1と大幅に上がっている。

gem名 説明
byebug 単体で使えるデバッガ
pry-byebug byebugをpryのプラグインとして組み込んだもの。作者はbyebugと同じ人。pry-debuggerからフォークした
pry-debugger Ruby 1.*用。以前はruby-debugという名前だった

Railsとかでなく単体のRubyスクリプトをデバッグすることを想定。

ちなみにRails(4.2.6)ではrails newした時点でGemfileに

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug'
end

が書かれているので、ソースコード中のどこでもbyebugと書けばそこで停止してデバッグができる。

単体スクリプトの場合は3つのやり方がある。
自分は最近は1-2「ソースコードの中にbyebugを書く方法」を使っている。

1.byebug単体で使う

1-1.シェルからbyebug ファイル名で起動する

1-2.require 'byebug'し、ソースコードの中にbyebugと書くとそこがブレークポイントになる

2.pry-byebugを使う

  • require 'pry'し、ソースコードの中にbinding.pryと書くとそこがブレークポイントになる
  • byebug単体で使う場合と比べて利用できるコマンドが少ない
  • カラー表示がうれしい
  • listコマンドがない(pry自身の@コマンドで代用可)
  • backtraceコマンドがない(pry自身のpry-backtraceコマンドで代用可)
  • displayコマンドがない
  • pry-stack_explorerといっしょに使えない
  • pry-rescueといっしょに使えるかも怪しい

byebugコマンドを使う方はソースコードを変更せずに実行できるというメリットがあるが、実際は実行のたびにブレークポイントを張り直すのが面倒。ソースコードの中にbyebugを書く方が手軽だと思う。

pry-byebugはカラフルなのがうれしいが、byebugの方がデバッグコマンドは充実している(現時点ではpry-byebugがbyebugに追いついていない。しかしbyebugのコマンドをpry-byebugでも使えるようにするのはそう難しくないので、しばらくしたらpry-byebugを使う方が便利になっているかもしれない)。

byebug単体での使い方

公式ドキュメント:GUIDE.md
この公式ドキュメントも細かい間違いが多い。

起動:

$ byebug hoge.rb

最初は実行が停止した状態なのでnまたはsでステップ実行する。
またはbreak NでN行目にブレークポイントを張ってcで実行継続する。

コマンド(よく使うもののみ)

※単にエンター押下すると直前のコマンドを繰り返し実行できる

●実行関連
n               ステップオーバー(next)
s               ステップイン(step)
c               実行継続(continue)
fin             ステップアウト(finish)
restart         最初から実行し直す

●ソースコード
l               ソースコードを表示する(list)。繰り返し実行することでどんどん先を表示する
l=              現在の行を中心に表示する
l-              前の方を表示する
l 1-10          1~10行目を表示する
※listコマンドはどうも使い勝手がよくないので、edでエディタを起動してしまう方がいいかもしれない
ed              エディタを起動する(edit)。環境変数EDITORを参照する

●変数表示
p 変数名        変数の中身を表示
変数名 = 値     変数に代入
v l             ローカル変数表示
disp 変数名     変数をウォッチする
i d             ウォッチしている変数一覧
undisp N        N番目のウォッチ変数を削除

●スタックフレーム
bt              スタックフレーム表示(backtrace, where)
up              フレーム1つ上に移動
down            フレーム1つ下に移動

●ブレークポイント
b N             N行目にブレークポイントを張る(break)
i b             ブレークポイントを表示する
del N           N番目のブレークポイントを削除する 

●ヘルプ
h               ヘルプ表示(help)
h COMMAND       コマンドのヘルプを表示

●irb, pry
irb             irbを起動
pry             pryを起動

エンターだけ押すと直前のコマンドを繰り返し実行する。
byebugに無いコマンドを入力するとRubyのコードとして解釈される。

saveでブレークポイント等のセッション情報を保存しておいてsourceで読み込むことができる。しかしsourceで引数にファイル名を指定しないといけなかったり、どうも使い勝手が良くない。byebug自体を何度も起動しなおすのでなく、restartコマンドを使ってスクリプトの方だけ再実行するのがいいかもしれない。

ソースコード中にbyebugと書いたブレークポイントを無効にする

そのような方法はない。
あらかじめ次のように書いておき、実行時に $nobyebug = true と代入する方法が代替案になる。

byebug unless $nobyebug

post-mortem(検死)モード

デバッグ対象のスクリプトでハンドルされない例外が発生したとき、通常はbyebugも終了するが、byebug --post-mortem hoge.rbで起動しておくとデバッグセッションを続けられるようになる。
例外発生がFixnumなど組み込みクラスの中だとpで変数を表示できなかったりするので、btでカレントフレームを確認して必要に応じてupでフレームを移動する。

post-mortemモードはruby >= 2.2.4で正常に動かないらしい。
2.3.0で少し試したところではちゃんと動いていたが…

pry-byebugの使い方

というか設定。

~/.pryrc
if defined?(PryByebug)
  # このエイリアスにより、pryでb = 123などとするとエラーになる。スペースを入れずにb=123とすればよい
  Pry.commands.alias_command 'b', 'break'
  Pry.commands.alias_command 's', 'step'
  Pry.commands.alias_command 'n', 'next'
  Pry.commands.alias_command 'fin', 'finish'
  Pry.commands.alias_command 'fr', 'frame'
  Pry.commands.alias_command 'cont', 'continue'
  Pry.commands.alias_command 'ed', 'edit -c'
end

Pry.commands.alias_command 'bt', 'pry-backtrace'

# エンターで直前のコマンドを繰り返し実行できるようにする
Pry::Commands.command /^$/, "repeat last command" do
  _pry_.run_command Pry.history.to_a.last
end

これらのエイリアスとあと@updownを使えば一通りのことはできる。

@       現在行の周辺を表示
@ 10    現在行の前後10行を表示
@ -m    現在のメソッド全体を表示

byebugの動作確認に使ったスクリプト

デバッグ対象として使ったスクリプト

hoge.rb
$g = 123 

def aaa 
  var_a = "あいうえお"
  puts "START aaa"
  bbb(var_a)
  puts "END aaa"
end

def bbb(x)
  var_b = "かきくけこ"
  puts "START bbb"
  ccc(x, var_b)
  puts "END bbb"
end

def ccc(y, z)
  puts "START ccc"

  sum = 10
  a = 10
  #a = nil  # コメントを解除すると例外が発生するようになる。post-mortemモードの確認用
  3.times do |i| 
    sum += i
    sum += a
  end 
  puts "END ccc"
end

aaa
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
136
Help us understand the problem. What are the problem?