调试生产服务器上卡住的 apache/php 线程

调试生产服务器上卡住的 apache/php 线程

我有一个 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生成文件,请使用命令进行检查。如果它显示,那么您应该将其修改为 ,例如:coreulimitulimit -c0unlimited

ulimit -c unlimited

只有这样你才应该重新启动应用程序并激发核心转储通过发送kill -3

答案2

你想要安装 PHP xdebug 扩展启用跟踪日志。然后它将创建一个文件,其中包含每个执行函数的统计信息 - 完成所需的时间、消耗的内存量、包含该函数的文件路径等。

这些数据将帮助您识别哪些功能需要修复,但请注意,完整的跟踪日志的大小会很快增长,您可能只想跟踪应用程序的一部分(这也在上面的指南中描述)...

相关内容