2017年05月26日 
 经验心得

作者:廖新喜

原文地址:PhpStorm Xdebug远程调试环境搭建原理分析及问题排查

网上关于 phpstorm 调试的文章很多,真实实践过的不多,都是几篇文章转来转去,没有原理分析,甚至有些文章的配置文件都是错的,我就是按照一篇错误的配置一路走过来的,不过好歹把这些坑都给埋了,这篇文章不仅仅有操作,还有原理分析,更有问题排查思路。

对于简单的工程,直接print_r();exit()已经足够,但是对于大型项目有时就有点力不从心,如果直接将 apache 部署在本地,phpstorm 调试本地代码这种方式也可以,我以前就是这么干的,这篇文章主要介绍远程调试系问题排除。

一. 环境介绍

本地:windows7(192.168..)+ phpstorm8

远程:Ubuntu14.04(192.168.3.206)+ apache2 + php5

二. 远程环境配置

2.2 Xdebug安装

Ubuntu下直接apt-get安装,安装命令如下:apt-get install php5-xdebug

2.3 配置

首先通过locate定位到 xdebug.ini,这个位置一定得对,在 Ubuntu 上位于/etc/php5/apache2/conf.d/20-xdebug.ini

zend_extension=xdebug.so
xdebug.idekey=PHPSTORM
xdebug.remote_connect_back = 1
;//如果开启此,将忽略下面的 xdebug.remote_host 的参数 ;xdebug.remote_host=192.168.x.x
; //注意这里是,客户端的ip<即IDE的机器的ip,不是你的web server> xdebug.remote_enable=on
xdebug.remote_port = 9001
;//注意这里是,客户端的端口<即IDE的机器的ip,不是你的web server> xdebug.remote_handler = dbgp
xdebug.auto_trace = 1
xdebug.remote_log = /tmp/xdebug.log

三. 本地phpstorm配置

下面的配置有执行顺序要求,请一步一步来。

3.1 下载远程代码

phpstorm在新建项目的时候提供了选项,可以通过ftp/sftp远程下载代码,直接按照提示下一步下一步就可以。

3.2 添加php解释器

通过file->settings->Languages & Frameworks找到php栏。

3.3 配置Debug

路径还是在file->settings->Languages & Frameworks->PHP,选择Debug,选择要监听的端口,这里设置为9001,如图所示:

设置完端口还需要设置DBGp Proxy,配置如下:

在设置完Debug页面后,在DBGp Proxy页面的端口已经确定,添加上IDE key为刚才Xdebug配置文件设置的key:PHPSTORM,Host则为要调试的远程主机。

3.4 配置Server

通过file->settings->Languages Frameworks->PHP找到Servers,Host对应远程主机IP, Debugger 选用 Xdebug ,如果是远程调试,一定得开启路径映射功能,否则无法调试,本地的路径不用选,在新建远程项目的时候就已经确定,Absolute path on the server 则是远程主机的 Web 路径。在途中红框上方有一个 Validate remote environment 可以用来验证远程的 Xdebug 配置,如果配置明显不对的话,会有提示信息,可按照提示信息修改远程服务器的 Xdebug 配置。

3.5 配置调试选项

由于调试的目标是一个项目,所以这里需要设置PHP Web Application,配置中Server:远程目标主机,Start URL设为/,设置完之后会在左侧新建一个PHP Web Application

到目前为止,该配置的都已经配置完成,这里面配置的选项比较多,一步一步配置,有顺序要求。配置完之后就是调试。点击下图右边红框中的小按钮,打开 Xdebug 监听,再选择我们要调试的目标,这里是server,最后点击那个调试按钮,就能开启调试之旅。

打开 Xdebug 监听的时候,可以看到IDE已经在本地建立监听服务,具体如下:

可以看到调试页面。如下所示

3.6 浏览器添加书签或者Xdebug Helper

前面描述的是通过PHPStorm的 debug 按钮,发送类似?XDEBUG_SESSION_START=17212这种请求调起浏览器来达到调试的目的,但是这种方式只能调起首页,存在缺陷。下面介绍另外一种启动调试的方式,就是通过浏览器中带XDEBUG_SESSION 的cookie直接发起,可以安装Chrome插件Xdebug Helper或者添加浏览器的调试插件、或书签来达到目的。新建书签的url:https://www.jetbrains.com/phpstorm/marklets/ , 这里就不再做示例,插件和书签的原理都是一样的,都是在cookie中添加XDEBUG_SESSION=PHPSTORM。

四. 数据流程

前面的配置完全是一个操作指南,如果仅仅是为了配置,上面的内容已经足够,但是如果配置中遇到什么问题,就需要接下来的原理分析。古人说的好,我们得知其然还得知其所以然。

