用DBGPavim在Vim中除錯PHP/Python程式

brookhong發表於2015-03-23

本文主要介紹如何在伺服器上用VIM + XDebug除錯PHP程式,目前雖然有不少介紹如何用Eclipse + XDebug在開發人員工作機上除錯PHP的文章,但對於如何系統的配置VIM + XDebug還是比較少的,而且目前關於VIM設定的文章都用一個比較老的外掛。這裡主要介紹一個新外掛DBGPavim,它相對於老的一些外掛有很多優勢。同時該外掛可完美的用於Python程式的除錯。另外VIM + XDebug相對於Eclipse + XDebug也有不少優勢,將在文章講述。

實現原理

dbgpavim

DBGp是偵錯程式後臺和偵錯程式介面通訊的一種協議,用於多種指令碼語言的除錯。XDebug是用於除錯PHP的DBGp實現。VIM要和XDebug互通,實現PHP的除錯,需要能夠理解DBGp協議,並能傳送DBGp指令。DBGPavim就是這樣一個外掛,它使VIM能夠接受DBGp請求,併傳送DBGp指令,以達到除錯目的。DBGPavim的名字源於DBGp@VIM。

ActiveState提供了用於除錯Python/Ruby的DBGp實現Komodo Remote Debugging Package,後面有一節將講到如何使它和VIM互通,以除錯Python。使用者將能以此類推出如何除錯ruby/nodejs等指令碼語言。

配置XDebug

    1. 安裝XDebug可以參考http://xdebug.org/docs/install。
    2. 編輯php.ini,加入以下兩行:
      zend_extension=/path/to/xdebug.so
       xdebug.remote_enable=1
    3. 編輯你的httpd.conf,加入以下行:
       php_value xdebug.remote_autostart 1
        注:這一行並非必須的,如果不加這一行,你需要在訪問HTTP伺服器的URL里加上XDEBUG_SESSION_START=1的引數,如: http://localhost/index.php?XDEBUG_SESSION_START=1。

如果有多個開發人員同時需要除錯不同的VirtualHost,可以在你的VirtualHost段中加入以下行:

 php_value xdebug.remote_port 9009

注:這裡的9009就是VIM作為DBGp伺服器應當監聽的埠,不同的開發人員在不同的VirtualHost中用各自不同的埠號。這個埠號和下一節提到的dbgPavimPort要一致。不加這一行,預設的埠號是9000。
最後可通過phpinfo.php檢查你的XDebug配置是否正確,你必須能夠看到以下這些行的值如下(主要是前兩列):

xdebug.remote_autostart	On	Off
 xdebug.remote_enable	On	On
 xdebug.remote_handler	dbgp	dbgp
 xdebug.remote_host	127.0.0.1	127.0.0.1
 xdebug.remote_port	9009	9000

phpinfo.php檔案內容如下:

<?php
     phpinfo();
 ?>

配置VIM + DBGPavim

DBGPavim外掛本身是用Python實現的,所以需要你的VIM支援Python 2.7。開啟你的VIM,輸入命令

:version

如果能看到“+python”,說明你的VIM是支援Python的。 如果看到的是“-python”,說明你的VIM不支援Python,你可以按如下步驟編譯自己的VIM:

  1. 安裝Python 2.7
  2. export path=/path/to/python2.7/bin:$PATH
  3. 用以下命令編譯VIM:
 ./configure --prefix=/opt/vim --enable-pythoninterp --with-python-config-dir=/usr/lib/python2.7/config
 make
 make install

注:這裡的/usr/lib/python2.7/config取決於你把Python2.7安裝到什麼位置。

這裡或者這裡下載DBGPavim,放到你的~/.vim目錄下,並編輯的你的~/.vimrc,加入以下兩行:

let g:dbgPavimPort = 9009
let g:dbgPavimBreakAtEntry = 0

注:這裡的9009和上一節的9009要一致,如果上一節沒有配置xdebug.remote_port,這裡也不需要配置,因為它們都會使用預設的9000。 dbgPavimBreakAtEntry=0告訴VIM不在入口處停下,這樣只會在斷點處停下。

你可以重新啟動VIM,按F5檢查你的DBGPavim配置是否正確。如果你配置成功的話,你會做VIM視窗的右下角看到提示資訊如下:

bap-LISN-9009

它表示VIM目前正在監聽9009埠,bap說明它只會在斷點處停下,其他提示資訊格式如下:

<bae|bap>-<LISN|PENDn|CONN|CLSD>

斷點狀態

bae Break At Entry,在入口處停下
bap Break only At breakPoints,只在斷點處停下

