Ruby: byebugからruby/debugへの移行ガイド(翻訳)
新しいデバッガに乗り換えてデバッグプロセスを変更するのがつい億劫になることもあるでしょう。本記事によって、皆さんがruby/debug
に親しんでスムーズに移行する助けになることを願っています。
以下、debug
はruby/debug
を指します。
免責事項
🔗 debug
を使うメリット
個別の機能を解説する前に、debug
を使うメリットについて簡単に触れておきたいと思います。
1. 出力がカラー化されている
2. メソッドやブロックの引数をバックトレースできる
3. Zeitwerkとの互換性問題は解決済み
4. ブレークポイントやトレーサーが強力
5. リモートデバッグ機能やVSCode統合が便利
詳しくは以下の別記事をどうぞ。
参考: Setup ruby/debug with VSCode
🔗 debug
の現在のデメリット
- スレッド制御があまり柔軟でない
- Fiberとの連携がまだ弱い
pry-byebug
のようなpry
統合がまだない- プロジェクト単位のコンフィグは利用不可(セキュリティ上の理由)
byebug
とdebug
の比較は以下のとおりです。
🔗 インストール
原注
Ruby 3.1にはdebug
v1.4が付属していますが、常に最新リリースを使うことをおすすめします。
byebug | debug | |
---|---|---|
サポートするRubyバージョン | 2.5以降 | 2.6以降 |
gemのインストールコマンド | gem install byebug |
gem install debug |
Bundlerでの記法 | gem "byebug" |
gem "debug" |
依存関係 | なし | irb 、reline |
C拡張 | 利用可能 | 利用可能 |
最新バージョン | 11.1.3(2020/04/23) | 1.6.2(2022/08/10) |
🔗 デバッガの起動方法
byebug | debug | |
---|---|---|
シェルでの起動 | byebug foo.rb |
rdbg foo.rb |
デバッガ構文での起動 | byebug |
binding.break 、binding.b 、debugger (いずれも同じ) |
require での起動 |
なし | require "debug/start" |
🔗 ユーザーエクスペリエンス機能
byebug | debug | |
---|---|---|
カラー出力 | なし | あり |
コマンド履歴 | あり | あり |
ヘルプコマンド | h 、help |
h 、help |
ソースファイル編集コマンド | edit |
edit |
🔗 評価
REPLでのコード評価方法はbyebug
とdebug
でだいたい同じです。
- 式がコンソールコマンドと一致しない場合(
my_method(arg)
など)、Rubyコードとして評価される - 式がコンソールコマンドと一致する場合(
n
など)、コンソールコマンドで評価を実行できる
byebug | debug | |
---|---|---|
デバッガ実行コマンド | <コマンド> |
<コマンド> |
式とコマンドの衝突回避方法 | eval <式> |
pp <式> 、p <式> 、eval <式> |
🔗 フロー制御とフレーム移動
debug
のステップコマンドはbyebug
と同じなので、byebug
ユーザーは新しい操作を学ばずにdebug
に乗り換えられます。
byebug | debug | |
---|---|---|
ステップイン | s 、step |
s 、step |
ステップオーバー | n 、next |
n 、next |
終了 | fin 、finish |
fin 、finish |
<id> フレームに移動 |
f <id> 、frame <id> |
f <id> 、frame <id> |
上のフレームに移動 | up |
up |
下のフレームに移動 | down |
down |
n フレーム上に移動 |
up <n> |
なし |
n フレーム下に移動 |
down <n> |
なし |
プログラムを継続実行 | c 、continue |
c 、continue |
デバッガ終了 | q 、quit |
q 、quit |
プログラムを強制終了 | kill |
kill |
🔗 スレッド制御
上述したように、debug
はサスペンド中にすべてのスレッドを停止するので、現時点ではスレッド単位の管理はできません。そのため、スレッドについてはよりシンプルなコマンドが用意されています。
byebug | debug | |
---|---|---|
サスペンド時のスレッド | 現在のスレッドのみ | すべてのスレッド |
すべてのスレッドをリスト表示 | th l 、thread l |
th 、thread |
スレッドid に切り替える |
th switch <id> 、thread switch <id> |
th <id> 、thread <id> |
スレッドを停止する | th stop <id> 、thread stop <id> |
なし |
スレッドを再開する | th resume <id> 、thread resume <id> |
なし |
🔗 ブレークポイント
byebug
も適切なブレークポイントをサポートしていますが、debug
は以下のようにさらにレベルアップしています。
pre:
オプションやdo:
オプションを用いてブレークポイントでコマンドを実行できるpath:
オプションを用いて呼び出し元ベースの条件付きトリガーをサポート- 特殊な
catch
ブレークポイントやwatch
ブレークポイントをサポート
🔗 1. ブレークポイントの設定
byebug | debug | |
---|---|---|
行を指定して設定 | b <行> 、break <行> |
b <行> 、break <行> |
ファイルと行を指定して設定 | b <ファイル>:<行> 、break <ファイル>:<行> |
b <ファイル>:<行> 、break <ファイル>:<行> |
メソッドに設定 | b <クラス名>#<メソッド名> 、break <クラス名>#<メソッド名> |
b <クラス名>#<メソッド名> 、break <クラス名>#<メソッド名> |
条件を指定して設定 | b ... if <式> 、break ... if <式> |
b ... if <式> 、break ... if <式> |
パスの条件を指定して設定 | なし | b ... path: /パス/ 、break ... path: /パス/ |
指定のコマンドを実行して継続 | なし | b ... do: <コマンド> 、break ... do: <コマンド> |
停止前に指定のコマンドを実行 | なし | b ... pre: <コマンド> 、break ... pre: <コマンド> |
例外にブレークポイントを設定 | なし | catch <例外クラス> |
インスタンス変数を監視するブレークポイント | なし | watch <@インスタンス変数> |
🔗 2. ブレークポイントの管理
byebug | debug | |
---|---|---|
ブレークポイントをすべて表示 | info breakpoints |
b 、break |
ブレークポイントを設定 | b ... 、break ... |
b ... 、break ... |
ブレークポイントを削除 | del <id> 、delete <id> |
del <id> 、delete <id> |
すべてのブレークポイントを削除 | del 、delete |
del 、delete |
🔗 情報表示
🔗 1. バックトレース
debug
のバックトレースには、メソッド呼び出しの値やブロック引数の値が含まれます。このちょっとした改良のおかげで、フレーム間で値を手動でinspectせずに済みます。
フィルタ機能を活用することで、フレームワークやライブラリのフレームを無視して、関連するフレームだけを表示できます。
byebug | debug | |
---|---|---|
バックトレースを表示 | where 、backtrace 、bt |
backtrace 、bt |
バックトレース内でメソッドやブロックの引数を表示 | なし | あり |
バックトレースのフィルタ | なし | bt /正規表現/ |
バックトレースの上限数を指定 | なし | bt <n> |
🔗 2. 変数・定数
byebug | debug | |
---|---|---|
ローカル変数を表示 | var local |
info l |
インスタンス変数を表示 | var instance |
info i |
グローバル変数を表示 | var global |
info g |
定数を表示 | var const |
info c |
引数のみを表示 | var args |
なし ( info l でできる) |
変数・定数を名前でフィルタ | なし | info ... /正規表現/ |
🔗 3. メソッド
debug
にはオブジェクトのメソッドをリスト表示する専用のコマンドはありませんが、irbやpryに似たls
コマンドが利用できます。
byebug | debug | |
---|---|---|
obj.methods |
method instance obj |
なし |
obj.methods(false) |
method obj.class |
ls obj |
🔗 トレース機能
debug
のトレース機能については別途記事を書くつもりですが、それまでのつなぎとして、特に以下のトレース機能を折に触れて試してみることをおすすめします。
trace exception
: コードで発生する例外を監視します。アプリケーション内部で発生する例外がrescue
される様子を見たら驚くでしょう。trace object <式>
: オブジェクトがメソッド呼び出しを受信する様子や、オブジェクトがメソッド呼び出しに渡されるなどの活動を監視します。
byebug | debug | |
---|---|---|
行トレーサー | set linetrace |
trace line |
グローバル変数トレーサー | tarcevar |
なし |
複数のトレーサーを利用する | なし | あり |
メソッド呼び出しトレーサー | なし | trace call |
例外トレーサー | なし | trace exception |
Rubyオブジェクトトレーサー | なし | trace object <式> |
トレース出力のフィルタ | なし | trace ... /正規表現/ |
トレーサーを無効にする | set linetrace false |
trace off [トレーサー種別] |
idを指定してトレーサーを無効にする | なし | trace off <id> |
🔗 コンフィグ
debug
ではニーズに応じてさまざまなコンフィグ機能を利用できます。ただしセキュリティ問題が懸念されるため、プロジェクト単位でのrcファイルはサポートしていません。
byebug | debug | |
---|---|---|
コンフィグをすべて表示 | なし | config |
特定のコンフィグを表示 | show <コンフィグ名> |
config show <コンフィグ名> |
コンフィグを設定 | set <コンフィグ名> <値> |
config set <コンフィグ名> <value> |
RCファイル名 | .byebugrc |
.rdbgrc (またはRubyスクリプト形式の .rdbgrc.rb ) |
RCファイルの置き場所 | $HOME およびプロジェクトルート |
$HOME |
🔗 リモートデバッグ
開発環境をコンテナ化すると標準I/O(stdio)に常にアクセスできるとは限らなくなるので、リモートデバッグ機能が非常に重要になってきます。リモートデバッグ機能は、VSCodeやChromeなどのさまざまなデバッグクライアントに接続するうえでも重要です。
リモートデバッグ機能が必要なら、debug
に乗り換えるのがベストです。
byebug | debug | |
---|---|---|
TCP/IP接続 | あり | あり |
Unixドメインソケット接続 | なし | あり |
Debug Adapter Protocol(DAP)経由のVSCode統合 | なし | あり |
Chrome DevTools Protocol(CDP)経由のChrome統合 | なし | あり |
まとめ
多くの開発者にとって、byebug
からdebug
への乗り換えはほとんど手間がかからないはずです。しかもdebug
に乗り換えることでかなりの生産性向上が見込めます。
もちろんbyebug
は素晴らしいデバッガであり、長年コミュニティに大きく貢献してきました。しかし近年は開発のテンポが低下しており(最後のリリースは2年前です)、debug
はRubyコアチームによって定期的に更新されているので、両者のギャップは開く一方です。
そういうわけで、debug
を手元に常備して強力な機能を知っておくと、長期的に生産性を高めるための大きな投資となります。
参考資料
- Debugger commands comparison sheet by @ko1(訳注: 現在は公開されていません)
- Byebug公式ガイド
- ruby/debug公式ドキュメント
概要
原著者の許諾を得て翻訳・公開いたします。