lumberjack是目前最可靠、最轻量的日志滚动方案,因标准库log和slog不支持自动滚动,硬套逻辑易丢日志或崩溃;其按大小滚动需配齐MaxSize(MB)、MaxBackups(非零)、MaxAge(time.Duration)及LocalTime:true四项,缺一则失效。

lumberjack 是目前最可靠、最轻量的日志滚动方案,标准库 log 和 slog 本身不支持自动滚动,硬套逻辑容易丢日志或崩溃。
为什么直接用 log.SetOutput(os.File) 不会滚动
因为 log 只管写,不管文件大小、时间、清理——它把所有内容无条件追加到同一个 os.File 句柄里。一旦你没手动切换文件,日志就永远堆在单个文件中,磁盘迟早撑爆。
常见错误现象:app.log 持续增长到几个 GB,MaxSize 配了但完全不触发;或者日志突然消失,查不到任何报错。
-
log.SetOutput接收的是io.Writer,不是“智能写入器”,它不会主动检查文件尺寸或时间 - 若你传入一个自定义
io.Writer但没加锁,多 goroutine 并发写时会 panic 或句柄错乱 - 相对路径(如
"logs/app.log")在 daemon 化后常指向/或$HOME,导致权限拒绝或静默失败
lumberjack 按大小滚动必须配齐的三项
lumberjack.Logger 默认只做“大小轮转”,但缺一不可:否则轮转不生效、旧文件不删、或压缩失败。
立即学习“go语言免费学习笔记(深入)”;
-
MaxSize单位是 MB(不是字节),设10就是 10MB;误写成10240(以为是 KB)会导致轮转永远不触发 -
MaxBackups必须设具体值(如7),设0表示“不留备份”,设空或负数则行为未定义 -
MaxAge单位是time.Duration,常用28 * 24 * time.Hour;它和MaxBackups是“或”关系——满足任一即清理 -
LocalTime: true必须显式开启,否则归档文件名和修改时间全是 UTC,排查时对不上本地时间
示例配置:
lj := &lumberjack.Logger{
Filename: "/var/log/myapp/app.log",
MaxSize: 10,
MaxBackups: 7,
MaxAge: 28 * 24 * time.Hour,
LocalTime: true,
Compress: true,
}按小时/天滚动不能只靠 lumberjack
lumberjack 原生不支持时间维度命名(如 app-2026-06-14-10.log),它的 MaxAge 是按“最后修改时间”清理,不是按写入时间切分。
想实现纯时间滚动(比如每小时一个文件),必须绕过 Filename 字段静态设定,自己封装 io.Writer:
- 每次
Write()前用time.Now().Format("2006-01-02-15")生成小时标识(注意 Go 时间格式固定为"2006-01-02-15",不是"Y-m-d-H") - 用
sync.Mutex保护文件句柄切换,否则并发写时Close()和OpenFile()会冲突 - 别用
time.Ticker定时切换——如果某小时没日志,文件句柄仍被占用,且 tick 瞬间正在写入可能 panic -
os.OpenFile必须带os.O_CREATE | os.O_WRONLY | os.O_APPEND,漏掉os.O_APPEND会导致每次重写清空文件
zap/slog 接入 lumberjack 的三个硬性条件
lumberjack.Logger 是 io.WriteCloser,但 zap 和 slog 对底层 IO 行为更敏感,配错就丢日志。
- 必须用
zapcore.AddSync()包裹*lumberjack.Logger,否则logger.Sync()调用无效,进程崩溃前最后一段日志必丢 -
Filename必须是绝对路径;若用相对路径,在 systemd service 或 docker 中极易指向错误目录 - 目录必须提前创建且权限正确:
os.MkdirAll(filepath.Dir("/var/log/myapp"), 0755)要在zap.NewCore()之前执行,否则lumberjack打开失败却静默忽略 -
Compress: true只影响归档文件(如app.log.1.gz),不影响当前活跃日志文件;未压缩的旧文件仍占磁盘空间
真正容易被忽略的是:lumberjack 的轮转判断发生在 Write() 入口,不是后台定时任务——这意味着没有日志写入,就不会触发任何切换。低频服务若依赖“每天一个文件”,得自己补一个每日零点调用 lj.Rotate() 的 goroutine。


















