🏃‍♂️

bin/devでRailsサーバー起動時にそのセッションでデバッグ出来るようにrun-ptyを導入した

2025/02/17に公開

🤔 問題意識

Railsアプリをjsbundling-railssolid_queueなどを用いて開発するとき、デフォルトではbin/devを実行することによって複数プロセスが立ち上がるかと思います。

ただdebug gemを使ってデバッグセッションを開始しようとするとそのままではうまくいかず、別途ターミナルを開いてrdbgで接続をする必要があるかと思います。
それは少し面倒だなと思っていたのでなにか別アプローチはないかと思っていたところ、run-ptyを利用した複数プロセス管理が出来ることがわかったので今回はそれを使ってみようと思います。
https://github.com/lydell/run-pty

🎁 導入

それでは早速入れていきましょう。
run-ptyはpackage.json経由でインストールするのでyarnを使って追加していきます。別のマネージャーを使っている場合はここを変えてもらえればよいはずです。

yarn add -D run-pty

これでインストールは完了しました。

実行したいプロセスはプロジェクトルートにrun-pty.jsonというファイルを作成して記述していきます。
ひとまず簡易的なJSONファイルを作成することで試してみようと思います。
以下のファイルではrails serverの起動とsolid_queueのjobを起動させるためのプロセスを立ち上げます。

run-pty.json
[
  {
    "command": ["bin/rails", "server"]
  },
  {
    "command": ["bin/jobs"]
  }
]

ファイルを上記のように設置出来たら動かしてみましょう。

yarn run-pty run-pty.json

このように実行すると以下の画像のようにダッシュボードが立ち上がります。

rails serverの状況が知りたいので1を押す(または1部分をクリックする)とrails serverのログが流れてきます。

🟢 bin/rails server
=> Booting Puma
=> Rails 8.0.1 application starting in development
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 6.6.0 ("Return to Forever")
* Ruby version: ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +YJIT +PRISM [arm64-darwin24]
*  Min threads: 3
*  Max threads: 3
*  Environment: development
*          PID: 47071
* Listening on http://127.0.0.1:5500
* Listening on http://[::1]:5500
Use Ctrl-C to stop

[ctrl+c] kill (pid 47071)
[ctrl+z] dashboard

この画面でCtrl+cを押すとrails serverのみプロセスを切ることが出来ます。
restartするにはまた1を押してEnterを押すとリスタートすることが出来ます。

それではログに書いてあるとおり、Ctrl+zを押してダッシュボードに戻りましょう。Ctrl+zを押すとまたダッシュボードに戻ってきます。

すべてのプロセスを切るためにはダッシュボード画面でCtrl+cを押すとすべて切ることが出来ます。
これで複数プロセスを同時に立ち上げることが出来ました。またここではやっていないのですが当初の問題意識にあったdebug gemを使ったbinding.irbでデバッグする場合もrails serverのプロセスに入ればその場でインタラクティブに操作が出来るのでrdbgで接続をしなくてもデバッグ出来るようになりました🎉

最後にbin/devで起動出来るようにファイルの中身を書き換えておきましょう。

bin/dev
#!/usr/bin/env ruby
exec "yarn", "run-pty", "run-pty.json", *ARGV

お疲れ様でした😁

その他オプション

run-pty.jsonはダッシュボードの見た目などのカスタマイズが出来るようになっています。全てのオプションはGitHubのREADMEを見てほしいのですが、少しわかりづらかった部分を書いていきます。
https://github.com/lydell/run-pty

run-pty.jsonはもう少し細かくカスタマイズすることが出来ます。例えば以下の通りです。

run-pty.json
[
  {
    "command": ["bin/rails", "server"],
    "status": {
      "Listening on": null
    },
    "defaultStatus": ["⏳", "S"]
  },
  {
    "command": ["yarn", "build", "--watch"],
    "status": {
      "\\[watch\\] build finished": null
    },
    "defaultStatus": ["⏳", "S"]
  },
  {
    "command": ["yarn", "build:css", "--watch"],
    "status": {
      "Done in": null
    },
    "defaultStatus": ["⏳", "S"]
  }
]

それぞれの項目を見ていきます。
まずcommandに関しては簡易的なものと変わらないので省略します。
次にstatusです。statusには複数のキー・バリューが指定出来て、キーに一致したログが流れてきたときにダッシュボードに絵文字、もしくは文字を設定することが出来ます。
例えばbin/rails serverコマンドを打ったときに"Listening on"という文字列が流れてきたらnull、つまりデフォルトで成功として定義されている🟢が表示されます。
例えば "Listening on": ["🚀", "S"]のように定義すると"Listening on"という文字列がログに流れてきたらダッシュボードで🚀が表示されます。
バリューの2つ目の文字列は何かというと、絵文字が無効化されている環境(WindowsやNO_COLOR環境変数が定義されている)ときに表示される文字になります。
最後にdefaultStatusですがこれは起動しているときに表示されるものになります。バリューの1つ目の絵文字が表示され、先程と同様に絵文字が無効化されている環境のときは2つ目の文字列が表示されます。

このような設定を使うとダッシュボードでそれぞれのプロセスでエラーが出たときの表示を変えたりすることが出来るので便利かなぁと思います。

📒 参考文献

自分が調べているときにrailsのissueでもforemanから別のものはないか検討しているissueがありました。
https://github.com/rails/rails/issues/52459
あまり依存関係は増やしたくないそうなので今回紹介したrun-ptyを使った方法は受け入れられないとは思いますが、overmindというgemは知らなかったので勉強になりました。
https://github.com/DarthSim/overmind

Discussion