搞清楚原理,一切明了
xdebug调试原理
-
IDE(如PhpStorm)已经集成了一个遵循BGDP的Xdebug插件,当开启它的时候, 会在本地开一个Xdebug调试服务,监听在调试器中所设置的端口上,默认是9000,这个服务就会监听所有到9000端口的链接。在PhpStorm中,位于:工具栏 > Run > Start / Stop Listening for PHP Xdebug Connetions。
-
当浏览器发送一个带 XDEBUG_SESSION_START 的参数的请求到服务器时,服务器接受后将其转到后端的php处理,如果php开启了xdebug模块,则会将debug信息转发到客户端IP的IDE的调试端口上。当参数或者cookie信息中不带 XDEBUG_SESSION_START ,则不会启动调试。这就为后续在浏览器中添加开关提供了可能。Xdebug的官方给出了一个示例图:很好的展示了相互调用关系。 这个示例图是绑定了ip,即使用了固定ip地址,xdebug.remote_connect_back = 0 ,也是 Xdebug 的默认方式,这种情况下,Xdebug 在收到调试通知时会读取配置 xdebug.remote_host 和 xdebug.remote_port ,默认是 localhost:9000,然后向这个端口发送通知,这种方式只适合单一客户端开发调试。
-
另外一种方式则是不绑定IP,Xdebug根据请求来源(REMOTE_HOST)来发起调试。示例图如下:
那从用户发起请求到,到IDE的整个流程图如下:
当用户的请求参数或者cookie中不带调试信息,数据流就是浏览器到Apache(或其他web容器)到PHP,如果加上了调试参数,则请求还会由PHP转给Xdebug处理,Xdebug再把信息转发给IDE,完成调试功能。
配置xdebug参数
由前面的原理我们知道,我们需要给xdebug配置一个ip和端口,给phpstorm配置一个监听端口。
由于xdebug是php的扩展,所以xdebug的参数我们是在php.ini
中配置的,把以下的参数加入到php.ini
文件中并重启php-fpm
:
[xdebug]
zend_extension="/path/to/xdebug.so"
;开启xdebug远程调试功能,On或1都表示开启
xdebug.remote_enable=On
;是否自动开启调试,Off/0都表示不开启
xdebug.remote_autostart=Off
;指定IDE所在电脑的ip或域名(暂时指定本机,即127.0.0.1)
xdebug.remote_host="127.0.0.1"
;打开后,xdebug会忽略remote_host值并自动从$_SERVER中获取来源ip
xdebug.remote_connect_back=On
;指定IDE debug端口(xdebug需要通过该端口与IDE通讯)
xdebug.remote_port=9002
;固定填dbgp(因为目前只支持这个协议,也只有这个协议)
xdebug.remote_handler="dbgp"
;这是一个所有网上的文章都提到要设置但实际上却没啥用的参数(不信你可以注释掉试试,一切都正常)
xdebug.idekey="PHPSTORM"
配置phpstorm debug端口
在phpstorm设置界面,找到下图所示位置并修改成你想要的端口
点击电话图标开启监听端口(我这里的电话图标已经是监听状态,非监听状态电话图标的左上角是红色的🚫符号)
添加调试网站,其中本地文件要与服务器上对应
所以远程调试(如b.abc.com)网站,关键是服务器与开发本机能通讯
远程debug的原理
其实根据前面的原理可知,想要使用phpstorm+xdebug来调试php代码,就必须保证phpstorm与xdebug能“相互通讯”,所以,所谓的远程debug,只要找到一种方法,让你的phpstorm能与xdebug“相互通讯”即可,只要明白了这个,你就能寻找解决方法。
注意:在以下所有类型的远程debug里,都需要保证远程的代码跟本地的代码完全一致,否则调试肯定会出问题。
局域网远程debug
局域网远程debug,是指php代码所在的服务器在内部局域网,你电脑的ip跟服务器的ip同网段,可通相互ping通。例如公司内部有开发服务器,每个人在服务器都建有一个账号,每个人都把代码部署在自己的账号下,phpstorm通过sftp上传,这样几乎相当于本地开发。
假设局域网远程主机只有你一个人用,那么你可以在php.ini
里指定xdebug.remote_host
的值为你本地电脑的ip(即phpstorm所在的那台电脑的ip),这样当xdebug开始debug后,就会与xdebug.remote_host
所指定的ip及xdebug.remote_port
指定的端口连接,这样phpstorm就能与xdebug通讯,只要它们能正常通讯,那么debug就不会有问题。
但如果是像前面说的,是多人开发,你就不能把xdebug.remote_host
的值指定为你电脑的ip,如果指定了,那别人就无法debug了,因为xdebug只会与xdebug.remote_host
指定的ip或域名通讯。
多用户debug需要添加以下配置(在配置xdebug参数的基础上添加以下配置)
xdebug.remote_connect_back=On
使用这个配置后,xdebug.remote_host
设不设置都可以,你不设置(把它注释掉)它也会默认为localhost
,但是只要xdebug.remote_connect_back=On
启用,xdebug就不会使用xdebug.remote_host
指定的ip或域名去连接phpstorm,而是会自动从php的$_SERVER['HTTP_X_FORWARDED_FOR']
(使用了反代)和$_SERVER['REMOTE_ADDR']
(未使用反代)这两个变量中获取来源ip地址(因为这个地址就是phpstorm所在机器的地址),这样自然就能获取到每个人的地址,当然,就算只有你一个人用,你也可以用xdebug.remote_connect_back=On
而不用指定xdebug.remote_host
的方式,这样就不用管是一个人还是多个人了。
另外需要注意,多人开发debug,最好保证相互之间URL中的XDEBUG_SESSION_START
值或COOKIE中的XDEBUG_SESSION
值不同,比如用各自姓名拼音(但实际上测试,就算相同也没问题)。
外网远程debug(单用户)
外网远程调试,主要是要使用ssh远程端口转发(ssh反向隧道)来让外网远程主机能“访问”位于内网的电脑里(phpstorm所在电脑)。
由于使用了ssh端口转发,所以xdebug配置必须保证remote_host
的值为127.0.0.1
或localhost
,因为xdebug的数据传输请求会被ssh隧道传输到你的电脑上,在你的电脑上用127.0.0.1
或localhost
肯定能连上phpstorm
xdebug.remote_host="127.0.0.1"
并且要保证remote_connect_back
值为Off(不写这行或注释掉默认为Off),因为一旦开启这个,remote_host
就会被忽略,根据前面知识可知,remote_connect_back
是自动识别来源ip用的,然而由于phpstorm所在机器的ip并非公网ip,所以识别到的ip肯定连不上(因为识别到的ip是你所在的网络环境的公网ip,即百度搜索“ip”出来的那个ip,这个ip并非你自己电脑的ip)
xdebug.remote_connect_back=Off
在phpstorm所在的电脑上运行以下命令,会在xiebruce@10.37.129.5
服务器上监听9003
端口(你没看错,虽然命令是在你电脑上执行,但却会在远程服务器上开启一个端口监听)
ssh -f -N -R 9003:localhost:9002 xiebruce@10.37.129.5
当使用网页请求并在URL中带上XDEBUG_SESSION_START=xxx
参数或在COOKIE中带上XDEBUG_SESSION=xxx
参数,xdebug即会开启debug,并向xdebug.remote_host
指定的ip(即127.0.0.1
)及xdebug.remote_host
指定的端口发送请求,而这个端口刚好是ssh隧道在服务器端的端口,于是请求会从服务器经过ssh隧道传回本地,并在本地请求localhost:9002
(而这刚好是本地phpstorm监听的端口),这样phpstorm就能跟xdebug通讯,从而完成远程debug。注意,以上的9003你写9002也可以,我故意写成9003方便区分命令中的哪个端口是表示在服务器上监听的端口。
关于ssh端口转发相关知识,如果想详细了解,可查看:SSH端口转发(SSH隧道)。
window可使用xshell建立隧道
请确保在你的 Xshell 左侧的 会话管理器
中已经添加了你的服务器连接。
图片中虽然已经对大部分内容进行了模糊处理,毕竟是外网服务器,如有遗漏之处,也请不要对其进行恶意请求,谢谢。
点开属性,依次选择 连接
>SSH
>隧道
> 添加
请参考图片进行操作
开始debug
“PHP Web Page”外网远程Debug
- 1.在
php.ini
中添加xdebug相关配置,注意xdebug.remote_host="127.0.0.1"
(注意重启php-fpm
); - 2.在phpstorm中修改Debug port,保证它与
php.ini
中的xdebug.remote_port
值相同; - 3.在phpstorm中添加要debug的网站;
- 4.在phpstorm中添加PHP Web Page配置,其中
Server
填写前面添加的网站; - 5.在phpstorm所在机器运行ssh命令建立ssh远程端口转发(反向隧道);
- 6.在phpstorm中点击“小电话”图标开启监听端口(这样xdebug才能往该端口发送数据);
- 7.在phpstorm中添加断点(编辑器行号旁边点一下就会添加一个断点);
- 8.在浏览器中使用浏览器插件(如Xdebug Helper)或在URL中添加
XDEBUG_SESSION_START=xxxx
这样的参数来告诉xdebug你要开启debug; - 9.运行代码,比如刷新浏览器或点击浏览器上的某个按钮(即使是ajax请求的按钮也行,只要这个请求最终能运行到你打断点的那一行代码),如果一切正常,则此时phpstorm会被自动调出,断点行会高亮显示,断点相关的变量也会显示在phpstorm下方的控制台中。