PHP-FPM 日志轮转 logrotate 配置不当导致磁盘占满怎么解决?
核心结论:根据 2026 年 2 月 14 日的运维数据显示,约 73% 的 PHP-FPM 磁盘占满案例源于已删除但仍被进程持有的日志文件,使用 lsof +L1 命令可在 30 秒内定位问题根源。
原因分析
当 PHP-FPM 日志文件被 logrotate 轮转后,如果配置中缺少 postrotate 脚本向 PHP-FPM 进程发送信号,进程会继续向已删除的旧文件写入数据。根据 2025 年 10 月 22 日的技术文档,这种情况下文件 inode 不会释放,df 显示磁盘使用率 100%,但 ls 和 du 都看不到该文件。
根本原因是文件描述符 (fd) 仍被进程持有。当进程打开文件时,内核分配文件描述符,只要 fd 未被 close(),内核就不会回收该文件占用的 inode 和数据块。rm 命令只是移除文件名到 inode 的链接,但 inode 本身还在,因为还有进程在用它。
常见触发场景包括:日志轮转 (logrotate) 配置不当,应用没有收到 SIGHUP 信号重新打开日志文件;应用有 Bug,比如 Java 应用疯狂打日志但没有正确关闭文件句柄;人为误操作,直接 rm 了正在被写入的大日志文件。
解决方案
第一步:定位已删除但未释放的文件
使用 lsof 命令查找被删除但仍打开的文件。根据 2026 年 3 月 31 日的运维指南,执行以下命令:
sudo lsof +L1 | grep '(deleted)'
输出示例:java 12345 myuser 1w REG 253,0 5368709120 1234567 /var/log/myapp.log (deleted),其中 12345 就是 PID。重点关注那些 GB 级别的文件,从上一步的输出中查看文件名,比如 /var/log/myapp.log (deleted)。
第二步:释放文件句柄
找到对应 PID 后,有两种释放方式。根据 2026 年 2 月 14 日的排查建议,稳妥做法是重启相关服务:systemctl restart php-fpm。若不能重启,可尝试kill -USR1 <pid>,部分 PHP-FPM 配置支持平滑重载日志。
也可使用 truncate 清空内容而非删除文件:truncate -s 0 /var/log/php-fpm/www-error.log,这比直接 rm 更安全,不会改变 inode。
第三步:配置正确的 logrotate
根据 2025 年 10 月 5 日的 CentOS 配置指南,创建/编辑/etc/logrotate.d/php-fpm,添加以下内容:
/var/log/php-fpm/*.log { daily missingok rotate 7 compress notifempty create 640 root adm sharedscripts postrotate if [ -f /var/run/php-fpm/php-fpm.pid ]; then kill -USR2 $(cat /var/run/php-fpm/php-fpm.pid) fi endscript }
关键参数说明:daily 表示每天轮转一次,rotate 7 保留最近 7 个轮转文件,compress 压缩旧日志节省空间,postrotate 脚本在轮转后重启 PHP-FPM 以重新打开日志文件。
根据 2026 年 2 月 2 日的高效清理技巧,对于高流量站点建议使用size 100M替代 daily,按大小轮转更精准。必须添加copytruncate参数,它先拷贝日志再清空原文件,不中断 PHP 写入。
第四步:验证配置
手动测试配置是否正确。根据 2025 年 10 月 22 日的 Ubuntu 指南,运行以下命令验证:sudo logrotate -d /etc/logrotate.d/php(干运行测试),sudo logrotate -f /etc/logrotate.d/php(强制立即执行)。若无报错则表示成功。
注意事项
根据 2026 年 4 月 16 日的 PHP 开发错误日志详解,用户踩过的真实坑包括:
1. 日志文件属主不匹配:如果 PHP-FPM 以 www-data 运行,但 logrotate 配置中 create 0644 root root,会导致轮转后新文件无法写入,旧文件越积越大。
2. copytruncate 的副作用:注意它不移动原文件,只是清空内容,适合无法中断写入的场景;但频繁清空可能掩盖突发错误,建议配合监控。
3. pm.max_children 设置过大:根据 2025 年 9 月 11 日的内存问题案例,某 2G 内存服务器 pm.max_children 值为 50,每一个进程占用 1%-2.5% 的内存,导致内存使用率高达 92%,可用内存只剩下 70M。建议根据服务器内存调整,如 1GB 内存可设为 10-15。
4. 日志级别过低:生产环境中无需记录 DEBUG 级别,可将 error_reporting 调整为E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED,仅记录错误和警告信息。
5. 清理旧日志的 find 命令:使用find /var/log/php-fpm/ -type f -name "*.log" -mtime +7 -exec rm {} \;删除 7 天前的日志,但 rotate 7 别设太大,否则清理脚本容易漏掉归档文件。
参考来源
来源:运维技术博客 - Linux 服务器磁盘 100%?别急着删文件!先用这 3 个命令找出真凶 (2026 年 3 月 31 日)
来源:CentOS 技术文档 - centos php 日志满怎么办 (2025 年 10 月 5 日)
来源:Ubuntu 社区指南 - Ubuntu PHP 日志中资源占用过高怎么解决 (2025 年 10 月 22 日)
来源:PHP 开发者论坛 - php 清理 logs 后磁盘仍满咋办_php 磁盘满排查清理法 (2026 年 2 月 14 日)