张墨轩的技术宅

不忘初心,方得始终

Xdebug调试PHP原理浅析

用很多工具写过PHP,最后还是发现PhpStorm最好用,同时用PhpStorm搭配Xdebug调试PHP也很舒服。至于如何配置Xdebug网上已经有了太多文章可以参考,这里不再说明,本文只是简单的记录一下Xdebug调试PHP的原理和过程。

要进行调试有三个必要组件:

组件一:实现了DBGP调试协议的调试插件,这个PhpStorm默认就已经包含了,设置里面也可以看到相关设置,如图:
通过点击导航栏上电话一样的按钮(如下图),PhpStorm会开启9000端口进行监听。
通过进程信息可以清楚的看到PhpStorm已经在监听9000端口。如下图:
DBGP协议介绍地址:

组件二:PHP的Xdebug扩展。下载地址为:
Xdebug作为PHP扩展模块将会被PHP所加载,加载成功后可以通过 php -m 命令 或者 phpinfo() 函数查看。如下图:
php.ini文件中的配置示例:

[Xdebug]
zend_extension=E:\php-5.4.8-Win32-VC9-x86\ext\php_xdebug-2.4.0rc3-5.4-vc9.dll
xdebug.profiler_enable=on
xdebug.trace_output_dir="../xdebug"
xdebug.profiler_output_dir="../xdebug"
xdebug.idekey=PhpStorm
xdebug.remote_handler=dbgp
xdebug.remote_enable=on

组件三:Chrome浏览器的xdebug helper扩展。安装地址(记得翻墙):

当把上面三大必要组件都配置好后(具体配置网上很多文章都有详细介绍),就可以开始调试了。具体的调试原理如下:
1. 运行WEB服务器(如Apache),Apache会加载PHP,PHP会加载Xdebug扩展模块。
2. WEB浏览器(如Chrome)会通过80端口访问 WEB服务器中的某个PHP文件
3. WEB服务器会调用PHP解释器解析PHP文件,如果开启调试的话,PHP会通过Xdebug(根据php.ini中的Xdebug配置)主动连接调试客户端,默认是localhost:9000,如图:
也就是说 PHP会通过Xdebug扩展模块主动连接上PhpStorm正在监听的9000端口,从而PHP会与PhpStorm建立起调试会话通讯,这样程序员就可以通过PhpStorm对PHP程序进行各种调试交互动作了,比如查看变量值,比如下断点等等。
4. 当PHP的代码执行完毕以后,Xdebug会断开与PhpStorm的连接,从而结束本次调试会话过程。

交互流程如下:

browser <==> Port 80 <==> Apache+PHP+Xdebug <==> Port 9000 <==> PhpStorm(DBGP Plugin)

文章写到这里,可能细心的朋友就发现了。Chrome浏览器的xdebug helper扩展 这个部分一直没有提起。不是说它是三大必要组件之一吗!确实,从操作体验上来看用Chrome浏览器配合xdebug helper扩展确实会体验好很多,但是从纯技术角度来讲,它确实不是必须的,因为你想啊,PHP是一门服务端语言,调试也是服务端调试,怎么需要某个特定的浏览器呢?难道只能用Chrome浏览器,其他的浏览器不行吗,这个从技术角度来讲说不过去啊。事实上确实与特定浏览器没有关系,Chrome浏览器的xdebug helper扩展实际作用其实只是设置了一个标志在cookie中,当浏览器访问服务端时,这个cookie值会被传到服务端,这样Xdebug读取到这个值后就知道本次请求用户是想要开启调试功能,它才会连接调试客户端建立调试会话。
上图就是浏览器传给服务端的cookie值,意味着要开启调试。

所以简单来讲,不管用的是什么浏览器,其实只要设置对了相应的cookie值,就可以开启调试。在我这个示例当中还可以直接利用下面的代码来开启调试:
<div id="xdebug_bookmarklets" class="hide" style=" displayblock" >
    <h3>Bookmark these links for future use </h3>
    <h4>Debug: </h4>
    <ul class= "starlist" >
        <li>< a id="xdebugStartSession" href="javascript:(/** @version 0.5.2 */function() {document .cookie='XDEBUG_SESSION='+'PHPSTORM'+';path=/;';})()"> Start debugger</a></li>
        <li>< a id="xdebugStopSession" href="javascript:(/** @version 0.5.2 */function() {document .cookie='XDEBUG_SESSION='+''+';expires=Mon, 05 Jul 2000 00:00:00 GMT;path=/;';})()"> Stop debugger</a></ li>
        <li>< a id="xdebugThisPage" href="javascript:(/** @version 0.5.2 */function() {document .cookie='XDEBUG_SESSION='+'PHPSTORM'+';path=/;';document. location.reload(); document.cookie='XDEBUG_SESSION='+''+';expires=Mon, 05 Jul 2000 00:00:00 GMT;path=/;';})()" >Debug this page </a></li>
    </ul>
    <h4>Profile: </h4>
    <ul class= "starlist" >
        <li>< a id="xdebugStartProfiler" href="javascript:(/** @version 0.5.2 */function() {document .cookie='XDEBUG_PROFILE='+'1'+';path=/;';})()"> Start profiler</a></li>
        <li>< a id="xdebugStopProfiler" href="javascript:(/** @version 0.5.2 */function() {document .cookie='XDEBUG_PROFILE='+''+';expires=Mon, 05 Jul 2000 00:00:00 GMT;path=/;';})()"> Stop profiler</a></ li>
    </ul>
    <h4>Function Trace: </h4>
    <ul class= "starlist" >
        <li>< a id="xdebugStartTracer" href="javascript:(/** @version 0.5.2 */function() {document .cookie='XDEBUG_TRACE='+'1'+';path=/;';})()"> Start tracer</a></li>
        <li>< a id="xdebugStopTracer" href="javascript:(/** @version 0.5.2 */function() {document .cookie='XDEBUG_TRACE='+''+';expires=Mon, 05 Jul 2000 00:00:00 GMT;path=/;';})()"> Stop tracer</a></ li>
    </ul>
