摘要:說明開發和調試環境為本地中的,環境為本地下的。再次在容器中抓取端口數據包連接的源地址已經正確再次使用的斷點調試時,控制臺如下所以,使用進行遠程調試時,需要選擇合適的調試模式,在下建議使用遠程模式。
首發于 樊浩柏科學院
我們經常會使用 PhpStorm 結合 Xdebug 進行代碼斷點調試,這樣能追蹤程序執行流程,方便調試代碼和發現潛在問題。博主將開發環境遷入 Docker 后,Xdebug 調試遇到了些問題,在這里整理出 Docker 中使用 Xdebug 的方法和注意事項。
說明:開發和調試環境為本地 Docker 中的 LNMP,IDE 環境為本地 Win10 下的 PhpStorm。這種情況下 Xdebug 屬于遠程調試模式,IDE 和本地 IP 為 192.168.1.101,Docker 中 LNMP 容器 IP 為 172.17.0.2。問題描述
在 Docker 中安裝并配置完 Xdebug ,并設置 PhpStorm 中對應的 Debug 參數后,但是 Debug 并不能正常工作。
此時,php.ini中 Xdebug 配置如下:
xdebug.idekey = phpstorm xdebug.remote_enable = on xdebug.remote_connect_back = on xdebug.remote_port = 9001 //PhpStorm監聽本地9001端口 xdebug.remote_handler = dbgp xdebug.remote_log = /home/tmp/xdebug.log
開始收集問題詳細表述。首先,觀察到 PhpStorm 的 Debug 控制臺出現狀態:
Waiting for incoming connection with ide key ***
然后查看 Xdebug 調試日志xdebug.log,存在如下錯誤:
I: Checking remote connect back address. I: Checking header "HTTP_X_FORWARDED_FOR". I: Checking header "REMOTE_ADDR". I: Remote address found, connecting to 172.17.0.1:9001. W: Creating socket for "172.17.0.1:9001", poll success, but error: Operation now in progress (29). E: Could not connect to client. :-(分析問題
查看這些問題表述,基本上可以定位為 Xdebug 和 PhpStorm 之間的 網絡通信 問題,接下來一步步定位具體問題。
排查本地9001端口Win 下執行 netstat -ant命令:
協議 本地地址 外部地址 狀態 卸載狀態 TCP 0.0.0.0:9001 0.0.0.0:0 LISTENING InHost
端口 9001 監聽正常,然后在容器中使用 telnet 嘗試同本地 9001 端口建立 TCP 連接:
$ telnet 192.168.1.101 9001 Trying 192.168.1.101... Connected to 192.168.1.101. Escape character is "^]".
說明容器同本地 9001 建立 TCP 連接正常,但是 Xdebug 為什么會報連接失敗呢?此時,至少可以排除不會是因為 PhpStorm 端配置的問題。
排查Xdebug問題回過頭來看看 Xdebug 的錯誤日志,注意觀察到失敗時的連接信息:
I: Remote address found, connecting to 172.17.0.1:9001. W: Creating socket for "172.17.0.1:9001", poll success, but error: Operation now in progress (29). E: Could not connect to client. :-(
此時,在容器中使用 tcpdump 截獲的數據包如下:
$ tcpdump -nnA port 9001 # 嘗試建立連接,但是失敗了 12:20:34.318080 IP 172.17.0.2.40720 > 172.17.0.1.9001: Flags [S], seq 2365657644, win 29200, options [mss 1460,sackOK,TS val 833443 ecr 0,nop,wscale 7], length 0 E..<..@.@.=...........#)...,......r.XT......... ............ 12:20:34.318123 IP 172.17.0.1.9001 > 172.17.0.2.40720: Flags [R.], seq 0, ack 2365657645, win 0, length 0 E..(.]@.@..M........#).........-P....B..
可以確定的是, Xdebug 是向 IP 為 172.17.0.1 且端口為 9001 的目標機器嘗試建立 TCP 連接,而非正確的 192.168.1.101 本地 IP。到底發生了什么?
首先,為了搞懂 Xdebug 和 PhpStorm 的交互過程,查了 官方手冊 得知,Xdebug 工作在遠程調試模式時,有兩種工作方式:
1、IDE 所在機器 IP 確定/單人開發
圖中,由于 IDE 的 IP 和監聽端口都已知,所以 Xdebug 端可以很明確知道 DBGP 交互時 IDE 目標機器信息,所以 Xdebug 只需配置 xdebug.remote_host、xdebug.remote_port 即可。
2、IDE 所在機器 IP 未知/團隊開發
由于 IDE 的 IP 未知或者 IDE 存在多個 ,那么 Xdebug 無法提前預知 DBGP 交互時的目標 IP,所以不能直接配置 xdebug.remote_host 項(remote_port 項可以確定),必須設置 xdebug.remote_connect_back 為 On 標識(會忽略 xdebug.remote_host 項)。這時,Xdebug 會優先獲取 HTTP_X_FORWARDED_FOR 和 REMOTE_ADDR 中的一個值作為通信時 IDE 端的目標 IP,通過Xdebug.log記錄可以確認。
I: Checking remote connect back address. I: Checking header "HTTP_X_FORWARDED_FOR". I: Checking header "REMOTE_ADDR". I: Remote address found
接下來,可以知道 Xdebug 端是工作在遠程調試的模式 2 上,Xdebug 會通過 HTTP_X_FORWARDED_FOR 和 REMOTE_ADDR 項獲取目標機 IP。Docker 啟動容器時已經做了 80 端口映射,忽略宿主機同 Docker 容器復雜的數據包轉發規則,先截取容器 80 端口數據包:
$ tcpdump -nnA port 80 # 請求信息 13:30:07.017770 IP 172.17.0.1.33976 > 172.17.0.2.80: Flags [P.], seq 1:208, ack 1, win 229, options [nop,nop,TS val 1250713 ecr 1250713], length 207 E....=@.@..............P.. .+.......Y...... ........GET /v2/room/list.json HTTP/1.1 Accept: */* Cache-Control: no-cache Host: localhost Connection: Keep-Alive User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_152-release) Accept-Encoding: gzip,deflate
可以看出,數據包的源地址為 172.17.0.1,并非真正的源地址 192.168.1.101,HTTP 請求頭中也無 HTTP_X_FORWARDED_FOR 項。
說明:172.17.0.1 實際為 Docker 創建的虛擬網橋 docker0 的地址 ,也是所有容器的默認網關。Docker 網絡通信方式默認為 Bridge 模式,通信時宿主機會對數據包進行 SNAT 轉換,進而源地址變為 docker0,那么,怎么在 Docker 里獲取客戶端真正 IP 呢?。定位根源
最后,可以確定由于 HTTP_X_FORWARDED_FOR 未定義,因此 Xdebug 會取 REMOTE_ADDR 為 IDE 的 IP,同時由于 Docker 特殊的網絡轉發規則,導致 REMOTE_ADDR 變更為網關 IP,所以 Xdebug 同 PhpStorm 進行 DBGP 交互會失敗。
解決問題由于 Docker 容器里獲取真正客戶端 IP 比較復雜,這里使用 Xdebug 的 遠程模式 1 明確 IDE 端 IP 來規避源 IP 被修改的情況,最終解決 Xdebug 調試問題。
模式 1 的 Xdebug 主要配置為:
//并沒有xdebug.remote_connect_back項 xdebug.idekey = phpstorm xdebug.remote_enable = on xdebug.remote_host = 192.168.1.101 xdebug.remote_port = 9001 xdebug.remote_handler = dbgp
重啟 php-fpm,使用php --ri xdebug確定無誤,使用 PhpStorm 重新進行調試。
再次在容器中 tcpdump 抓取 9001 端口數據包:
# 連接的源地址已經正確 14:05:27.379783 IP 172.17.0.2.44668 > 192.168.1.101.9001: Flags [S], seq 3444466556, win 29200, options [mss 1460,sackOK,TS val 1462749 ecr 0,nop,wscale 7], length 0 E..<2.@.@..........e.|#).Nc|......r.nO......... ..Q.........
再次使用 PhpStorm 的 REST Client 斷點調試 API 時, Debug 控制臺如下:
所以,使用 Xdebug 進行遠程調試時,需要選擇合適的調試模式,在 Docker 下建議使用遠程模式 1。
其他注意事項Xdebug 版本和 PHP 版本一致
并不是每個 Xdebug 版本都適配 PHP 每個版本,可以直接使用 官方工具,選擇合適的 Xdebug 版本。
本地文件和遠端文件映射關系
如上圖,在使用 PhpStorm 時進行遠程調試時,需要配置本地文件和遠端文件的目錄映射關系,這樣 IDE 才能根據 Xdebug 傳遞的當前執行文件路徑與本地文件做匹配,實現斷點調試和單步調試等。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/27628.html
摘要:說明開發和調試環境為本地中的,環境為本地下的。再次在容器中抓取端口數據包連接的源地址已經正確再次使用的斷點調試時,控制臺如下所以,使用進行遠程調試時,需要選擇合適的調試模式,在下建議使用遠程模式。 首發于 樊浩柏科學院 我們經常會使用 PhpStorm 結合 Xdebug 進行代碼斷點調試,這樣能追蹤程序執行流程,方便調試代碼和發現潛在問題。博主將開發環境遷入 Docker 后,Xd...
摘要:連接容器內的進行斷點調試進行斷點調試盡管不像其他語言那樣方便,但是有些是有確實有其用處,比如調試循環內的數據異常時。 PhpStorm連接容器內的XDebug進行斷點調試 php進行斷點調試盡管不像其他語言那樣方便,但是有些是有確實有其用處,比如調試循環內的數據異常時。在php于phpstorm都安裝在同一環境下時,配置phpstorm的xdebug調試并不是多困難的事情,但是如果你使...
摘要:這樣就配置好了安裝插件監聽地址開啟小電話以后,如果訪問會自動進入斷點中的模式,這樣我們的開發環境的斷點調試就已經配置好了。 docker-compose環境來自:https://github.com/zhaojunlik...原文:http://blog.oeynet.com/post/9... 說明 在開發中,斷點調試是我們最快能找出Bug代碼問題的所在,那么在docker中如何使用...
摘要:這樣就配置好了安裝插件監聽地址開啟小電話以后,如果訪問會自動進入斷點中的模式,這樣我們的開發環境的斷點調試就已經配置好了。 docker-compose環境來自:https://github.com/zhaojunlik...原文:http://blog.oeynet.com/post/9... 說明 在開發中,斷點調試是我們最快能找出Bug代碼問題的所在,那么在docker中如何使用...
摘要:寫代碼總繞不過需要調試,除了外,我們還是需要借助進行調試。這里的使用,是分別整合到和下。安裝還是基于神級武器。至于下一步如何更好的使用,就看各自的實際項目和開發需要了。 寫代碼總繞不過需要調試,除了 UnitTest 外,我們還是需要借助 Xdebug 進行調試。 所以今天來說說如何基于本地 Docker 環境下,使用 Xdebug。 這里的使用,是分別整合到 VS Code 和 PH...
閱讀 3096·2021-11-19 09:40
閱讀 1568·2021-11-15 11:39
閱讀 678·2021-10-08 10:05
閱讀 2277·2021-09-03 10:29
閱讀 3411·2021-08-12 13:22
閱讀 2167·2019-08-30 15:54
閱讀 3714·2019-08-30 14:03
閱讀 2658·2019-08-30 13:45