GDB调试PHP、COREDUMP文件,快速定位出错代码的介绍与演示

1.前言

PHP的调试技巧有很多(xdebug、phpdbg、gdb、zend_debug等等),在PHP函数调用层我们可以用xdebug之类的调试扩展来追踪调试信息,然而当你使用第三方扩展,或者遇到php崩溃的时候,又或者需要对运行中的脚本进行实时调试,就可以使用GDB调试工具来对PHP的SAPI进行跟踪定位,PHP源码内置了GDB初始化脚本.gdbinit,让我们能够从C函数堆栈直接看到PHP函数堆栈,非常方便。GDB调试PHP有3种方式:1.运行脚本调试 2.附加进程调试 3.静态文件coredump调试,下面我们来依次介绍这三种调试技术及应用场景。

2.运行PHP脚本调试

我们知道,PHP的运行环境依赖于SAP的实现,所以当我们在命令行下运行PHP的时候,实质则在对SAP-CLI接口进行调试,看下面的例子。

gdb php7 
l //显示源码
b 1184 //在1184行设置断点
run test.php//执行脚本
continue//继续执行
我们在cli的main函数打上断点,然后就可以s、n的调试整个PHP的执行流程

3.附加进程调试

这种方式是线上脚本调试的福音,通过gdb -p PID 可以指定调试的进程ID。如果某个脚本CPU占用率达到100%,多半是死循环,那么可以通过这种方式快速定位代码位置。下面让我们来看下运行在PHP-FPM下的PHP脚本如何来定位死循环的位置。

<?php

$a = 1;

while(1) {
    $a++;
}
gdb -p XXXX
c
source /tmp/.gdbinit //导入PHP的gdb初始化脚本用于zbacktrace命令
bz
zbacktrace
通过top命令找到死循环的进程id
通过gdb载入该进程,进行代码追踪,通过zbacktrace可以快速的定位到死循环的代码行

4.静态coredump文件分析

gdb还可以调试静态的coredump文件,在这之前请确保:

1.php 编译选项支持 –enable-debug

2.设置linux core文件无限制

ulimit -c unlimited

3.自定义设置coredump文件位置

echo“/tmp /core-%e.%p”> / proc / sys / kernel /core_pattern

下面我们随便从bug.php.net上找一个让php crash掉生成coredump的例子

<?php
class getDestructed {
    public function __destruct() {
        new self;
    }
}
$class = new getDestructed();
php崩溃以后,自动生成了coredumpe文件
gdb php7 -c CORE_DUMP_PATH
source /tmp/.gdbinit
zbacktrace
bt
通过zbacktrace可以快速定位到php的代码处,bt可以定位到C函数堆栈

5.参考

http://www.laruence.com/2011/06/23/2057.html

https://wiki.swoole.com/wiki/page/p-gdb.html

如无特殊说明,文章均为本站原创,转载请注明出处。如发现有什么不对的地方,希望得到您的指点。

发表评论

电子邮件地址不会被公开。 必填项已用*标注