Vdebugというデバッガを紹介します。

実際に動いている様子はDebug Drupal PHP in Vim with Vdebug | Mediacurrent動画があったので、そちらを見て下さい。

Vdebugを使うにはVimが+pythonでコンパイルされている必要があるので、

$ vim --version

+pythonになっているかを確認します。

インストールはShougo/denite.nvimなどを使って、インストールしてください。

VdebugはDBGpというプロトコルを使うため、デバッグしたい言語でDBGpが使えるように設定する必要があります。各言語の設定はVdebugのヘルプに載っています(:help VdebugSetUp<言語>)。

PHP

まずはPHPを例にして使い方を説明していきます(:help VdebugSetUpPHP)。

Xdebug

PHPでデバッグするにはXdebugが必要です。xdebugのinstallのドキュメントなどを見てインストールしましょう。

Xdebugのremote debugのついての説明はXdebugのRemote Debuggingのドキュメントに書かれています。

XdebugとVdebugを使ったwebページのdebugは以下のように行われます。

+------------------+                  +------------------+
|                  | ---------------> | 80               |
|                  |   HTTP Request   |                  |
|                  |                  |                  |
|             9000 | <--------------- |                  |
|                  |   DBGP Connect   |                  |
|   Vim / Vdebug   |                  |   PHP / Xdebug   |
|                  | <--------------> |                  |
|                  |       DBGP       |                  |
|                  |                  |                  |
|                  | <--------------- |                  |
|                  |   HTTP Response  |                  |
+------------------+                  +------------------+

左側がVimで、右側がデバッグしたい対象です。

  1. まず、Vdebugを起動して、xdebug.remote_portで設定したポート(デファルトは9000)をリッスンしておきます。
  2. デバッグしたいURLにHTTPでリクエストします。このときidekeyと呼ばれる設定も送ります
  3. idekeyを送られたPHPはxdebug.idekeyに設定された値と一致した場合にxdebug.remote_hostに設定されたホストのxdebug.remote_portに設定されたポートに接続します
  4. デバッグが開始されます
  5. デバッグが終了するとHTTPレスポンスが返ります

Xdebugから見て、デバッグクライアントはremoteなので、xdebug.remote_...という設定名になっています。

PHPとVimが同じ環境で動いている場合の設定

例えば、PCでPHPを動かしてVimでデバッグする場合や、サーバでPHPを動かしてそのサーバのVimでデバッグする場合、PHPのiniファイルを以下のようの設定します。

; 1にするとxdebug.remote_hostとxdebug.remote_portで設定したホストとポートをリッスンしているデバッグクライアントに
; 接続を試みるようになる。defaultは0。
xdebug.remote_enable=1
; 設定したidekeyと同じ値がPHPに送られたときにデバッグを開始する。周りの人がPhpStormを使っているなら、PHPSTORMなど。
xdebug.idekey="PHPSTORM"
; デバッグクライアントのホスト。defaultはlocalhost。
xdebug.remote_host=localhost
; デバッグクライアントがリッスンしているポート。defaultは9000。
xdebug.remote_port=9000
; HTTPのGET/POST/COOKIEのの設定にかかわらずデバッグの開始を試みる。defaultは0。
xdebug.remote_autostart=1

最後のxdebug.remote_autostart=1は0にしても、後で入れるブラウザ拡張がうまくやって、デバッグを開始してくれるはずですが、開始しないので入れています。

サーバ上でPHPを動かして、PC上のVimでデバッグする場合

PHPのiniファイルを以下のようの設定します。

; 1にするとxdebug.remote_hostとxdebug.remote_portで設定したホストとポートをリッスンしているデバッグクライアントに
; 接続を試みるようになる。defaultは0。
xdebug.remote_enable=1
; 設定したidekeyと同じ値がPHPに送られたときにデバッグを開始する。周りの人がPhpStormを使っているなら、PHPSTORMなど。
xdebug.idekey="PHPSTORM"
; 1にするとHTTPでリクエストして来たIPに接続を試みるようになる。defaultは0
xdebug.remote_connect_back=1
; デバッグクライアントがリッスンしているポート。defaultは9000
xdebug.remote_port=9000
; HTTPのGET/POST/COOKIEのの設定にかかわらずデバッグの開始を試みる。defaultは0。
xdebug.remote_autostart=1

