本文目录导读:

在 PHP 项目中,定位磁盘 IO 过高的进程(特别是 PHP-FPM 或 CLI 进程)需要从系统级别和进程级别入手,以下是分步排查方法:
第一步:确认是哪个磁盘分区和哪个进程
-
使用
iostat查看磁盘整体负载(需要sysstat包)iostat -x 1 5
- 关注
%util(磁盘利用率,接近 100% 说明繁忙)、await(IO 等待时间)、r/s、w/s(读写次数)。 - 如果特定分区(如
/dev/sda或/dev/vda)很高,则进一步定位。
- 关注
-
使用
iotop实时查看进程 IO(推荐,需要 root)iotop -oP
-o:只显示有 IO 的进程。-P:只显示进程(不显示线程)。- 按
P键按 IO 读写量排序,按p键切换进程/线程模式。 - 重点看:
DISK READ和DISK WRITE数值高的进程。
-
使用
pidstat针对特定进程查看(需要sysstat包)# 先找到可疑的高 CPU/IO 进程 PID pidstat -d 1 5
- 输出包括
kB_rd/s、kB_wr/s等。
- 输出包括
第二步:定位 PHP 进程内部行为
如果确认是 PHP 进程(如 php-fpm 或 php)导致的 IO 高,需要深入 PHP 代码层面:
-
查看 PHP 进程打开的句柄(文件描述符)
# 假设 PHP 进程 PID 是 12345 ls -l /proc/12345/fd/ | grep -E "(日志|缓存|session|暂存文件路径)" | head -20 lsof -p 12345 | grep -E "REG|DIR" | sort -k 8 | head -20
- 常见高 IO 来源:
/tmp/sess_*(PHP Session 读写频繁,特别是文件存储模式)/var/log/(日志写入过于密集,如access.log、error.log)- 文件缓存目录(如 Smarty、Twig 或 Laravel 视图缓存)
- 图片上传、文件批量处理
- 常见高 IO 来源:
-
开启 PHP 的 strace 跟踪(临时,谨慎)
# 跟踪文件写入系统调用 strace -p 12345 -e trace=write -c -S time 2>&1 | head -20 # 或者跟踪文件打开创建 strace -p 12345 -e trace=openat,creat -c 2>&1
- 观察频繁写入或读取的文件名或路径模式。
/tmp/sess_abc123或/var/www/html/storage/logs/laravel.log。
- 观察频繁写入或读取的文件名或路径模式。
-
分析 PHP 代码中的 IO 热点
- 日志:检查是否有循环/高频的日志写入(如
error_log()、Monolog的Debug级别、var_dump到日志)。 - Session:如果不必要的 Session 写入(如每次请求都修改
$_SESSION),切换为 Redis/Memcached 存储。 - 文件缓存:检查框架的视图编译缓存、配置缓存是否每次请求都重新生成。
- 大文件处理:是否有
file_get_contents读取大文件、fwrite频繁写临时文件。
- 日志:检查是否有循环/高频的日志写入(如
第三步:常见 PHP 高 IO 场景与优化方向
| 场景 | 表现 | 解决方法 |
|---|---|---|
| Session 文件频繁读写 | IO 集中在 /tmp/sess_*,iowait 高 |
切换 Session 驱动到 Redis(session.save_handler = redis) |
| 框架 Debug 日志级别 | 日志文件每秒写入大量 DEBUG 行 | 生产环境日志级别设为 WARNING 或 ERROR |
| 视图编译缓存未开启 | 每次请求都重新编译模板(如 Laravel Blade) | 开启视图缓存(php artisan view:cache) |
| 文件上传/图片处理 | 批量 file_put_contents、imagejpeg |
使用队列异步处理,或使用 CDN/对象存储 |
| 慢查询+全表扫描 | 数据库查询慢但 IO 高(注意:PHP 进程可能只是在等待数据库返回,实际 IO 在 MySQL) | 检查数据库层面的 IO,而非 PHP 进程本身,使用 pt-ioprofile 或 MySQL 的 slow_query_log。 |
第四步:系统级快速排查命令清单(按优先级)
# 1. 实时查看磁盘 IO 最活跃的进程
iotop -oP
# 2. 查看某个分区上哪些进程在读写(如 /data)
ls -l /proc/*/fd/ 2>/dev/null | grep "/data" | awk '{print $10}' | sort | uniq -c | sort -rn
# 3. 针对 php-fpm 进程快速查看:
ps aux | grep php-fpm | awk '{print $2}' | xargs -I {} sh -c 'echo "PID={}"; ls -l /proc/{}/fd/ | grep "sess\|log\|cache"'
# 4. 如果是 Linux,使用 blktrace(高级)
blktrace -d /dev/sda -c 60 | blkparse -i - | grep php
典型排查流程
iotop -oP→ 看到php-fpm进程在大量写入。lsof -p [PID]→ 发现大量/tmp/sess_*句柄。- 判断 → Session 存储为文件,且并发高(每个请求都写 Session)。
- 解决 → 修改
php.ini:session.save_handler = redis,并检查session.auto_start设置,避免不必要写入。
如果问题不是 PHP 自身 IO,而是 PHP 进程被阻塞等待数据库/文件锁,那么表面上是 PHP 进程在消耗 IO,实际瓶颈在数据库或文件系统/NFS,这时需要结合 strace 观察系统调用是否卡在 connect、accept(网络等待)或 flock(文件锁)上。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播