大型服务器端程序的调试方法跟运行在个人电脑或者手持设备的程序的调试思路完全不一样,主要体现在下面几点:
- [ ] 服务器端一般是一个受限的环境,你无法安装你所需要的所有工具和依赖的库
- [ ] 服务器程序的Bug跟某些特定逻辑相关,这个特定逻辑可能你还未知,或者在自己PC上面很难模拟触发(比方说大容量访问的时候)
- [ ] 触发机制,你总是希望在错误发生的时候,能够获取系统的关键信息用以辅助定位问题
- [ ] 既能够自动保存关键信息,但是对现有系统的性能有较小影响
所以,对于上诉的需求,你需要一个可配置的轻量级调式方法(库)来帮助你定位php系统的问题,xdebug是一个不错的选择。
- 以ubuntu为例,安装xdebug
apt-get install php70-debug
当然如果你的系统不是ubuntu,你可以到xdebug官网上面去寻找对应的版本。
-
配置xdebug
xdebug有非常丰富的配置选项,我们从最简单的开始
zend_extension = "xdebug.so" xdebug.auto_trace = 0 xdebug.show_exception_trace = 0 xdebug.collect_vars = 1 xdebug.collect_return = 1 xdebug.collect_params = 4 xdebug.trace_output_dir = "/tmp/xdebug" xdebug.profiler_append = 0 xdebug.profiler_enable = 1 xdebug.profiler_enable_trigger = 0 xdebug.profiler_output_dir = "/tmp/xdebug" xdebug.profiler_output_name = "cachegrind.out.%t-%s"
xdebug.auto_trace = 1 这个参数要慎用,这个是xdebug会自动跟踪错误,但是在绝大部分过程中,会导致额外的问题。
xdebug的配置文件放在/etc/php7/mods-available/xdebug.ini
-
var_dump
var_dump的价值很大程度上被新手低估,实际上var_dump有可能是你的第一(唯一)选择,php是一个动态语言,并不需要编译就可以运行,这里使得调试就非常的方便,通过var_dump来获取一些关键信息,缩小故障范围就非常有效。这里提及var_dump的原因是这个函数是php本身就支持的,但是自带的版本非常不适合阅读,在安装了xdebug之后,xdebug会格式化var_dump的输出,可阅读性大大增加。var_dump的使用非常简单:
var_dump($this);
在浏览器里面的可能输出:
object(main)[19] public 'user_id' => int 1 public 'user_info' => array (size=57) 'uid' => int 1 'user_name' => string 'user1' (length=9) 'email' => string 'user@aaa.com' (length=21) 'mobile' => null 'password' => string 'd55ca4ba28f97df06702c339edce8309' (length=32) 'salt' => string 'wlxb' (length=4) 'avatar_file' => null 'sex' => null 'birthday' => null 'province' => null 'city' => null 'job_id' => int 0 'reg_time' => int 1478519086 'reg_ip' => int 2886795265 'last_login' => int 1479277954 'last_ip' => int 2886795265 'online_time' => int 41488 'last_active' => int 1479277989
-
使用Log
在调试服务器端程序的时候,Log是最为基础同样也是最为重要的工具,Log可以帮助你记录事件发生前后发生的事件,帮助你定位问题,几乎所有的复杂问题调查都是从分析Log开始的。下面几个参数跟trace的输出结果相关。
xdebug.collect_vars = 1 xdebug.collect_return = 1 xdebug.collect_params = 4 xdebug.trace_output_dir = "/tmp/xdebug"
都比较好理解,xdebug.collect_params = 4 设定用于trace的输出方式,可以选择1-4,下面以4举例:
TRACE START [2007-05-06 14:37:16] 0.0003 114112 -> {main}() ../trace.php:0 0.0004 114272 -> str_split('Xdebug') ../trace.php:8 0.0007 117424 -> ret_ord($c = 'X') ../trace.php:10 0.0007 117584 -> ord('X') ../trace.php:5 0.0009 117584 -> ret_ord($c = 'd') ../trace.php:10 0.0009 117584 -> ord('d') ../trace.php:5 0.0010 117584 -> ret_ord($c = 'e') ../trace.php:10 0.0011 117584 -> ord('e') ../trace.php:5 0.0012 117584 -> ret_ord($c = 'b') ../trace.php:10 0.0013 117584 -> ord('b') ../trace.php:5 0.0014 117584 -> ret_ord($c = 'u') ../trace.php:10 0.0014 117584 -> ord('u') ../trace.php:5 0.0016 117584 -> ret_ord($c = 'g') ../trace.php:10 0.0016 117584 -> ord('g') ../trace.php:5 0.0019 41152 TRACE END [2007-05-06 14:37:16]
在php代码中使用,记得这个要成对使用,否则长期运行trace会导致系统性能问题(特别是磁盘)
string xdebug_start_trace( [ string trace_file [, integer options] ] )
string xdebug_stop_trace()
如果xdebug.collect_vars = 1 开启变量打印功能,常用的函数有下面几种:
void xdebug_debug_zval( [string varname [, ...]] )
void xdebug_dump_superglobals()
array xdebug_get_declared_vars()
详细的参数说明可以参考xdebug的网页,如下:
https://xdebug.org/docs/execution_trace
-
如何更好的查看Log