PHP项目服务器磁盘爆满:系统级排查与根治方案(含实战问答)
📖 目录导读
- 问题现象与紧急止损
- 快速定位异常大文件(含Linux命令实战)
- PHP项目特有“磁盘黑洞”诱因
- 日志、SESSION、缓存三大元凶深挖
- 脏数据与幽灵进程清理
- 监控预警与自动化脚本
- 常见问答(Q&A)
- 从被动排查到主动防御
问题现象与紧急止损
典型场景:PHP项目(如Laravel、ThinkPHP)运行数月后,服务器突然报警“磁盘空间使用率99%”,导致数据库写入失败、用户上传图片报错甚至网站白屏。

第一步:紧急止血
df -h # 查看各分区使用率 du -sh /var/log # 快速检查日志分区是否爆满
若主分区(通常为或/var)使用率接近100%,立即执行:
- 清空临时目录:
rm -rf /tmp/*(注意:部分PHP进程会写入/tmp) - 暂停非核心服务:如
systemctl stop php-fpm,防止进程继续写盘。
注意:切勿在生产高峰期直接重启服务器,需先定位具体文件后再清理。
快速定位异常大文件(核心命令)
使用find与du组合拳定位“磁盘杀手”:
1 查找超过1GB的文件
find / -type f -size +1G -exec ls -lh {} \; | sort -k5 -hr | head -20
2 分析PHP项目目录结构
du -sh /www/wwwroot/*/runtime # 检查框架运行时目录(如ThinkPHP的runtime) du -sh /www/logs/ # 检查应用日志目录
3 隐藏的“磁盘黑洞”:inode耗尽
即使df -h显示剩余空间,也可能出现“No space left”报错,原因可能是inode耗尽:
df -i # 查看inode使用率 find / -xdev -printf '%h\n' | sort | uniq -c | sort -rn | head -10
常见诱因:大量会话文件(SESSION)、缓存碎片、上传目录中成千上万的缩略图。
PHP项目特有“磁盘黑洞”诱因
PHP项目比其他语言(如Java)更易产生磁盘问题,根本原因在于:
- SESSION文件未自动清理:默认PHP会话存储在
/tmp/sess_*或/var/lib/php/sessions,若gc_maxlifetime设置过长,文件会堆积。 - 日志轮转失效:Laravel日志(storage/logs/laravel.log)重写写入模式,长期不轮转。
- 缓存文件膨胀:Redis/Memcached的磁盘溢出缓存(如swap)、文件缓存(如
cache/*)。
实战案例:某电商平台PHP项目每周产生2GB日志文件,排查后发现:
# 检查Laravel日志大小
ls -lh storage/logs/laravel-*.log | awk '{print $5, $9}'
日志文件laravel-2024-12-01.log达到1.8GB。
日志、SESSION、缓存三大元凶深挖
1 日志清理与轮转策略
# 对超30天的日志进行压缩归档
find /www/logs -name "*.log" -mtime +30 -exec gzip {} \;
# 配置logrotate(关键)
cat > /etc/logrotate.d/php-app << EOF
/www/logs/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
copytruncate
postrotate
/bin/kill -USR1 $(cat /var/run/php-fpm.pid 2>/dev/null)
endscript
}
EOF
2 SESSION文件批量清理
# 查看当前会话文件数 ls /tmp/sess_* | wc -l # 手动清理超过1天未修改的SESSION find /tmp -name "sess_*" -atime +1 -delete # PHP.ini关键参数优化 session.gc_maxlifetime = 1440 # 调整为24分钟 session.gc_probability = 1 session.gc_divisor = 100
3 缓存与临时文件清理
对于使用file缓存的应用(如ThinkPHP的temp目录):
find /www/wwwroot/app/runtime -type d -name "Cache" -exec rm -rf {} \;
rm -rf /tmp/php* # 清理php临时上传文件残留
脏数据与幽灵进程清理
1 被删除但仍被进程占用的文件
某些进程可能打开了一个大文件后又删除了,但文件描述符未释放,导致磁盘空间虚假占用:
lsof | grep '(deleted)' | sort -k7 -rn | head -10 # 找到对应PID后重启进程 kill -HUP <PID>
2 数据库Binlog与慢查询日志
MySQL日志也是常见磁盘杀手:
-- 查看binlog占用 SHOW BINARY LOGS; -- 清理过期binlog PURGE BINARY LOGS BEFORE '2024-12-01 00:00:00';
同时检查/var/lib/mysql/下的ibdata1是否异常增长(通常是未启用独立表空间)。
监控预警与自动化脚本
1 磁盘告警脚本(Shell)
#!/bin/bash
THRESHOLD=80
CURRENT=$(df -h / | awk 'NR==2 {print $5}' | cut -d'%' -f1)
if [ $CURRENT -gt $THRESHOLD ]; then
du -sh /www/logs /tmp /var/log | mail -s "Disk Warning" admin@yourdomain.com
fi
2 PHP项目专属监控点
- 挂载监控:检查
/tmp、/var/lib/php/sessions是否独立分区(避免主分区爆满) - 文件数监控:
find /www -type f | wc -l超过50万触发告警 - 日志增长速率:
watch -n 60 'du -sh /var/log/php-fpm'
常见问答(Q&A)
问1:为什么df -h显示剩余20%,但写入文件仍报错?
答:大概率是inode耗尽,执行df -i检查,常见于上传目录(public/uploads)有数十万个小文件(如用户头像缩略图)。
问2:清理日志后,PHP-FPM进程没有释放空间怎么办?
答:使用lsof | grep '(deleted)'找到被删除但仍被占用的文件(如/var/log/php-fpm/error.log被重命名但未重启进程),需重启对应的PHP-FPM进程。
问3:Laravel项目storage/logs下的laravel-2025-01-01.log为什么无法删除?
答:可能原因:
- 文件权限问题(
chmod 644或chown www:www) - 该文件正被
tail -f或log viewer程序打开 - 启用了
SELinux(检查ls -Z,使用restorecon -R解决)
问4:如何让PHP会话文件自动定期清理?
答:配置php.ini中session.gc_divisor=100及session.gc_probability=1,配合systemctl restart php-fpm生效,也可使用crontab定时清理:
0 */6 * * * find /tmp -name "sess_*" -mmin +30 -delete
问5:用户上传文件直接导致磁盘满,如何预防?
答:建议:
- 对上传文件大小做上限(
upload_max_filesize和post_max_size) - 使用分布式文件系统(如OSS、S3)或单独挂载容量大的磁盘分区
- 设置上传目录定期清理脚本(如
mtime +7删除临时文件)
从被动排查到主动防御
磁盘爆满的根源往往不是空间不足,而是管理缺失,本文建议三步走:
- 应急定位:
df -h→find大文件 →lsof删除文件 - 根源修复:配置日志轮转、会话清理、inode监控
- 长期防御:部署磁盘告警脚本+定期巡检PHP项目特有的日志、SESSION、缓存目录
推荐为PHP项目单独挂载/var/log和/tmp分区,限制/tmp最大为5GB,避免应用日志反噬系统盘。