通过工具查询PHP程序堆栈信息

12 篇文章 2 订阅

需求

在线上发现某些进程一直在执行,消耗cpu特别的多。需要查看到底是那一段代码的导致的这种情况。在线上时,程序一直在执行,在不能中断程序的情况下,可以通过下面的工具排查信息。

Top 工具

使用格式:

top [-] [d] [p] [q] [c] [C] [S] [s] [n]

参数说明:

  • d:指定每两次屏幕信息刷新之间的时间间隔。当然用户可以使用s交互命令来改变之。
  • p:通过指定监控进程ID来仅仅监控某个进程的状态。
  • q:该选项将使top没有任何延迟的进行刷新。如果调用程序有超级用户权限,那么top将以尽可能高的优先级运行。
  • S:指定累计模式。
  • s:使top命令在安全模式中运行。这将去除交互命令所带来的潜在危险。
  • i:使top不显示任何闲置或者僵死进程。
  • c:显示整个命令行而不只是显示命令名。

通过top查询某个进程的所有线程信息。

top -Hp pid可以查看某个进程的线程信息
-H 显示线程信息,-p指定pid

[root@iz2ze4u1jmuziiojqy873fz]~# top -Hp 22748
top - 14:42:10 up 33 days, 16:29,  1 user,  load average: 1.40, 0.59, 0.29
Threads:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.4 us,  0.4 sy, 99.3 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1882088 total,   156740 free,   595876 used,  1129472 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1104448 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
22748 root      25   5  238952   9444   6100 R 98.3  0.5   2:05.30 php

通过top工具可以拿到消耗CPU最高的进程ID信息。

gdb 工具

GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具,可以用来调试C/C++开发的程序,PHP和Swoole是使用C语言开发的,所以可以用GDB来调试PHP+Swoole的程序。

使用方法

gdb -p 进程ID
gdb php
gdb php core

跟踪正在运行的PHP程序,使用gdb -p 进程ID
使用gdb运行并调试PHP程序,使用gdb php -> run server.php 进行调试
PHP程序发生coredump后使用gdb加载core内存镜像进行调试 gdb php core
如果PATH环境变量中没有php,gdb时需要指定绝对路径,如gdb /usr/local/bin/php

常用命令

  • p:print,打印C变量的值
  • c:continue,继续运行被中止的程序
  • b:breakpoint,设置断点,可以按照函数名设置,如b zif_php_function,也可以按照源代码的行数指定断点,如b src/networker/Server.c:1000
  • t:thread,切换线程,如果进程拥有多个线程,可以使用t指令,切换到不同的线程
  • ctrl + c:中断当前正在运行的程序,和c指令配合使用
  • n:next,执行下一行,单步调试
  • info threads:查看运行的所有线程
  • l:list,查看源码,可以使用l 函数名 或者 l 行号
  • bt:backtrace,查看运行时的函数调用栈
  • finish:完成当前函数
  • f:frame,与bt配合使用,可以切换到函数调用栈的某一层
  • r:run,运行程序

zbacktrace

zbacktrace是PHP源码包提供的一个gdb自定义指令,功能与bt指令类似,与bt不同的是zbacktrace看到的调用栈是PHP函数调用栈,而不是C函数。

下载php-src,解压后从根目录中找到一个.gdbinit文件,下载地址 注意选择你自己的PHP版本

gdb -p 22748
(gdb) source /path/to/.gdbinit
(gdb) zbacktrace
[0x7ff7e7e13030] (main) /data/www/test/index.php:8
(gdb) zbacktrace
[0x7ff7e7e13030] (main) /data/www/test/index.php:8
(gdb) zbacktrace
[0x7ff7e7e13030] (main) /data/www/test/index.php:8

多执行几次发现是某段代码一直卡住了。查看这段代码即可跟踪解决问题。

cat /data/www/test/index.php

<?php


// 写一个死循环

$a = 1;
$total = 100000000;
while ($a) {
   if ($total <= 0) {
   	$a =  0;
   }
   //$total -= 1;
}

.gdbinit还提供了其他更多指令,可以查看源码了解详细的信息。

strace 工具

strace可以跟踪系统调用的执行情况,在程序发生问题后,可以用strace分析和跟踪问题。 使用方法:

FreeBSD/MacOS下可以使用truss

strace -o /tmp/strace.log -f -p $PID

  • -f 表示跟踪多线程和多进程,如果不加-f参数,无法抓取到子进程和子线程的运行情况
  • -o 表示将结果输出到一个文件中
  • -p $PID,指定跟踪的进程ID,通过ps aux可以看到
  • -tt 打印系统调用发生的时间,精确到微妙
  • -s 限定字符串打印的长度,如recvfrom系统调用收到的数据,默认只打印32字节
  • -c 实时统计每个系统调用的耗时
  • -T 打印每个系统调用的耗时
[root@iz2ze4u1jmuziiojqy873fz]~# strace -p 22748
strace: Process 22748 attached


发现一直卡住了,也可以知道,程序进入了死循环。

参考信息:
https://blog.huoding.com/2015/10/16/474
https://www.php.cn/php-weizijiaocheng-417726.html
https://www.linuxidc.com/Linux/2018-01/150654.htm
https://blog.csdn.net/cs729298/article/details/81906375

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值