4.1 Xdebug工作原理
  1. IDE(如PhpStorm)已经集成了一个遵循BGDP的Xdebug插件,当开启它的时候, 会在本地开一个Xdebug调试服务,监听在调试器中所设置的端口上,默认是9000,这个服务就会监听所有到9000端口的链接。在PhpStorm中,位于:工具栏 > Run > Start / Stop Listening for PHP Xdebug Connetions。

  2. 当浏览器发送一个带 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参数,导致走了不少弯路,如果仅仅是为了配置PhpStorm及Xdebug原理,关注前面部分即可。下面主要分析排除过程。

错误的配置如下:

zend_extension=xdebug.so
xdebug.idekey=PHPSTORM #xdebug.remote_connect_back = 1 //如果开启此,将忽略下面的 xdebug.remote_host 的参数 xdebug.remote_host=192.168.x.x //注意这里是,客户端的ip<即IDE的机器的ip,不是你的web server> xdebug.remote_enable=on
xdebug.remote_port = 9001 //注意这里是,客户端的端口<即IDE的机器的ip,不是你的web server> xdebug.remote_handler = dbgp
xdebug.auto_trace = 1
xdebug.collect_includes = 1
xdebug.collect_params = 1
;xdebug.collect_return = 1 xdebug.remote_autostart = 1 xdebug.remote_log = /tmp/xdebug.log

问题现象: Apache反应奇慢无比,一个普通请求能耗时10分钟,但是最终会有效应。

排查过程:

5.1 问题背景

本地环境:Windows7,远程服务器:Ubuntu14.04,这个远程服务器是本地环境下VMWare WorkStation下的一台虚拟机,网络连接方式是桥接。在调试远程项目时,作者使用的sftp来管理服务器的资源,这里面就会涉及到权限的问题。远程服务器只开了一个普通账户liaoxinxi,而/var/www 目录以前是root权限的,由于PhpStorm调试时会在远程服务器web目录下创建一个文件,这必然会导致权限问题,为了解决这个问题,执行chmod liaoxinxi:liaoxinxi /var/www -R将web目录修改为liaoxinxi用户所有。当然为了远程调试,我配置了xdebug.ini,这个配置参数当时也不是太清楚具体含义,比较着急,就从某篇号称亲手测试过可用的Xdebug环境拷贝而来。下午比较混沌,当时做过的操作还挺多,Xdebug这个配置我居然忘记我配过了,只记得修改了权限相关内容。重启Apache之后,web请求响应奇慢无比。

5.2 疑问点

5.2.1 权限

当时一股脑的认为是权限的问题,就又把web目录权限全改为777,还是奇慢无比,查看apache日志也没有半点异常。

5.2.2 网络

无意之中发现在远程服务器上直接访问,很快就能得到响应。这个远程服务器是我VMware下的虚拟机,通过桥接模式与宿主机通信。中午与其他同事讨论这个问题的时候将问题排查点转移到网络环境。怀疑是网络的问题,将桥接模式改成NAT,又是重启虚拟机,重启宿主机,都不起作用。

5.2.3 Apache配置

于是又将矛盾转移到Apache的配置上,Apache的配置文件被我改动了很多回,当时觉得很简单所以没设置备份点,一个好的备份是多么重要。只能重装,这个在Ubuntu下还是很简单的,一条命令搞定apt-get auto-remove --purge apache2,并且删除了原有的配置文件。再通过apt-get重新安装,apt-get install apache2,重启apache后发现在本地访问,很快得到响应,不过响应的都是原始的php文件,再安装一下libapache2php模块,安装完之后,响应还是一样的奇慢无比。难道跟这个模块有关系,但是找不到相关资料。再翻看安装apache2的输出信息时发现其重启了Xdebug模块,回想一下,是不是这些模块导致的问题呢?再仔细想想,那天下午好像还改了Xdebug的配置,可能有问题。

5.2.4 Xdebug配置

回到Xdebug的配置文件,其中一个配置xdebug.remote_host=192.168.*.* //这个配置是用来,感觉峰回路转了,因为只有这个ip访问就会奇慢无比,于是注释掉,再重启apache访问,果然奇慢无比的问题解决了。

但是这又带来一个新的问题,这个ip是我的本地环境,如果不配置的话怎么调试呢?于是将//后边的内容用;注释起来,前期一直以为//也是个注释。//这种注释方式在Xdebug中不识别,所以根本不会向IDE所在机器发送调试包,会一直等到超时,所以就会特别慢。 再去调试,在index.php下断点,终于断下来了。调试的过程中发现,开启或者未开启调试参数都会直接进入调试模式,见了鬼了,回想起调试流程图,肯定出问题的地方在Xdebug的配置,打开配置文件,果然发现一个相关参数xdebug.remote_autostart = 1,这个参数的意思就是自动打开远程调试,注释掉就能接收不使用Xdebug调试的参数。

说到最后不得不佩服这位兄弟,挖了两个大大的坑(坑的位置),好歹我全埋了,提醒大家尽量找官方文档,如果官方文档写的不详细的,还是多见识见识几份文档。

综合来看,信息大爆炸的年代,干扰信息太多,各位见仁见智。

