yii日志默认不按日期切分,因filetarget仅支持大小轮转;需禁用enablerotation并配合logrotate使用copytruncate、dateext和missingok实现按日归档。

Yii 日志文件不自动按日期切分,是因为默认用的是 FileTarget
Yii 自带的 FileTarget 默认只做大小轮转(maxFileSize + maxLogFiles),不支持按天生成新文件。你看到的日志一直追加到同一个 app.log 里,不是 bug,是设计如此。
想按日期切分,有两个路子:一是换日志 target(比如用社区扩展),二是把切分逻辑交给系统工具——logrotate 是最稳、最省心的选择,尤其在线上环境。
-
logrotate不依赖 PHP 进程,不抢锁、不卡写入,适合高并发场景 - Yii 日志保持“单文件持续写入”模式,对
FileTarget配置几乎不用动 - 注意:必须关掉
FileTarget::enableRotation(设为false),否则 PHP 和logrotate可能同时操作文件,导致丢日志
logrotate 配置里最关键的三行:copytruncate、dateext、missingok
直接贴出生产可用的最小配置片段(存为 /etc/logrotate.d/yii-app):
/var/www/myapp/runtime/logs/*.log {
daily
missingok
rotate 30
compress
delaycompress
copytruncate
dateext
dateformat -%Y-%m-%d
}
重点解释这三行为什么不能少:
-
copytruncate:先拷贝再清空原文件,保证 Yii 进程始终往同一个 fd 写,不中断日志;没它,PHP 可能继续往已被 mv 走的 inode 写,新日志就丢了 -
dateext+dateformat -%Y-%m-%d:让归档文件名带日期,比如app.log-2024-06-15;不加dateformat默认用YYYYMMDD格式,可读性差 -
missingok:避免某天没日志时 logrotate 报错退出;Yii 某些环境(如 dev)可能一天都没触发日志,这个开关很实用
Yii 的 FileTarget 配置要配合关掉自动轮转
在 config/main.php 或日志配置处,确认这几项:
-
enableRotation必须设为false(默认是true) -
maxFileSize和maxLogFiles可以删掉或设为 0,它们已失效 - 确保
file路径是绝对路径,且logrotate配置里的 glob 能匹配到,比如runtime/logs/app.log
示例片段:
'file' => '@runtime/logs/app.log',
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
'enableRotation' => false, // ← 关键
],
],
验证和排障:logrotate 不生效的三个常见原因
配完跑不起来?先查这几个点:
- 执行
logrotate -d /etc/logrotate.d/yii-app(-d是 debug 模式),看输出里是否识别到你的日志文件、是否判断“今天该轮转” - 检查日志文件权限:
logrotate默认用 root 运行,但目标文件若属 www-data 且无 group 写权限,copytruncate后可能清空失败(表现为文件大小不变) - 确认 cron 是否真在跑:
systemctl status cron,并检查/var/lib/logrotate/status里最后处理时间
一个容易被忽略的细节:logrotate 默认每天凌晨触发,但首次配置后不会立即运行,得等 cron 下次调度,或者手动跑一次 logrotate -f /etc/logrotate.d/yii-app 测试。