xdebug.remote_hostにPCのIPアドレスを設定することでもデバッグできますが、それだと一つのPCしか接続できません。xdebug.remote_connect_backを使うと複数のPCで同時にデバッグをすることが出来ます。

サーバ上のファイルと、PC上のファイルのマッピングはg:vdebug_options['path_maps']で設定します。この部分の設定だけを設定することは出来ないので、まず、デフォルトの設定をします。

let g:vdebug_options= {
\    "port" : 9000,
\    "server" : '',
\    "timeout" : 20,
\    "on_close" : 'detach',
\    "break_on_open" : 1,
\    "ide_key" : '',
\    "path_maps" : {},
\    "debug_window_level" : 0,
\    "debug_file_level" : 0,
\    "debug_file" : "",
\    "watch_window_style" : 'expanded',
\    "marker_default" : '⬦',
\    "marker_closed_tree" : '▸',
\    "marker_open_tree" : '▾'
\}

ide_keyは空のままでも大丈夫です。設定するとデバッグの対象をide_keyで絞り込みます。

そして、ファイルパスのマッピングの設定をします。

let g:vdebug_options['path_maps'] = {"/path/to/server/scripts": "/path/to/local/scripts"}

サーバ上でPHPが動いていて、PCでデバッグしたい人と、サーバ上でデバッグしたい人がいる場合

PCでデバッグしたい人はxdebug.remote_connect_back=1とすることでデバッグ出来ますが、サーバ上でデバッグしたい人はlocalhostに接続してほしいので両立しません。

解決策1: サーバ上でデバッグしたいしたい人がサーバ上からリクエストする

サーバ上でデバッグしたい人が、そのサーバ上でcurlやテキストブラウザでリクエストすれば、remote_connect_back先はそのサーバになるのでデバッグできます。ただ、PCのブラウザを使いたいですよね……。

解決策2: プロキシを立てる

Remote DebuggingのドキュメントのMultiple Users DebuggingのDBGp proxyを使い、remote_hostをproxyに設定して、proxyが振り分けるようにするとうまくいくかもしれません。

ブラウザ拡張

ブラウザからデバッグを開始したい場合は、例えばchromeの場合、Xdebug helperという拡張をインストールします1。オプションでidekeyを設定します。

デバッグの仕方

まず、VimでF5を押してデバッガを起動します。

次にwebページをデバッグしたい場合はインストールしたブラウザ拡張のDebugをonにしてアクセスします。

コマンドラインからPHPを実行する場合は、環境変数XDEBUG_CONFIGにidekeyを設定して、PHPを起動します。

XDEGUG_CONFIG="idekey=PHPSTORM" php script.php

PHPUnitを使ったテストもデバッグできます。ただし、関数名に日本語を使っていると落ちます。

XDEGUG_CONFIG="idekey=PHPSTORM" php /path/to/phpunit ...

実行後、Vimを見ると、コードの最初の行で止まっているので、F2などを押してステップ実行していきます。

デフォルトのキーは以下の通り。

<F5>: start/run (to next breakpoint/end of script)
<F2>: step over
<F3>: step into
<F4>: step out
<F6>: stop debugging (kills script) (すでにデバッグが終わっている場合はデバッガUIを閉じます)
<F7>: detach script from debugger
<F9>: run to cursor
<F10>: toggle line breakpoint
<F11>: show context variables (e.g. after "eval")
<F12>: evaluate variable under cursor

自分で設定することもできます。

let g:vdebug_keymap = {
\    "run" : "<F5>",
\    "run_to_cursor" : "<F9>",
\    "step_over" : "<F2>",
\    "step_into" : "<F3>",
\    "step_out" : "<F4>",
\    "close" : "<F6>",
\    "detach" : "<F7>",
\    "set_breakpoint" : "<F10>",
\    "get_context" : "<F11>",
\    "eval_under_cursor" : "<F12>",
\    "eval_visual" : "<Leader>e",
\}

