24
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

VimAdvent Calendar 2017

Day 12

Vdebugでデバッグする

Last updated at Posted at 2017-12-11

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

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

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

$ vim --version

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

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

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のセットアップをしてみます。

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

からダウンロードします(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のドキュメントを見て下さい。

24
20
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?