</div>
本质就是设置一个cookie值而已。
当然其实还有个更简单的办法 就是直接在请求的url后面连上一个&XDEBUG_SESSION_START=1,这样也开启了调试。

其实不单单是PhpStorm,其他编辑器如 vim,notepad++等编辑器装上DBGP调试插件后也都能进行PHP调试,原理流程也和上文介绍的一样,只是调试客户端不同而已。
下面是notepad++的DBGP调试插件的下载地址:
下面是vim插件下载地址:


浅析微信x5内核inspect调试

最近做一个基于微信公众号的产品,用到了微信的x5浏览器调试的功能,这里简单的做个总结。站在微信客户端角度来讲,微信公众号其实就是由一系列的网页组成的程序,它运行在微信内置的浏览器中,产品的调试就是网页的调试,这里就涉及到一个远程调试网页的问题。我们需要在开发机上远程调试位于手机上的微信内置浏览器中的网页。庆幸的是现在这已经不是什么大问题,腾讯X5浏览服务中已经提供了相应的解决方案,相关资料在 
在分析腾讯X5的方案前,我们先回顾一下google的解决方案:
利用google chrome浏览器支持远程调试也已经有蛮长一段时间了,它本身也在不断的升级和变化,我们先来看看它以前的模式,然后再看看现在的模式。
以前的模式的资料在:
这里需要重点说明的部分是我们在进行远程调试时 在开发机的chrome浏览器中运行的调试工具其实本身就是个web程序,名字叫做 WebInspector 它是由html,css,javascript写成的,chrome浏览器自带了这个web程序,路径在chrome-devtools://devtools/bundled/devtools.html,新版的chrome浏览器路径已经改成了chrome-devtools://devtools/bundled/inspector.html,可以自行打开看看,你如果不信这是网页程序的话,你可以打开后再按f12呼出chrome原生的网页调试工具,你会神奇的发现屏幕上2个一模一样的调试工具,其中一个调试工具正在调试另外一个调试工具。如图:
这个调试工具本身就是个web程序,那么我们也可以把它当一个网站放到互联网上去访问,google确实这样做了,比如你可以访问:
这个调试工具,严格说应该叫做调试前端工具,它由html,css,javascript实现,怎么跟后端的被调试程序通讯呢,这里使用的是websocket的方法。通过文档我们知道调试前要执行命令
adb forward tcp:9222 localabstract:chrome_devtools_remote  通过adb将9222端口转发到手机端去。流程如下:

WebInspector(html,css,javascript实现,运行在浏览器中) ==>websocket==>adb守护进程==>手机端adbd==>被调试程序
chrome后来又推出了新的支持远程调试的方法,新的方法号称不再需要adb了,操作也更加简单,与chrome浏览器集成度更高了。资料参考:
虽然号称不需要adb,其实也只是chrome内部集成了adb的功能而已,所以外部就不需要adb这个程序配合了。当然如果外部存在adb守护进程的话,chrome还是会尝试连接外部adb的5037端口建立连接。 同时既然不需要adb了那也不存在9222端口进行转发到手机了,那做为调试前端的WebInspector又怎么跟后端被调试程序进行通讯了,答案是chrome暴露出来的js内部接口,
WebInspector通过javascript调用chrome内部的调试功能,直接与chrome浏览器通讯。
WebInspector==>内部接口==>chrome浏览器==>手机端adbd==>被调试程序

或者是

WebInspector==>内部接口==>chrome浏览器==>5037端口==>adb守护进程==>手机端adbd==>被调试程序

最后看看远程调试微信webview是如何实现的,其实用的就是chrome远程调试老的方法。