偵錯程式狀態

LISN	偵錯程式已啟動,正處於監聽狀態。
PEND-n	偵錯程式已捕捉到連線請求,可以按F5進入除錯模式了。
CONN	VIM正處於除錯模式中。
CLSD	偵錯程式已停止。

在Apache環境下除錯PHP

  1. 現在確認配置正確後,可以用VIM開啟你需要除錯的檔案,跳到你需要除錯的行,按F10設定當前行為斷點,並按F5啟動偵錯程式。
  2. 用瀏覽器訪問會呼叫相應PHP檔案的URL,你會看到VIM狀態列裡的的提示資訊變成:
     bap-PEND-1
  1. 它告訴你已經有一個連線被攔截,可以按F5開始除錯了。dbgpavim
  2. 按F5進入除錯模式,你會看到VIM視窗被分成三部分:左上為原始碼視窗,右上為變數檢視視窗,下方為呼叫堆疊視窗。dbgpavim在原始碼視窗裡,把游標定位到某一個變數上面按F12,在變數檢視視窗就能看到該變數的值,如果該變數不是簡單變數,其成員也會顯示出來。如果該變數的某個成員仍不是簡單變數,該行後面會出現一個加號,在該行按Enter鍵,該成員的值將被繼續展開。如果你想直接檢視某個變數的成員變數,可以按v切換到visual模式,選中該成員再按F12,比如$this->login。在堆疊視窗,當你在某一行按回車,將跳到該層。最上面一行是最底層,最下面一行是最頂層。切換呼叫堆疊的層次,可以幫助你檢視各個層次的變數,比如有些全域性變數只有在最頂層才能看到。對於原始碼中沒有出現的變數,你可以通過命令:Pg來檢視,比如:
     :P g $this->memberShip
  1. 你可以開始你的除錯了,隨時按F1可調出幫助視窗,再次F1就關閉幫助視窗。dbgpavim

除錯命令列啟動的PHP程式

如果你需要除錯命令列啟動的PHP程式,也需要保證PHP程式端的設定是正確的。這些設定可以像前面一樣在php.ini中設定,也可以通過命令列引數來設定。比如:

php -dxdebug.remote_autostart=1 -dxdebug.remote_port=9009 test.php

如果你的命令列使用的ini和apache中php5_module使用的ini是一樣的(通常情況是這樣的),你不需要在引數中再來做這些設定。但如果你在ini中的設定是放在某個virtualhost段裡,你仍然需要加上這些設定。 你可以通過命令列:

php --ini

來檢視你的命令列用的是哪個ini。

接著你可以使用命令:

php -r "phpinfo();"|grep xdebug.remote_

來檢查你的XDebug設定。

基本步驟如下:

  1. 用VIM開啟你需要除錯的PHP檔案,F10設定斷點,F5啟動除錯監聽。
  2. 從命令列執行php程式如上。
  3. 回到你的VIM視窗,將看到提示資訊為PEND-1。
  4. 按F5進入除錯模式。

DBGPavim提供一個:Dp命令簡化命令列程式的除錯。只需開啟你的PHP檔案,輸入命令:Dp即可。

除錯Python程式

前面說過VIM + DBGPavim作為DBGp協議的伺服器,可以與XDebug協同工作,也可以與ActiveState提供的Komodo Python Remote Debugging Client協同工作,實現Python程式的除錯,具體步驟如下:

  1. 這裡下載安裝Komodo Python Remote Debugging Client,把解壓後的bin目錄加到你的PATH路徑中,注意bin目錄下的pydbgp檔案。
  2. 用VIM開啟你需要除錯的Python檔案,F10設定斷點,F5啟動除錯監聽。
  3. 通過pydbgp執行你的Python程式,如
     pydbgp -d 127.0.0.1:9009 test.py
    1. 注:這裡的9009埠就相當於上面為PHP除錯時設定的xdebug.remote_port,需要和dbgPavimPort保持一致。
    2. 回到你的VIM視窗,將看到提示資訊為PEND-1。
    3. 按F5進入除錯模式。

    上面的:Dp命令同樣適用於Python除錯,下圖為Windows 7下用GVIM + pydbgp除錯Python的截圖。 dbgpavim

    VIM + DBGPavim相對於Eclipse + XDebug的優勢

    大多數伺服器不會啟動XServer,無法在伺服器上啟動Eclipse。如果在開發人員工作機上啟動Eclipse + XDebug,就相當於把DBGp伺服器在工作機上執行,你需要設定路徑對映,也就是HTTP Server執行的一份程式碼在伺服器上,Eclipse除錯時開啟的是一份程式碼,在工作機上,要保證這兩份程式碼能對應上需要對映路徑。當程式規模不大時,問題不大,當程式規模大時,會比較麻煩,而且要保證程式碼的同步,否則會序列。

    同時可以遭遇網路防火牆之類的問題。

    VIM + DBGPavim也是支援遠端除錯的,但同樣避免不了路徑對映的設定,如下:

    let g:dbgPavimPathMap = [['D:/works/php','/var/www'],]

