Edited at

[PHP] Xdebug のリモートデバッグ、理解していますか?

PHP のデバッグツールである Xdebug にはリモートデバッグという機能があります。

…というのは言うまでもなく、広く知られていると思います。

しかし、Xdebug の設定をなんとなくコピペで済ませたりしていないでしょうか?


Xdebug のリモートデバッグ設定、理解していますか?

日本語のサイトを検索すると「 xdebug.remote_enable=1 にして、xdebug.remote_host を xxx にして…」と設定だけが淡々と書かれた情報が多いです。

しかし、設定項目について、それぞれの意味を理解していないとトラブル時の対処が難しくなります。


リモートデバッグとは何か?

リモートデバッグ (Remote Debugging) とは、実行中の PHP とは別の場所にデバッグを制御するものが存在する 方式です。

よくある環境だと、次のように図示できます。

image.png

PHP 本体とは別の場所で動いてる方 がリモートです。

この図だと PHPStorm 側がリモートというわけです。

ここでは PHP 開発用のツールである PHPStorm を例として出していますが、Xdebug を動かすのに PHPStorm が必要というわけではありません。

PHPStorm 以外にも Xdebug のリモートデバッグを行えるツールはたくさんあります。


リモート・セッション

デバッグの制御を開始するには、PHP 本体側とリモートをつなぐ必要があります。

この一連の接続を「リモート・セッション」と呼びます。


リモートデバッグを有効にする

初期値ではリモートデバッグは無効になっています!

したがって、次の設定値を 1 にする必要があります。

設定
役割
初期値

xdebug.remote_enable

1 にするとリモートデバッグが有効になる
0


リモートへの接続設定

Xdebug 側からリモートにつなぐために、どこにつなぐのか? という設定が必要です。といっても、単純な TCP 接続なのでホストとポート番号のみです。

設定
役割
初期値

xdebug.remote_host
つなぎ先のホスト名
localhost

xdebug.remote_port
つなぎ先のポート番号
9000

たとえば、PHP本体とリモート(PHPStorm等)が同じマシンにある場合は初期値のままで使える、ということになります。

image.png

PHP を実行しているのが同じマシンではなく、Docker のコンテナ内にある!といった場合は xdebug.remote_host を変えればOKです。

image.png


Xdebug のリモート・セッションはいつ始まっていつ終わるのか?

xdebug.remote_enable=1 にすると、すぐにセッションが始まるわけではありません。

php-fpm のように、HTTPリクエストを受け付ける方式の場合 XDEBUG_SESSION_START=xxx というパラメータを付けてアクセスすると、はじめて Xdebug のリモート・セッションが ON になります。

xxx の部分は任意の名前で OK です。

▼ 実際に XDEBUG_SESSION_START ありなしで比べてみるとわかります

xdebug_session_start.gif

しかし、常に自動で開始させることもできます。

xdebug.remote_autostart=1 を設定するとパラメータがなくても自動的にセッションが始まるようになります。

設定
役割
初期値

xdebug.remote_autostart

1 にすると常にセッションを自動開始する
0

一度セッションが始まると、XDEBUG_REMOTE_SESSION という Cookie がセットされ、それが残っている限りはずっとセッションが続きます。

では、セッションはいつ終わるのでしょうか?

XDEBUG_SESSION_STOP というパラメータをつけてアクセスすると、セッションを止めることができます。また、Cookie の有効期限が切れるとセッションも切れます。ここの有効期限は xdebug.remote_cookie_expire_time で調整できます。

設定
役割
初期値

xdebug.remote_cookie_expire_time
XDebug のセッションを維持する Cookie の有効期限
3600


Xdebug のセッション開始モード( reqjit

基本、セッション開始は上記のやり方で即座に開始されます( req モードといいます)が、これを エラーが初めて起こったときに開始する ように変更することもできます。

このエラーが起こって初めてセッションを開始するモードを jitモード といいます。

設定
役割
初期値

xdebug.remote_mode

jit にするとエラーが初めて起こったときにセッションを開始する
req

jit モードにすると、XDEBUG_SESSION_START パラメータは無視され、エラー発生直後で必ずセッションがつながります。

▼ 試しにわざとエラーを起こしてみるとこのようになりました。XDEBUG_SESSION_START パラメータを与えていないのにデバッグ制御ができているのがわかります。

jit-mode.gif


(応用編)複数のリモートをつなぐには?

ひとつの PHP に対して複数のリモートセッションをつなぐ方法もあります。xdebug.remote_host で決定するのではなく、PHPにアクセスした側の IP アドレスに自動的につなぎにいってくれる 機能があります。この機能は xdebug.remote_connect_back=1 にすることで有効になります。

image.png

(※ただし、HTTP ヘッダから IP アドレスを取る仕組みなので CLI 実行の場合はうまく動きません)

設定
役割
初期値

xdebug.remote_connect_back

1 にするとPHPにアクセスした側の IP アドレスに自動的につなぎにいってくれる
0

この設定を ON にすると、xdebug.remote_host は無視されます。


(応用編) 間にルーターなどがあり、connect_back が使えない場合

複数リモートを管理する中間サーバー (DBGp Proxy) を立てる必要があります。

ここについてはすでに Qiita にすばらしい記事があるので参照すると良いでしょう

【PHP】リモートマシンのデバッグを、「複数人で」やる【Xdebug×DBGpProxy】


Xdebug リモートデバッグの設定値まとめ

この記事で紹介した xdebug.remote_... の設定値を振り返ってみます。

設定
役割
初期値

xdebug.remote_enable

1 にするとリモートデバッグが有効になる
0

xdebug.remote_host
つなぎ先のホスト名
localhost

xdebug.remote_port
つなぎ先のポート番号
9000

xdebug.remote_autostart

1 にすると常にセッションを自動開始する
0

xdebug.remote_cookie_expire_time
XDebug のセッションを維持する Cookie の有効期限
3600

xdebug.remote_mode

jit にするとエラーが初めて起こったときにセッションを開始する
req

xdebug.remote_connect_back

1 にするとPHPにアクセスした側の IP アドレスに自動的につなぐようになる。よって xdebug.remote_host は無視される
0


参考になるサイト

公式ドキュメントがやはりいちばん網羅的でわかりやすいです。英語ですが。