デバッグ開始時にスクリプトの最初の行で止まらずにブレークポイントまで進んでほしい場合は

let g:vdebug_options["break_on_open"] = 0

という設定をします。

うまくいかない場合

xdebug.remote_log=/tmp/xdebug.log

を設定して、ログを確認してみるといいかもしれません。

他の言語

Vdebugのヘルプを見ると他にもPython, Perl, Ruby, Nodejs, TClでデバッグができるようです。どれもKomodo Remote Debugging Packageを使います。VdebugのヘルプとKomodoのDebugging your programsを参照すれば設定できそうです。

実際にPythonとPerlの設定について書きます。

Python

:help VdebugSetUpPythonKomodo 11 DocumentationのDebugging Pythonを見てPythonのセットアップをしてみます。

Komodo Remote Debugging Package Downloads « ActiveState CodeからPython Remote Debugging Clientをダウンロードして解凍します。以下を実行してOKが出るかを確認します。

$ export PYTHONPATH="/path/to/Komodo-PythonRemoteDebugging-xxx/pythonlib${PYTHONPATH:+:${PYTHONPATH}}"
$ python -c "import dbgp.client; print 'ok'"
ok

Vdebugを起動して、

$ /path/to/Komodo-PythonRemoteDebugging-xxx/pydbgp -d localhost:9000 script.py

でscript.pyに対してのデバッグを開始できます。やってみると、デバッグが終了しても上記コマンドが終了せず、Ctrl-cでも終了できないのが難点でした。

非公式ですがpipでインストールできるようにした人がいました(dougn/komodo-pydbgp: Repackaging of the Komodo python remote debugging package for building into usable wheels)。

試してみるとpython 2.7.14は動きましたがpython 3.6.3ではエラーがでました。

Perl

:help VdebugSetUpPerlを見てPerlのセットアップをしてみます。

ヘルプ曰く、特定のバージョンからうまくいかなくなったようなので、ヘルプに書いてあるバージョンを

http://downloads.activestate.com/Komodo/releases/archive/8.x/8.0.2/remotedebugging/

からダウンロードします(Komodo-PerlRemoteDebugging-8.0.2-78971-xxx)。

展開して、適当な場所(~/perl5/lib/perl5/など)に配置します。

シェルの設定ファイルに以下の設定をします。

export PERL5LIB="/path/to/Komodo-PerlRemoteDebugging-xxx/${PERL5LIB:+:${PERL5LIB}}"
export PERL5DB="BEGIN { require q(/path/to/Komodo-PerlRemoteDebugging-xxx/perl5db.pl)}"
export PERLDB_OPTS="RemotePort=localhost:9000"
export DBGP_IDEKEY="PHPSTORM"

あとはVdebugを起動して

$ perl -d script.pl

でPerlを実行すればデバッグが始まります。

webページのデバッグ

Debugging Perl | Komodo IDE/Edit Documentationにやり方が載ってます。

例えば、Apache HTTP ServerでCGIを使っている場合はApache HTTP Serverのconfファイルに

SetEnv PERL5LIB "/path/to/Komodo-PerlRemoteDebugging-xxx"
SetEnv PERLDB_OPTS "RemotePort=<hostname>:<port>"
SetEnv DBGP_IDEKEY "<ide_key>"

と書いて、デバッグしたいスクリプトのシェバンに-dを加えます。

#!/usr/local/bin/perl -d

そして、Vdebugを起動してwebページにアクセスするとデバッグが開始されます。

Python 3への移行

Vdebugはpython2で動きますが、v2.0という名前がついたプロジェクトページにAdds Python 3 supportというissueが立ってます。そこのコメント

@l0rb fortunately @lucc mentioned the v2-integration branch where there is continued development but still some issues to be resolved before thinking about py3

と書いてあるので、Python 3への移行はまだ先になりそうです。


  1. その他のブラウザの拡張については、Remote Debuggingのドキュメントを見て下さい。