ThinkPHP 6 不内置日志轮转机制,需通过配置 cli 日志通道并结合 logrotate 或手动脚本实现定时任务日志轮转,同时注意权限、路径及日志级别控制。

ThinkPHP 6 本身不提供内置的日志轮转(log rotation)机制,尤其在 CLI 环境下执行定时任务时,日志默认写入 runtime/log/ 目录,若不干预,会持续追加、文件不断膨胀,甚至撑爆磁盘。要实现定时任务日志的自动轮转,需结合框架日志通道配置 + Linux 系统级工具(如 logrotate)或手动脚本控制,而非依赖 TP 自动处理。
明确日志写入位置与通道
TP6 的命令行日志默认走 cli 通道(非 default),必须显式指定,否则可能静默丢弃:
// 在命令类的 execute() 中
Log::channel('cli')->info('Backup started at ' . date('Y-m-d H:i:s'));确保 config/log.php 中已定义 cli 通道,且 path 指向可写目录(如 runtime/log/cli/):
'cli' => [
'type' => 'file',
'path' => runtime_path() . 'log/cli/',
'level' => 'info',
],⚠️ 注意:runtime/log/cli/ 目录需存在且 Web/CLI 进程有写权限(如 www-data 或 root 用户)。
立即学习“PHP免费学习笔记(深入)”;
用 logrotate 实现系统级日志轮转
这是最稳定、生产环境推荐的方式。以每天切割、保留 7 天为例:
-
创建轮转配置文件
sudo nano /etc/logrotate.d/thinkphp-cron
-
写入以下内容(路径按实际调整):
/www/wwwroot/myapp/runtime/log/cli/*.log { daily missingok rotate 7 compress delaycompress notifempty create 644 www-data www-data sharedscripts postrotate # 可选:通知应用重载日志句柄(TP6 不需要) endscript } -
手动测试是否生效:
sudo logrotate -d /etc/logrotate.d/thinkphp-cron # 调试模式 sudo logrotate -f /etc/logrotate.d/thinkphp-cron # 强制执行一次
✅ 效果:cli/backup.log → cli/backup.log.1, cli/backup.log.2.gz … 最多保留 7 份。
在命令脚本中手动切割日志文件
若无法使用 logrotate(如共享主机),可在调用定时任务的 shell 脚本里加切割逻辑:
#!/bin/bash
APP_DIR="/www/wwwroot/myapp"
LOG_DIR="$APP_DIR/runtime/log/cli"
TODAY=$(date +\%Y\%m\%d)
cd "$APP_DIR"
# 切割昨日日志(避免干扰当日写入)
find "$LOG_DIR" -name "*.log" -mtime +0 -exec mv {} "{}.$TODAY" \; 2>/dev/null
# 执行命令(日志仍写入原名,新日志从今天开始)
/usr/local/bin/php think backup:data --force >> "$LOG_DIR/backup.log" 2>&1? 关键点:
-
mtime +0表示“修改时间超过 0 天”,即昨天及更早的日志; -
>> "$LOG_DIR/backup.log"保持主日志名不变,便于统一查看; - 避免在
execute()内做文件操作——CLI 环境下权限和路径易出错。
避免日志爆炸的实用建议
- 日志级别设为
info或notice,避免在定时任务中大量写debug; - 敏感信息(如密码、token)禁止打日志,哪怕
--force模式下也要过滤; - 每个定时任务用独立日志文件名,例如:
Log::channel('cli')->info('...', ['task' => 'backup']); // 对应日志文件可按 task 分类:backup_20260806.log - 若用
>>追加写入,务必确认磁盘空间监控已启用(如df -h告警); - 不要依赖
file_put_contents(..., FILE_APPEND)手动写日志——绕过 TP 日志系统,丢失格式与通道能力。
不复杂但容易忽略。



