第一步在手机上安装TbsSuiteNew.apk,这个app关键的功能就是将微信的浏览器内核换成一个暴露了9222调试端口的x5浏览器内核。
第二步是运行调试包里面的inspector.py,打开这个inspector.py文件看看代码,就知道其实主要就做了两件事情,第一就是利用adb forward命令将本机9222端口转发到手机端的9222端口上,然后就是启动一个简单的web服务器,它会监听9223端口,这个web服务器的目的就是让浏览器能够通过http://localhost:9223/inspector.html这样的地址可以访问到我们前面说到的WebInspector这个由html,css,javascript实现的调试前端工具。如图:
有兴趣的人可以自己去研读这些代码。
第三步在开发机中用chrome浏览器打开http://localhost:9222,因为9222端口已经转发到了手机上的x5内核,所以这个时候手机上的x5内核就会返回待调试的页面给开发机上的chrome浏览器,然后用户选中某个要调试的页面,又会打开http://localhost:9223/inspector.html?host=localhost:9222&page=2这样的页面,前面已经说过,这个时候就已经运行起了WebInspector这个调试前端工具,然后WebInspector会通过websocket的方式连接本地的9222端口,因为这个端口已经转发到了远端手机上的x5内核的9222的端口上,到此调试会话已经建立起来,用户就可以进行调试工作了。事实上如果手机和开发机都连接在同一个内网中,那么不用adb也没问题,假设我们的手机ip地址为192.168.104,那么这个时候我们只需要先将http://localhost:9222 替换成http://192.168.1.104:9222。 然后把具体调试页也换成如 http://localhost:9223/inspector.html?host=192.168.1.104:9222&page=2 这样子就可以了。
下面是调试"这个调试工具"的截图,可以清楚的看到通过websocket连到了9222端口:
流程如下:
WebInspector(开发机)==>websocket(本机9222端口)==>adb守护进程(开发机)==>adbd(手机端)==>腾讯X5内核(手机端)
或者是
WebInspector(开发机)==>websocket(192.168.1.104:9222端口)==>腾讯X5内核(手机端)

总结:

WebKit 是一个开源的浏览器引擎,apple和google等都在使用它,虽然现在google推出了blink,但是它也是一个webkit的派生品,微信的x5内核也是一个webkit的派生品,所以如果有兴趣进一步了解,完全可以把webkit源代码下载下来研究一下,Inspector的大部分代码都在WebCore/inspector下,有兴趣可以研读。
一些有用的站点和资料:
http://alpha.publicore.net/_/brackets/src/LiveDevelopment/Inspector/inspector.html
https://developer.chrome.com/devtools/docs/debugger-protocol
http://x5.tencent.com/index


GapDebug简易分析

最近做前端开发,用到了GapDebug,觉得这工具挺有意思的,就大概研究了下,这里简单总结一下(我的开发环境是win7,设备是nexus5,android5.0)。
GapDebug运行后将自己变成了一个本地web服务器。当打开菜单点击调试器,会弹出调试器,这个调试器其实就是chrome浏览器(事实上其他webkit内核的浏览器也可以),会访问GapDebug(注意此时GapDebug可以看成本地web服务器)提供的页面 。如http://localhost:8080/gapdebug/index.html。调试工具本身就是web页面构成。操作调试工具其实本质上就是操作网页,这时网页会通过ajax访问GapDebug进程,然后GapDebug进程收到访问请求又会去访问adb守护进程,然后adb守护进程又会通过usb线缆或者是tcpip与我的nexus5手机上的adbd守护进程通讯,然后adbd与包含有webkit控件的app通讯。如下:
chrome浏览器(调试工具网页)<==>GapDebug(看成web服务器)<==>adb(默认是5037端口)<==>adbd(手机端)<==>包含webkit的app(手机端)
这里顺便提下chrome这个强大的浏览器,本身也带有远程调试web功能,在浏览器运行chrome://inspect/#devices页面 就可以进行操作,流程都大同小异。如下:
chrome浏览器(chrome://inspect/#devices)<==>adb(默认是5037端口)<==>adbd(手机端)<==>包含webkit的app(手机端)

这里还有一种简单的方式,命令行中运行  adb forward tcp:9222 localabstract:chrome_devtools_remote  然后打开浏览器输入http://localhost:9222 就可以远程调试了。
数据流程如下:
chrome浏览器(http://localhost:9222)<==>adb(9222端口)<==>adbd(手机端)<==>包含webkit的app(手机端)

补充:
1. 想用上面几种调试方法记得先翻墙,因为包含有调试工具页面的url都被墙了,如 appspot.com
2. 另外有兴趣可以用chrome浏览器打开chrome-devtools://devtools/bundled/devtools.html 看看,这个就是网页版的调试工具,强大!!!
3. 如果是调试网页,移动设备需要安装Chrome for Android ,且安卓系统须为Android 4.0+
4. 如果要调试自己app中嵌入的webkit  需要系统为Android 4.4+ 并且原生应用内的WebView须进行相应的调试配置,在代码中加入WebView.setWebContentsDebuggingEnabled(true)。
5. 远程调试要求桌面版Chrome浏览器版本要高于安卓移动设备的Chrome版本号。有条件的最好使用Chrome 的金丝雀特别版Chrome Canary (Mac/Windows)或者Chrome桌面开发版Chrome Dev channel release (Linux)。
6. GapDebug只所以能调试PhoneGap打包的app,本质上还是用了google官方提供的调试功能,所以要求系统是Android 4.4及其以上版本。

参考:


«1»

Powered By Z-Blog 2.2 Prism Build 140101

Copyright phonegap.me Rights Reserved.