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

che*_*vim 5 php troubleshooting threads dump apache2

我有一个带有 apache httpd 和 PHP 的 linux 系统,它使用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
Run Code Online (Sandbox Code Playgroud)

请注意,XXXXX 类似于昨天的 Jan02。此外,pid (5636) 与我在 apache 的 mod_status 页面中看到的卡住线程的 pid 相匹配。

我的问题是:我怎样才能做一个线程转储或类似的事情来查看这个东西在 PHP 代码中的确切位置?也许它正在等待某些东西(I/O、网络、数据库),但我不知道是什么。

在 Java 世界中,我会做一个kill -3 pid很好的可读线程转储,它会清楚地向我展示该特定线程的确切位置。php土地有类似的技术吗?

小智 2

以下说明以 Linux 为中心:

  • 识别故障/卡住的进程

在您的情况下,该过程处于 state S,意思是来自man ps

S 可中断睡眠(等待事件完成)

所以是的,它可能正在等待某些网络或文件系统操作完成。

  • 跟踪系统调用和信号strace

通过运行以下命令将程序附加strace到挂起的线程:

# strace-p 

这将实时向您显示程序运行的操作或更准确地说是系统调用,例如,您可能会看到一个open()返回错误的循环,例如ENOENT意味着特定文件不存在。

您的ps输出表明该进程没有消耗 CPU(第 3 列),因此这里的问题可能与循环无关,而只是等待操作,例如锁定文件、等待套接字或外部操作。

  • kill和核心转储

用于向正在运行的程序kill发送特定信号的程序与 java 无关,它很好地可以用于发送信号 3 ( SIGQUIT),该信号将关闭程序并生成文件corecore仅当具有正确的权限时才允许生成文件ulimit,请使用命令进行检查ulimit -c。如果它显示0,那么您应该修改它,例如unlimited

ulimit -c 无限

只有这样,您才应该重新启动应用程序并通过发送kill -3.