logrotate未启用dateext导致旧日志被覆盖是最常见原因;此外还有轮转后权限错误、删除后进程仍写入、审计日志未实际生成等问题。

logrotate 没启用 dateext,旧日志被覆盖
这是最常见原因:轮转时没加 dateext,导致每天生成的归档文件名都是 access.log.1、error.log.1,新轮转直接覆盖旧文件,历史数据“消失”而非“归档”。
实操建议:
- 检查
/etc/logrotate.d/php-fpm或/etc/logrotate.d/apache2是否包含dateext和dateformat -%Y%m%d - 确认配置中是否同时设置了
extension .log(例如dateext extension .log),否则.1后缀仍会干扰日期格式 - 测试配置是否生效:
logrotate -d /etc/logrotate.conf | grep -A5 "your-log-path",看 debug 输出里是否识别到 dateext 行为
轮转后文件权限错误,新日志写不进去
logrotate 创建新日志文件时用了错误属主或权限,比如 create 0644 root root,但 PHP-FPM 是以 www-data 身份运行,结果新文件无法写入,进程继续往旧文件(已被 rename)写——而你看到的“旧日志”其实是被 rename 后仍在写入的残留句柄,真实归档文件却是空的或权限拒绝。
实操建议:
- 用
ls -l /var/log/php-fpm/查看轮转后新文件的 owner/group 是否匹配 PHP 进程用户(如www-data:www-data) - 确保 logrotate 配置中
create行明确指定用户和组:create 0644 www-data www-data - 若使用
copytruncate,注意它不移动原文件,只是清空内容,旧数据实际已丢失,不适合审计场景
日志被删除但进程还在写,df 满却找不到大文件
你以为日志“丢了”,其实是 rm 删除后,PHP-FPM 或 nginx 还在往该 inode 写入——文件已删但句柄未关,du 看不到,df 却算占用。这种情况下,轮转生成的新文件是空的,而真正含数据的“旧日志”藏在 lsof +L1 的 DEL 条目里。
实操建议:
- 运行
lsof +L1 | grep php-fpm,找标记为DEL的行,记录 PID 和文件路径 - 用
lsof -p <pid></pid>确认该进程是否仍在向已删文件写入 - 稳妥做法是重启服务:
systemctl restart php-fpm;若不能重启,尝试kill -USR1 <pid></pid>(仅当 PHP-FPM 配置了catch_workers_output = yes且支持平滑重开日志)
audit 日志本身没配,误把 error_log 当审计日志用
PHP 的 error_log 默认只记错误、警告、通知,不记录请求行为、参数、登录动作等审计所需字段。很多团队把 access.log 或自定义 audit.log 交给 logrotate,但忘了它们根本没开启或没写入关键事件。
实操建议:
- 确认审计日志路径是否独立于
error_log,比如 Laravel 的storage/logs/laravel.log或自定义的/var/log/app/audit.log - 检查应用代码中是否真有写审计日志的动作(如登录成功后调用
Log::channel('audit')->info(...)) - 若用 Monolog,确认 handler 配置了
RotatingFileHandler并设对$maxFiles,而不是依赖系统 logrotate
tail -f 看几秒,就知道问题出在哪一层。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











