最直接方式是用 find 命令按修改时间清理:find /path/to/logs_php -name "*.log" -type f -mtime +7 -delete,其中-mtime +7 表示删除 8 天及更早的文件,建议先用 -print 测试再执行 -delete。

用 find 命令按天数清理 PHP 日志最直接
Linux 下 PHP 日志(比如 /var/log/php-fpm.log 或项目自定义的 logs_php/)通常不自带轮转逻辑,得靠外部命令控制保留窗口。最常用、最可靠的方式就是 find 配合 -mtime。
例如保留最近 7 天日志,删除更老的:
find /path/to/logs_php -name "*.log" -type f -mtime +7 -delete
注意:-mtime +7 表示「修改时间超过 7 天」,即第 8 天及更早的文件会被匹配;-delete 是 GNU find 扩展,若系统不支持(如 macOS),改用 -exec rm {} \;。
-
/path/to/logs_php必须是绝对路径,相对路径在 cron 中容易失效 - 先用
-print替代-delete测试匹配是否准确,避免误删 - 如果日志带日期后缀(如
app_20240520.log),-mtime仍以文件修改时间为准,不是文件名里的日期
PHP 自身写日志时控制文件名和滚动逻辑
如果用 error_log() 或 file_put_contents() 直接写日志,PHP 不会自动切分或清理。要“控量”,得在写入前做判断。
立即学习“PHP免费学习笔记(深入)”;
常见做法是按天生成文件名,并限制单个文件大小或保留天数:
$logFile = sprintf('logs_php/app_%s.log', date('Y-m-d'));
// 写入前检查:若文件存在且大于 10MB,可归档或跳过
if (file_exists($logFile) && filesize($logFile) > 10 * 1024 * 1024) {
rename($logFile, $logFile . '.' . time());
}但这种方式不解决“只留 N 天”的问题,需额外加清理逻辑(比如在脚本末尾调用 shell_exec("find ..."))。
- 不要在每次请求中执行
find清理,性能差且可能并发冲突 - 推荐把清理逻辑抽成独立 CLI 脚本(如
php clean_logs.php --keep-days=7),再由 cron 定时运行 - 用
glob()扫描日志文件时注意排序,array_filter()配合filemtime()可手动实现保留逻辑,但不如find稳定
用 logrotate 管理 PHP 日志最省心(适合生产环境)
如果 PHP 日志由系统服务(如 php-fpm、Apache、Nginx)产生,或你有 root 权限,logrotate 是标准方案,能精准控量、压缩、归档、甚至触发 postrotate 脚本。
配置示例(/etc/logrotate.d/php-custom):
/var/log/php-fpm/*.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
create 0644 www-data www-data
sharedscripts
postrotate
if [ -f /var/run/php/php-fpm.pid ]; then
kill -USR1 `cat /var/run/php/php-fpm.pid`
fi
endscript
}关键点:rotate 7 表示保留 7 个归档文件(不是 7 天),配合 daily 才等效于“保留最近 7 天”;postrotate 用于通知服务重新打开日志文件,避免写入中断。
- 务必测试配置:运行
logrotate -d /etc/logrotate.d/php-custom查看模拟行为 - 如果日志路径含通配符(如
*.log),确保目录下只有目标日志,否则可能误删其他文件 - 非 root 用户无法使用
logrotate,此时只能退回find+ cron 方案
注意日志时间戳来源和时区偏差
所有基于时间的清理逻辑(find -mtime、logrotate、PHP 的 filemtime())都依赖文件系统记录的 mtime。而 PHP 写日志时,mtime 通常等于最后写入时间 —— 但如果你用 touch() 修改过文件时间,或日志被 rsync 同步过,mtime 就不可信。
更麻烦的是时区:PHP 脚本里 date('Y-m-d') 用的是 date.timezone 设置,而 find -mtime 和 logrotate 用的是系统本地时间。若两者不一致(比如 PHP 设为 Asia/Shanghai,系统设为 UTC),会导致“以为保留了 7 天,实际只留了 6 天半”。
- 统一时区:建议系统和 PHP 都设为 UTC,避免歧义
- 验证方式:用
stat -c "%y %n" /path/to/logfile看实际 mtime,再对比date输出 - 若必须按文件名中的日期清理(如
app_20240520.log),就得用正则+DateTime解析,不能依赖 mtime