PhpStorm Xdebug远程调试环境搭建原理分析及问题排查的更多相关文章

  1. [xDebug] PhpStorm Xdebug远程调试环境搭建

    对于简单的工程,直接print_r();exit()已经足够,但是对于大型项目有时就有点力不从心.. 1,环境介绍 本地:windows10(192.168..)+ phpstorm8远程:Cento ...

  2. 论持久战之PHPStorm Xdebug Remote 调试环境搭建(不依赖本地环境)

    最近公司自己搭建了一个资源管理平台,哈哈,当然是我在github上找的,后台用PHP开发.个人觉得写得非常nice,web页面几乎模拟了真实OS,有兴趣的朋友下载部署体验https://github. ...

  3. PhpStorm XDebug 远程调试

    现在我们自己公司的各种开发和测试服务器,都是使用阿里云的服务器.一些PHP的项目,无法在本地搭建完整的环境,在外网服务器上调试更方便定位问题.发现网上没有完整的关于如何配置PHPStorm和XDebu ...

  4. 一步一步 Pwn RouterOS之调试环境搭建&&漏洞分析&&poc

    前言 本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274 本文分析 Vault 7 中泄露的 RouterOs 漏洞.漏洞影 ...

  5. phpstorm+xdebug远程调试设置

    1 xdebug扩展安装 1.1 xdebug扩展安装: 2 服务器PHP配置 3 phpstorm设置 3.1 添加远程debug 3.2 phpstorm设置: 4 浏览器插件安装 4.1 chr ...

  6. centos7+nginx 1.9.0+php-fpm+phpstorm+xdebug+vmware开发环境搭建

    1.php-fpm yum install php-fpm 默认配置在本地9000端口监听 service php-fpm restart启动 2.nginx 1.9.0 需先安装gcc zlib o ...

  7. XAMPP + PhpStorm + Xdebug本地实验环境搭建

    参考: 下载合适的XDebug 点击这里,选择合适xdebug XAMPP配置 php_xdebug-xxxx.dll 拷贝dll至 D:\XAMPP\php\ext php.ini 文末追加 [XD ...

  8. xdebug远程调试原理分析

    xdebug可以控制PHP程序的执行,这意味着xdebug可以在任何时候暂停或者恢复正在运行的PHP程序.当PHP程序被暂停的时候,xdebug可以获取到程序的有关 信息,比如变量的值等.xdebug ...

  9. Solr4.8.0源码分析(4)之Eclipse Solr调试环境搭建

    Solr4.8.0源码分析(4)之Eclipse Solr调试环境搭建 由于公司里的Solr调试都是用远程jpda进行的,但是家里只有一台电脑所以不能jpda进行调试,这是因为jpda的端口冲突.所以 ...

随机推荐

  1. mybatis结合generator进行分页插件PluginAdapter开发

    使用org.mybatis.generator生成UserExample时,无法进行分页,使用下面这个类运行generator便可以生成分页相关的属性了 package org.mybatis.gen ...

  2. [Bash] Find Files and Folders with `find` in Bash

    find is a powerful tool that can not only find files but it can run a command on each matching file ...

  3. 当Eclipse爱上SVN

    推荐使用:Subclipse  :http://jingyan.baidu.com/article/1612d5007d41e9e20e1eeeff.html 为离线安装做准备: 1.下载Subver ...

  4. Office WORD里面打字,后面的字自动被删除怎么办

    word或其他编辑器里打字以后其后面的字就被自动删除了-解决方案   2011-09-26 14:52:09|  分类: 电脑维护|字号 订阅 解决方法:  再按一下 Insert键 就OK啦 今天有 ...

  5. PHP根据两点间的经纬度计算距离

    /** * 说明: 根据两点间的经纬度计算距离 * @param float $lat 纬度值 * @param float $lng 经度值 */ function getDistance($lat ...

  6. 小胖说事35-----Terminating app due to uncaught exception &#39;CALayerInvalidGeometry&#39;, reason: &#39;CALayer posi

    2011-06-11 15:19:17.167 ***[930:707] *** Terminating app due to uncaught exception 'CALayerInvalidGe ...

  7. Make 编译脚本上手

    考察下面的示例代码: main.c #include <stdio.h> int main(){ printf("hello world!"); return 0; } ...

  8. Handlebars.js 中文文档

    Home  »  前端   »   Handlebars.js 中文文档 Handlebars.js 中文文档 Posted in 前端 By KeenWon On 2014年4月3日 Views:  ...

  9. vim、gvim在windows下中文乱码的终极解决方式

    測试成功,完美解决. 仅仅需改动VIM文件夹以下的这个文件_vimrc. 加油吧,骚年.非常强大的! set encoding=utf-8 set fileencodings=utf-8,chines ...

  10. grep命令使用技巧

    grep如何实现全词查找例如:要查找name这个单词,反馈的查找结果不能包含namespace这样的模式,但是可以包含name()这样的模式,即要查找的单词两端不可以有其他的数字或者字母,但可以有空格 ...