php进程cpu突高时,应先检查php-fpm慢日志(需手动启用并设低超时),再排查cli定时任务(不走fpm)、用strace跟踪可疑进程,最后检查mysql连接超时与查询卡顿。

查 top 时发现 PHP 进程 CPU 突高,但不知道哪个脚本在跑
宝塔面板自带的「进程管理」只显示 php-fpm 工作进程,不显示具体执行的脚本路径。直接看 top 或面板里的进程列表,只能看到一堆 php-fpm: pool www,根本分不清是 index.php 还是某个定时任务里的 sync_order.php 在狂吃 CPU。
真正有用的线索藏在 php-fpm 的慢日志里,前提是它开了——不是所有宝塔默认启用:
- 进宝塔 → 网站 → 对应站点 → PHP 设置 → 配置修改 → 找到
slowlog行,确认值类似/www/wwwlogs/php_slow.log,且前面没被;注释掉 - 同时检查
request_slowlog_timeout = 1s(建议设成0.5s,太高会漏掉短时爆发) - 改完必须点「重载配置」,否则不生效
开启后,只要某个请求执行超时,就会在慢日志里记录完整调用栈和脚本绝对路径,比如:
[28-May-2024 14:22:31] [pool www] pid 12345<br>script_filename = /www/wwwroot/example.com/api/v3/process.php<br>[0x00007f8b1c0a1234] curl_exec() /www/wwwroot/example.com/lib/Http.php:89
宝塔「计划任务」里跑的 PHP 脚本不走 php-fpm,slowlog 压根记不到
很多用户把定时任务写成「Shell 脚本」,里面用 php /path/to/script.php 直接调用,这种属于 CLI 模式,完全绕过 php-fpm,slowlog 和面板里的 PHP 进程监控都看不见它。
排查这类问题得换思路:
- 先确认是否用了 CLI:进宝塔 → 计划任务 → 看「任务类型」是不是「Shell 脚本」,再点编辑看命令内容里有没有
php开头 - 临时加日志:在脚本开头插入
file_put_contents('/tmp/cli_cpu_debug.log', date('Y-m-d H:i:s') . " START\n", FILE_APPEND);,结尾加同理的 END 日志,配合tail -f /tmp/cli_cpu_debug.log观察执行频率和耗时 - 限制资源:在 Shell 任务命令前加
timeout 30s nice -n 19,防止失控脚本长期霸占 CPU
strace 跟踪单个 PHP 进程,但别在生产环境乱用
当慢日志没抓到、CLI 又没日志、CPU 占用还在跳,就得上 strace——但它对性能影响极大,一次只能盯一个进程,且输出极多,容易把磁盘打满。
安全操作步骤:
- 先用
ps aux | grep 'php' | awk '{print $2}'找出疑似高 CPU 的 PID(看%CPU列) - 用
strace -p PID -e trace=epoll_wait,read,write,openat -s 128 -o /tmp/strace.out,只跟踪关键系统调用,避免全量 trace - 等 10–20 秒后
ctrl+c中断,立刻用head -50 /tmp/strace.out看最近在反复 open 哪个文件(比如不停读/dev/random或循环 include 同一个配置)
注意:strace 不能跨进程,PHP-FPM 多进程下,你抓到的可能只是刚启动的空闲子进程,得配合 top -Hp PID 看线程级 CPU 占用再选目标。
数据库查询卡住也会让 PHP 进程假死在 mysql_query 上
PHP 脚本本身逻辑简单,但卡在 MySQL 查询上时,top 显示 CPU 高,slowlog 却没记录——因为慢的是 SQL,不是 PHP 执行时间。
快速验证方法:
- 进宝塔 → 数据库 → 选择对应库 → 点「phpMyAdmin」→ 左侧选中库 → 点「SQL」→ 执行
SHOW PROCESSLIST;,重点看State列是不是Sending data、Copying to tmp table或长时间Locked - 如果发现某条查询
Time超过 5 秒,复制它的Info字段,在「性能分析」里看执行计划(EXPLAIN) - 临时缓解:在 PHP 代码里给
mysqli或PDO加超时,比如$pdo->setAttribute(PDO::ATTR_TIMEOUT, 5);
最常被忽略的一点:宝塔「网站」页面里每个站点的「PHP 版本」设置,和「数据库」页面里「MySQL 配置」是两套独立配置。PHP 连接池参数(如 mysql.connect_timeout)改了,但 MySQL 服务端的 wait_timeout 还是 28800,连接空闲太久被服务端断开,PHP 就会卡在重连逻辑里,表现就是 CPU 高、无日志、无报错。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