DBGPavim相對於其他外掛的優勢

DBGPavim源於VIM早期的一個DBGp外掛http://www.vim.org/scripts/script.php?script_id=1152,從這個外掛還衍生出其他一些DBGp外掛。但DBGPavim重寫了作為偵錯程式後臺的DBGp伺服器,非同步監聽,使得VIM在監聽DBGp的同時不妨礙使用者與VIM之間的互動。使用者按F5啟動除錯監聽後,可繼續使用VIM,隨時可按F6停止監聽。

DBGPavim會監聽所有來自DBGp客戶端如XDebug、pydbgp的DBGp連線,不像其它外掛只能捕獲第一個連線。這對於大規模的WEB程式是必須的,因為現在的一次網頁載入通常會觸發多個HTTP請求,而我們需要除錯的可能來自其中的任何一個。 同時DBGPavim支援只在斷點處停下,其它的外掛都是在入口處停下,需要程式設計師一步步跟蹤進去。這省了開發人員很大的麻煩,而且避免出錯後一次次的重啟除錯。

相信你也已經發現,DBGPavim可以與Windows下的GVIM一起工作,並且工作的很好。

DBGPavim的詳細使用參考

VIM normal模式下

F5	啟動除錯監聽,或者有可除錯連線時進入除錯模式。
F6	停止除錯監聽。
F8	切換dbgPavimBreakAtEntry的值,按這個鍵你可以看到狀態列提示資訊在bae和bap之間切換,即是否在PHP程式入口處停下。
F10	在當前行設定或刪除斷點,在除錯模式下同樣適用。

除錯模式下

F1	開啟或關閉幫助視窗
F2	單步進入
F3	單步跳過
F4	單步退出
F5	繼續執行直到下一個斷點,如果後續沒有斷點就退出除錯模式。
F6	停止除錯,這個按鍵就導致VIM退出除錯模式,並且停止除錯監聽。
F7	除錯時執行php語句,按下F7後,使用者可在變數檢視視窗輸入php語句,回車後執行。
F9	最大化某個子視窗,或者重置視窗布局。
F11	檢視當前執行環境下的所有變數的值,在不同的堆疊層次,會有不同的結果。
F12	檢視游標下的變數的值。

以上功能鍵為預設配置,你如果習慣多數瀏覽器的按鍵設定,可以把下面的程式碼加入你的.vimrc中:

let g:dbgPavimKeyRun = '<F8>'
let g:dbgPavimKeyStepOver = '<F10>'
let g:dbgPavimKeyStepInto = '<F11>'
let g:dbgPavimKeyStepOut = '<F12>'
let g:dbgPavimKeyPropertyGet = '<F3>'
let g:dbgPavimKeyContextGet = '<F4>'
let g:dbgPavimKeyToggleBp = '<F9>'
let g:dbgPavimKeyToggleBae = '<F5>'
let g:dbgPavimKeyRelayout = '<F2>'

VIM命令,所有命令只有第一個字母為大寫。

:Bl	列出所有斷點
:Bp	與F10功能相同
 :D p	這個命令可用於快速除錯當前檔案,它實現瞭如下功能:

    1. 檢查命令列下XDebug/pydbgp的設定是否正確
    2. 啟動偵錯程式監聽
    3. 用php/pydbgp執行當前檔案

 :P g <longfoo>	檢視較長變數的值,比如:Pg $this->savings[3]
:Up	呼叫堆疊往上一級
 :D n	呼叫堆疊往下一級
:Wc [$foo]	開啟/關閉對變數$foo的監視。如果沒有引數,就監視當前執行環境下的所有變數。
:We <foo>	開啟/關閉對語句foo的監視,即每一單步後自動執行foo語句。
:Wl	列出所有被監視的變數或語句。
:Children <n>	對於陣列預設顯示前1024個元素,這個命令可以修改。
 :D epth <n>	對於複雜變數,預設只顯示下一層成員,這個命令可以設定限制多層。
:Length <n>	對於字串變數,預設執行顯示前1024個字元,這個命令可以設定顯示長度。

相關文章