定位 PHP-FPM 进程僵死且 CPU 占用 100% 的问题,最推荐直接使用 top 命令锁定高占用进程 PID,结合 PHP-FPM 慢日志(slowlog)分析代码执行栈,必要时使用 strace 追踪系统调用。
先说结论:PHP-FPM 进程 CPU 满载通常由代码死循环、外部依赖超时重试或进程管理配置不当引起,需优先隔离故障进程再分析日志。
- 先确认:使用 top 命令区分是单个 worker 进程占用高还是 master 进程占用高,确认是否伴随负载(load average)飙升。
- 先处理:对持续占用 CPU 的特定 PID 执行 kill 操作止血,避免影响其他请求,同时保留现场日志。
- 再验证:调整 php-fpm.conf 中的 pm 最大子进程数及 request_terminate_timeout 参数,观察重启后 CPU 是否回落。
命令速用版
以下命令用于快速定位高 CPU 占用的 PHP-FPM 进程及其父进程关系,适用于大多数 Linux 发行版。
# 1. 查找 CPU 占用最高的进程
top -c -o %CPU
# 2. 确认进程是否为 php-fpm
ps -ef | grep php-fpm
# 3. 查看进程树,确认子进程归属
pstree -p | grep php-fpm
# 4. 追踪卡顿进程的系统调用(需替换 PID)
strace -p <PID> -o /tmp/php_strace.log
# 5. 优雅重启 PHP-FPM(不同系统路径不同)
systemctl reload php-fpm
为什么会这样
PHP-FPM 进程 CPU 占用 100% 的核心原因是进程处于持续计算状态或频繁上下文切换,而非单纯的 I/O 等待。
当 PHP 代码中存在死循环、正则回溯灾难或未设置超时的外部 API 请求重试时,Worker 进程会一直占用 CPU 时间片。另一种情况是 pm.max_children 配置过大,导致系统频繁进行进程调度,Master 进程 CPU 升高。如果进程状态为 D 态(不可中断睡眠)但 CPU 高,通常涉及驱动或内核级问题,但 PHP 层面多见于逻辑死锁。
分步处理
按照以下顺序操作,确保每一步都有明确的检查点,避免误杀 Master 进程导致服务全部中断。
第一步:锁定异常进程
登录服务器执行 top 命令,按 Shift+P 按 CPU 排序。观察占用最高的进程命令是否为 php-fpm: pool www 之类的_worker 进程。记录该进程 PID。
第二步:检查慢日志
查看 php-fpm 配置文件(通常在 /etc/php-fpm.d/www.conf 或 /etc/php/8.x/fpm/pool.d/www.conf),确认 request_slowlog_timeout 已开启。读取 slowlog 文件(通常在 /var/log/php-fpm/slow.log),找到对应时间点的堆栈信息,定位具体 PHP 文件行号。
第三步:系统调用追踪
如果慢日志无记录,说明代码未执行完或卡在底层。使用 strace -p <PID> 查看进程卡在哪个系统调用上。如果看到反复的 connect 或 read,说明是外部依赖阻塞。
第四步:调整超时配置
在 PHP-FPM 池配置中设置 request_terminate_timeout = 30s(根据业务调整),防止单个请求无限占用资源。修改后执行 systemctl reload php-fpm 生效。
怎么验证是否生效
执行完处理后,需通过以下指标确认问题是否解决。
1. CPU 指标:使用 top 命令观察 5 分钟,PHP-FPM 进程 CPU 占用率应回落到正常水平(通常单个核的 10%-50% 以下)。
2. 日志指标:检查 php-fpm.log 中不再出现 child exited on signal 9 以外的异常退出日志,slowlog 中不再频繁出现相同堆栈。
3. 业务指标:网站响应速度恢复,监控系统中请求耗时(RT)曲线不再出现持续高位。
常见坑
在处理 PHP-FPM 高 CPU 问题时,以下场景容易导致故障扩大,需谨慎操作。
1. 误杀 Master 进程:kill 命令若指向了 php-fpm 的 Master PID,会导致所有 Worker 进程终止,服务瞬间不可用。务必通过 pstree 确认 PID 角色。
2. 忽略 OPcache:某些情况下 OPcache 缓存损坏会导致进程异常,重启 PHP-FPM 无效时需尝试清除 OPcache 缓存文件或重启 Web 服务器。
3. 盲目调大进程数:CPU 高时增加 pm.max_children 会加剧上下文切换,导致负载更高。应先降低并发数排查代码,再逐步调优。
常见问题
PHP-FPM 进程 CPU 高可以直接 kill 吗?
可以 kill 具体的 Worker 进程 PID,但不要 kill Master 进程。PHP-FPM 机制会自动补充新的 Worker,单独杀死高占用 Worker 能快速释放 CPU 资源。
开启慢日志会影响性能吗?
仅在请求超过设定阈值时才会记录,正常请求无影响。建议生产环境设置 request_slowlog_timeout 为 5s 以上,避免日志写入过频。
strace 追踪会不会加重 CPU 负担?
会。strace 会显著降低被追踪进程的速度,仅建议在测试环境或问题复现时短时使用,生产环境长时间开启可能导致服务不可用。
参考来源
- PHP Official Documentation, "FPM Configuration", php.net.
- Linux Man Pages, "top", "strace", "pstree".