こんにちは、株式会社エヌ・エイ・シー・ケア システムインテグレーション事業部です。
今回はPHPでのリモートデバッグ方法についてご紹介いたします。
プログラミング言語によっては、IDE(統合開発環境)がそろっていて、IDEに含まれるデバッガを使用して、実行中にブレークポイントで停止させたり、ステップ実行ができたりします。
しかし、PHPはサーバーサイドで実行されるため、ローカル環境にあるエディタはプログラムの何行目を実行されているかが分かりません。
そこで、PHPの拡張モジュール(Xdebug)を使用してリモートデバッグを実施してみます。
Xdebugは、エディタに現在実行中の行番号などの情報を提供し、エディタはブレークポイントを設定する行番号などの情報をXdebugに送信します。この情報のやり取りがなければ、デバッグはできません。
そこで、Xdebugとエディタはそれぞれ通信するためにDBGp(Common DeBugGer Protocol)というプロトコルを用いて通信します。
まずはXdebugはpeclでインストールします。Red Had系でPHPをyumインストールしていればyumで
インストール、RHEL8であればyumの後継コマンドであるdnfを使用してインストールします。
なお、今回はXdebugのバージョン3を使用していますが、バージョン2と3で設定項目などがだいぶ変更
されていますので注意してください。
Xdebugをインストール後、必要があれば設定を変更します。
今回はログ出力とmodeを変更します。ログ出力はデバッガが動作しない場合に調査するのに便利です。
その後、PHPを再起動します。
まず一番単純な場合として、サーバー上のエディタでデバッグします。
プログラムはPHPのCLIで実行し、エディタはvimを使用します。
また、VimでデバッグするためにVimのプラグインVdebugを使用します。
Vimのプラグインマネージャはvim-plugを使用します。
次のコマンドでインストールできます。
ホームディレクトリにある.vimrcに二行追加します。
その後、Vim上で:(コロン)を入力しコマンドモードにして、PlugInstallと入力するとプラグインのインストールが始まります。
.vimrcにVdebugの設定を入れます。まずはデフォルトの設定を追加し、その後に項目ごとに変更した値を追記します。
portはXdebug側からVimに接続しに行くときのportで、debug_fileはvdebug側のログファイルです。
Vdebugが動作しない場合に調査するのに便利です。
また、CLIからPHPを実行してVdebugを起動する場合、環境変数XDEBUG_CONFIGにidekeyを設定す
る必要がありますので、.bashrcに下記一行を追加します。
環境変数を反映するためにログインしなおします。
1.Vimでデバッグしたいソースコードを開きます。
2.〈F10〉を押してブレークポイントを設定します。
3.〈F5〉を押してデバッガをスタートさせます。
〈F5〉を押すと20秒間Xdebugからの接続待ちになります。
4.別端末でデバッグしたいソースコードを実行します。
5.元の端末上のVimでソースコードを開いた画面でデバッガーインターフェイスが自動的に起動します。
(まれに何も反応がない場合もありますが、何かキーを押したりするとデバッガーインターフェイスが起動します。)
6.ステップ実行させます。
主なキーバインド
〈F5〉: 開始/実行(次のブレークポイント/スクリプトの終了まで)
〈F2〉: ステップオーバー
〈F3〉: ステップイン
〈F4〉: ステップアウト
などの他に変数の値を参照したり、変数の値を書き換えることも可能です。
7.〈F6〉を押してデバッガを停止します。
もう一度押すと、デバッガーインターフェイスが閉じます。
第一の注意点として、XdebugとIDEの関係で気を付けないといけないところは、Xdebug側からIDEに
向けてコネクションを張る点(Xdebug側から接続を開始する)です。
つまり、サーバー上のXdebug側からエディタに向けて接続するため、ルーターの外側にサーバーが存在すると接続できません。
二番目の注意点は、その時の接続先はXdebugの設定ファイルで設定された一か所に向けてとなります。
ただし、サーバーがルーターの内側にある場合、Xdebugの設定で解決可能です。
discover_client_hostをtrueにすると、XdebugはサーバーにHTTPリクエストを送信してきた送信元に
向けて接続しに行きます。
サーバーがルーターの外側にある場合は、ルーターでポートフォワーディングの設定ができれば良いのですが、できない場合はリモートポートフォワーディングを利用することで解決します。
また、複数人でデバッグする場合の問題を解決するために、DBGp Proxyを導入します。
DBGp Proxyを使用すると、IDEKeyによって接続先のポートを別ポートに振り分けることができます。
以下よりダウンロードします。(リンクが消されている場合は、別途ダウンロードしてください。)
https://xdebug.org/download#dbgpProxy
ダウンロードしたファイルはバイナリのため、実行権限を与えればそのまま実行できます。
下記のコマンドにより実行します。ここでは「9003」はXdebugの設定ファイルに設定されている接続先のIDE側のポートで、「9005」はDBGp Proxyのポートになります。
下記のコマンドにより、IDE KeyがXDEBUG_VIMの場合、「9006」のポートに接続するように指示します。
リモートポートフォワーディングとは、ローカルのSSHクライアントからSSHサーバに接続したとき
に、ローカルから接続可能な「アドレス:ポート」に接続できる方法です。 (接続先のポート(リモート)が待ち受けとなり、そこに接続すると指定したローカルの「アドレス:ポート」に接続できます。)
上記の場合、リモートの「9006」ポートに接続すると、ローカルアドレスの「9006」ポートへの接続になります。Tera TermやPuTTYでも可能です。
ブラウザから接続時にXdebugセッションを開始するためには、HTTPリクエスト時にXDEBUG_SESSION=IDE_Keyを送る必要があります。
HTTPリクエストにXdebugを起動するcookieを追加するchrome拡張をインストールします。下記からchrome extensionのXdebug helperをインストールします。
(リンクが消されている場合は、別途ダウンロードしてください。)
https://chromewebstore.google.com/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc
Xdebug helperの設定画面でIDE_keyを設定して保存します。
そうすると、chromeの右上のXdebug helperのアイコンを押下し、Debugを選択するとアイコンが緑色になり、 HTTPリクエストのcookieにXDEBUG_SESSION=XDEBUG_VIMが追加されるようになります。
ローカル環境がWindowsであれば_vimrcにVdebugの設定を入れます。
リモート環境の.vimrcとの違いは下記の項目です。
port
リモートポートフォワーディングで設定したポートを設定
path_maps
ソースコードを配置しているディレクトのパスのマッピング情報を設定
(:(コロン)の左側がリモート側、右側がローカル側のパスになります)
リモート環境での実行方法と同じですが、今回の違う点はブラウザからアクセスするとデバッガが起動するところです。
1.Vimでデバッグしたいソースコードを開きます。
2.〈F10〉を押してブレークポイントを設定します。
3.〈F5〉を押してデバッガをスタートさせます。
〈F5〉を押すと20秒間Xdebugからの接続待ちになります。
4.ブラウザからアクセスします。
5.Vimの画面でデバッガーインターフェイスが起動します。
6.ステップ実行させます。
7.〈F6〉を押してデバッガを停止します。
もう一度押すと、デバッガーインターフェイスが閉じます。
VScodeを使用する場合は、VSCodeの拡張のPHP Debugを使用すれば同様のことが可能になります。
簡単にご紹介させていただきましたが、いかがでしたでしょうか。
デバッグを駆使することにより、コードの理解が深まり、より良いシステムの構築につながると考えています。