温馨提示×

Golang日志切割如何做

小樊
46
2026-08-23 17:36:21
栏目: 编程语言

在 Go 里做日志切割(log rotation),常见做法有三种,从“最推荐”到“最原始”依次说明,并给出可直接用的示例。


✅ 一、最推荐:使用 lumberjack(生产级)

这是 Go 里最主流、最成熟的日志切割方案,被 logruszap 等广泛使用。

1️⃣ 安装

go get gopkg.in/natefinch/lumberjack.v2

2️⃣ 示例(标准库 log)

package main

import (
	"log"
	"gopkg.in/natefinch/lumberjack.v2"
)

func main() {
	log.SetOutput(&lumberjack.Logger{
		Filename:   "logs/app.log",
		MaxSize:    10,   // MB
		MaxBackups: 7,    // 保留旧文件数
		MaxAge:     30,   // 天
		Compress:   true, // 是否压缩
	})

	log.Println("hello lumberjack")
}

✅ 特点:

  • 文件大小 切割
  • 自动清理旧日志
  • 支持压缩
  • 无需重启服务

✅ 二、配合 zap / logrus(常见组合)

zap + lumberjack

import (
	"go.uber.org/zap"
	"gopkg.in/natefinch/lumberjack.v2"
)

func main() {
	w := &lumberjack.Logger{
		Filename:   "logs/app.log",
		MaxSize:    20,
		MaxBackups: 5,
		MaxAge:     30,
	}

	logger := zap.New(
		zap.NewJSONEncoder(),
		zap.AddStacktrace(zap.ErrorLevel),
		zap.WriteTo(w),
	)

	logger.Info("hello zap")
}

logrus + lumberjack

import (
	"github.com/sirupsen/logrus"
	"gopkg.in/natefinch/lumberjack.v2"
)

func main() {
	log := logrus.New()
	log.SetOutput(&lumberjack.Logger{
		Filename: "logs/app.log",
	})
	log.Info("hello logrus")
}

✅ 三、系统级方式(不推荐但常见)

Linux logrotate(运维方案)

不修改 Go 代码

/var/log/myapp/*.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
    copytruncate
}

⚠️ 缺点:

  • 需要系统支持
  • copytruncate 可能导致少量日志丢失
  • 不适合容器化场景

✅ 四、不推荐:自己写切割逻辑

除非你是为了学习,否则不建议,因为:

  • 要处理文件锁
  • 要处理信号
  • 要处理并发写日志

✅ 五、如何选择?

场景 推荐方案
Go 服务 ✅ lumberjack
使用 zap / logrus ✅ lumberjack
Docker / K8s ✅ 输出到 stdout + 宿主机日志
传统 Linux 服务 logrotate

✅ 六、最佳实践(总结)

只用一个日志文件句柄
按大小切割,而不是时间
不要自己 rename 日志文件
容器里优先打到 stdout


如果你愿意,我可以:

  • 给你一个 完整项目模板
  • 帮你设计 日志级别 + 切割策略
  • 或讲 K8s 下日志如何处理

你现在是哪种使用场景?

0