我有一个 Linux 系统,其中装有 apache httpd 和 PHP,使用 加载LoadModule php5_module /usr/lib/apache2/modules/libphp5.so
。
我启用了 apache 的 mod_status 模块,发现一个特定的线程从昨天开始就卡住了。我还通过ps -axu | grep apache
在众多线程中执行该操作来确认这一点,它给了我那个特定的卡住线程:
www-data 5636 0.0 0.1 423556 23560 ? S XXXXX 0:04 /usr/sbin/apache2 -k start
请注意,XXXXX 类似于 Jan02,即昨天。此外,pid (5636) 与我在 apache 的 mod_status 页面中看到的卡住线程的 pid 匹配。
我的问题是:我如何进行线程转储或类似操作,以便查看 PHP 代码中这个问题究竟卡在了哪里?也许它在等待某些东西(i/o、网络、数据库),但我不知道是什么。
在 Java 世界中,我会执行kill -3 pid
并获取一个可读性良好的线程转储,它将清楚地显示该特定线程卡在何处。php 领域是否有类似的技术?
答案1
以下说明以 Linux 为中心:
- 识别故障/卡住的进程
就您而言,该过程处于状态S
,即从man ps
:
可中断睡眠(等待事件完成)
是的,它可能正在等待某些网络或文件系统操作完成。
- 使用以下方法跟踪系统调用和信号
strace
通过运行以下命令将程序附加strace
到挂起线程:
# strace -p
这将实时向您显示操作,或者更准确地说系统调用例如,当程序运行时,您可能会看到一个循环并open()
返回一个错误,例如ENOENT
意味着某个特定文件不存在。
您的ps
输出表明该进程没有消耗 CPU(第 3 列),因此这里的问题可能与循环无关,而只是等待操作,例如锁定文件、等待套接字或外部操作。
kill
和核心转储
用于向正在运行的程序发送特定信号的程序kill
与 Java 无关,它完全可以用于发送信号 3 ( SIGQUIT
),该信号将关闭程序并生成文件。只有在具有正确的权限时才允许core
生成文件,请使用命令进行检查。如果它显示,那么您应该将其修改为 ,例如:core
ulimit
ulimit -c
0
unlimited
ulimit -c unlimited
只有这样你才应该重新启动应用程序并激发核心转储通过发送kill -3
。
答案2
你想要安装 PHP xdebug 扩展和启用跟踪日志。然后它将创建一个文件,其中包含每个执行函数的统计信息 - 完成所需的时间、消耗的内存量、包含该函数的文件路径等。
这些数据将帮助您识别哪些功能需要修复,但请注意,完整的跟踪日志的大小会很快增长,您可能只想跟踪应用程序的一部分(这也在上面的指南中描述)...