疑難雜症,可以通過服務器端的xdebug.remote_log進行診斷處理。
一、前言
初學PHP語言,一般會推薦notepad++等編輯器進行開發。但是入門之後,使用phpstrom等IDE好處多多,比如學習一些框架的時候,斷點調試對於理解框架的整個運行機制和生命週期無可替代。在生產環境中,IDE的調試的變量監控對於提高開發效率也至關重要。當然了,每個行業都有前1%的人,程序員也不例外,使用VIM也未嘗不可。
本篇的主要寫作原因是,Xdebug配置對於新手來說問題多多,網上的教程多是一家之言,對於很多配置的官方文檔來源語焉不詳,缺乏對於可能存在的問題的調試辦法,對於各種本地、遠程等各種環境下的配置不做兼顧。本篇將就以上問題的每一個細節的來源、機理儘量加以說明,爭取做到讀者可以觸類旁通,不必查找其他資料。
二、準備和系統說明
- 本篇使用vmware安裝CentOS 7(下文簡稱虛機),虛機配置兩個網卡,網卡一爲NAT模式用於上網,網卡二爲host only模式,用於與主機通信。具體可以參見前文【 使用Vmware安裝CentOS作爲web開發機實踐】
- 開發機配置的是Nginx + php7.0
- 所有步驟依賴Phpstorm的配置說明,即settings->Languages&Frameworks->PHP->Debug
特別注意,本文的全部內容都是按照下圖的Pre-configuration裏的4個步驟進行的。如果你遇到本文中沒有涉及到的問題,可以點擊第一步中的Validate debugger configuration on the Web Server進行調試,具體請參見本文四、4章節。
三、Xdebug的安裝
1、點擊上圖中步驟一里install xdebug,進入phpstorm對xdebug的安裝說明:
https://confluence.jetbrains.com/display/PhpStorm/Xdebug+Installation+Guide
phpstorm對xdebug的安裝思路是,去xdebug官網下載編譯好的二進制文件,拷貝到php的extention目錄,然後在php.ini文件最後面加入如下配置(實際的例子見本文三、4):
[Xdebug]
zend_extension=<full_path_to_xdebug_extension>
xdebug.remote_enable=1
xdebug.remote_host=<the host where PhpStorm is running (e.g. localhost)>
xdebug.remote_port=<the port to which Xdebug tries to connect on the host where PhpStorm is running (default 9000)>
2、 這裏主要是針對windows服務器的php開發環境而言的,我們這裏使用的是CentOS 7,因此,最便捷的安裝辦法是:
sudo yum search xdebug
yum install xdebug.....
這時候,xdebug.so已經自動放入php的extention目錄下了,比如zend_extension = /usr/local/php/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so
,然後將上述配置加入到php.ini文件裏。
3、 xdebug官網還可以編譯安裝xdebug,推薦這種安裝方式。
- 首先打開xdebug wizard網址:
https://xdebug.org/wizard.php
然後將php.ini文件全部內容,或者shell下 php -i
命令輸出的全部內容都放到裏面去,解析後會給出詳盡的安裝步驟:
Tailored Installation Instructions
Summary
Xdebug installed: no
Server API: Command Line Interface
Windows: no
Zend Server: no
PHP Version: 7.0.15
Zend API nr: 320151012
PHP API nr: 20151012
Debug Build: no
Thread Safe Build: no
Configuration File Path: /usr/local/php/etc
Configuration File: /usr/local/php/etc/php.ini
Extensions directory: /usr/local/php/lib/php/extensions/no-debug-non-zts-20151012
Instructions
Download xdebug-2.5.1.tgz
Unpack the downloaded file with tar -xvzf xdebug-2.5.1.tgz
Run: cd xdebug-2.5.1
Run: phpize (See the FAQ if you don't have phpize.
As part of its output it should show:
Configuring for:
...
Zend Module Api No: 20151012
Zend Extension Api No: 320151012
If it does not, you are using the wrong phpize. Please follow this FAQ entry and skip the next step.
Run: ./configure
Run: make
Run: cp modules/xdebug.so /usr/local/php/lib/php/extensions/no-debug-non-zts-20151012
Edit /usr/local/php/etc/php.ini and add the line
zend_extension = /usr/local/php/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so
4、xdebug在服務器端的配置。
上面1、2、3的思路都是得到一個xdebug.so的二進制擴展,然後將xdebug的相關配置放到php.ini文件裏,下面對配置進行詳細說明。
- 首先確定php.ini文件的位置,比如shell下
php -i | grep
,可以得到php.ini的路徑Configuration File (php.ini) Path => /usr/local/php/etc
Loaded Configuration File => /usr/local/php/etc/php.ini - 編輯php.ini文件,在最後面加入如下配置,官方說明見本文三、1,這裏是一個實際配置的例子。
zend_extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so
xdebug.remote_enable =1
xdebug.remote_handler = "dbgp"
xdebug.remote_host = "www.phpcms.com"
xdebug.remote_mode = "req"
xdebug.remote_port = 9001
對上述項逐項說明一下:
zend_extension
顧名思義是xdebug擴展的路徑。xdebug.remote_enable
這裏都要必須是1,如果不是1,無論phpstrom在虛擬機裏還是在主機上,都不能進行調試。xdebug.remote_handler
這裏的協議只能是dbgp,xdebug的官網文檔是這樣說的:Note: Xdebug 2.1 and later only support 'dbgp' as protocol.
xdebug.remote_host
是你要本地調試的域名,這裏注意,不能填localhost或者127.0.0.1,除非你要調試的站點域名叫做localhost。也就是說,你要根據nginx或者apache裏虛擬站點的配置確定這個叫什麼。比如我這裏的nginx站點配置文件是:
server {
listen 80;
server_name www.phpcms.com;
……
}
注意,這裏配置了www.phpcms.com爲虛擬站點的域名,那麼要在/etc/hosts裏配置對應值,即 www.phpcms.com 127.0.0.1
根據上述nginx的站點配置, xdebug.remote_host
的值就是www.phpcms.com。如果不是這樣的話,本文二、3中的Validate xdebug configuration on the server
會報錯remote host is configured as 'localhost' despite server host is probably not local
,如下圖:
xdebug.remote_mode
req模式即腳本啓動即連接,如果是jit模式,則是在腳本產生錯誤之後才連接。詳情見xdebug關於遠程調試的說明文檔:https://xdebug.org/docs/remotexdebug.remote_port
這個是服務器開給遠程ide的端口,默認是9000,注意,很多nginx的php-fpm監聽端口也是9000,這時候改成非9000,或者將nginx站點配置文件和php-fpm監聽改爲unix sock,比如
server {
listen 80;
server_name www.phpcms.com;
……
location ~ [^/]\.php(/|$) {
#fastcgi_pass remote_php_ip:9000;
fastcgi_pass unix:/dev/shm/php-cgi.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
……
}
否則的話,會卡在`debug:waiting for incoming connection with ide key *
- 僅需要配置上述幾項,其他的諸如下面的不需要配置,配上了也無影響:
;xdebug.idekey =
;xdebug.remote_log = "/tmp/xdebug_remote_log"
;xdebug.remote_connect_back =1
四、PHPSTORM的配置
特別注意,這裏PHPSTORM是跑在虛擬機裏的,CentOS 7 裏,是Linux版。如果虛機是跑在主機上的,要把以下的127.0.0.1全部改成虛機的host only網卡的IP。然後在主機的hosts裏配置對應的域名和ip。
1、配置PHPSTORM使用的php執行文件。settings->Langeuages & Frameworks->PHP,然後Project Configuration,php版本選擇php7,CLI的解釋器選擇ssh模式,可以自動檢測。
2、Debug配置。有兩步,一個是settings->Langeuages & Frameworks->PHP->Debug裏,Debug port要跟本文三、4裏,php.ini文件裏配置的遠程端口一致,這裏是9001。此頁面的其他選項沒有經過一一測試,建議全部配置成和下圖一致。
然後是DBGp協議的配置,settings->Langeuages & Frameworks->PHP->Debug->DBGp Proxy頁面,這裏經過測試,只需要填寫代理端口即可,DBGp代理端口也是和本文三、4裏,php.ini文件裏配置的遠程端口一致,這裏是9001。
3、PHPSTORM調試配置。Run->Edit Configuration,點擊最左上角的綠色加號,這裏我們調試的類型是PHP Web Application
,還有一種常用的調試是CLI腳本模式。然後Configuragion ->Server,點擊…,彈出框裏點擊綠色加號,填寫Host和Port,這兩項要跟你的Nginx Server配置裏的域名和端口相對應。返回之後,在Start URL裏填寫項目的起始地址。
特別注意,這個Start URL坑比較多。一個是建議寫成如下圖的絕對訪問地址,帶上入口文件index.php。爲什麼呢,因爲Nginx的虛擬站點配置裏,一般是首先識別index.html,而不是index.php。這樣調試開始之後,打開了http://www.php.com,實際訪問的是index.html而不是index.php,卡在
waiting for incoming connection with ide key
。另一方面,這個Start URL是可以填寫相對地址的,如果你調試的是https的話,Start URL下面拼出來的那個藍色的網址不會加上https。很多人會卡在這裏,想要調試https,但是打開的卻是http+443端口。
綜上,強烈推薦按照下圖的寫法,絕對地址+入口文件:http://www.php.com/index.php
4、驗證Server端和PHPSTORM端配置。settings->Langeuages & Frameworks->PHP->Debug,Pre-configuration裏,第一步,點擊Validate,彈出框裏,Url填寫http://www.php.com/,點擊Validate,如果Infomation如下圖所示則說明Server端和PHPSTORM端都已經成功了!如果你的Infomation裏有其他問題,歡迎在本文評論裏貼出來。
五、瀏覽器插件的配置
什麼?還沒配完,瀏覽器爲什麼還需要一個插件呢? 這裏不得不說一下Xdebug調試的通信流程。下面直接粘一下Xdebug的官方說明,大概的流程是PHPSTORM向瀏覽器發起請求,瀏覽器通過DBGp協議返回給PHPSTORM,PHPSTORM同樣通過DBGp協議把插入的信息返回給瀏覽器,最後瀏覽器將最終的返回結果給PHPSTORM用於調試和報錯。具體可以參見https://xdebug.org/docs/remote的Communication Set-up With a static IP/single developer
的章節。
官方說明:
With remote debugging, Xdebug embedded in PHP acts like the client, and the IDE as the server. The following animation shows how the communication channel is set-up:
The IP of the server is 10.0.1.2 with HTTP on port 80
The IDE is on IP 10.0.1.42, so xdebug.remote_host is set to 10.0.1.42
The IDE listens on port 9000, so xdebug.remote_port is set to 9000
The HTTP request is started on the machine running the IDE
Xdebug connects to 10.0.1.42:9000
Debugging runs, HTTP Response provided
具體安裝插件,點擊本文二、3中Pre-configuration圖裏的settings->Languages&Frameworks->PHP->Debug第二步,Install browser toolbar and bookmarklet。會跳轉到這個網址:https://confluence.jetbrains.com/display/PhpStorm/Browser+Debugging+Extensions。如下圖所示,會有多個瀏覽器的插件安裝。
這裏,我們選擇Xdebug的Chrome Xdebug Helper。會跳轉到Chrome的插件商店,需要代理訪問。
這裏不得不吐槽一下谷歌退出中國造成的各種不便,谷歌的創始人作爲基督教祕密團體的成員,對無神論的中國充滿了偏見,當年退出中國的理由竟然不是內容審查,而是中國政府攻擊它的郵箱,並且判斷依據是攻擊它的IP在國內,這也是醉了。
具體網址:https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc
安裝即可,如下圖:
六、調試
settings->Languages&Frameworks->PHP->Debug,Pre-configuration裏,先validate一下設置。沒有問題,第三步,Enable listening for PHP Debug Connection,這個在PHPSTORM界面的右上角也有。
在index.php的第一行打一個斷點,就是再圖中紅點位置單擊一下。然後點擊右上角的小爬蟲,或者菜單裏Run-debug,PHPSTORM自動打開瀏覽器,如何判斷已經成功了呢?這時候瀏覽器應該是空白並且是載入中的狀態,而PHPSTORM的debugger窗口,則有一些全局變量已經被watch。恭喜,你可以像是用微軟的開發環境一樣調試PHP啦。
七、疑難說明
1、 xdebug官方文檔認爲xdebug與zend opcache是不能通用的,經筆者實驗,兩者不相互影響。
2、 ionCube加密組件則需要將其配置放前,否則會報錯
PHP Fatal error: [ionCube Loader] The Loader must appear as the first entry in the php.ini file in Unknown on line 0
3、 php.ini文件中,xdebug.idekey應該如何配置?配置成’PHPSTORM’,或者留空,或者其他都沒有影響,每次調試時會自動生成一個數字idekey,然後在打開瀏覽器時以參數的形式傳過去。比如http://www.phpcms.com/index.php?XDEBUG_SESSION_START=11756
4. phpstorm卡在debug:waiting for incoming connection with ide key 。這裏主要可能有兩個可能的問題,一個是三、4服務器php.ini裏的xdebug.remote_port
和四、2中PHPTSORT填寫的端口不一致。另一個則可能是四、3中填寫的URL沒有實際訪問到。還有一種可能是打的斷點位置不對,不是每個地方的斷點都可以執行到的,配置時建議打入口php文件的第一行。
八、附錄
完整的xdebug配置參數說明有幾十KB大小,這裏就不貼了,感興趣的可以去我的csdn下載頁面看看。