温馨提示×

golang linux日志为何丢失

小樊
44
2026-10-05 11:48:15
栏目: 编程语言

在 Linux 上用 Go 写程序时,“日志丢失”是一个比较常见但不一定单纯是 Go 的问题。下面按最常见原因 → 排查思路 → 解决建议来说明。


一、最常见原因

1. 日志没真正“落盘”(缓冲问题)

Go 的 log / fmt.Fprintf / 自己写的 buffer 都可能有缓冲:

  • 标准输出有缓冲(尤其 pipe / 重定向时)
    • 直接终端:通常行缓冲
    • 重定向到文件或 | tee:全缓冲
  • 程序崩溃 / os.Exit / kill -9 → 缓冲未 flush → 日志丢失

✅ 表现:

  • 程序正常退出有日志
  • 异常退出 / 被杀没日志

✅ 解决:

  • 使用 log.SetOutput 到 带 flush 的 Writer
  • 自己写 logger 时,每次写都 Flush()
  • 或用 bufio.Writer 并显式 Flush
  • 推荐:直接用 zap / logrus(默认更安全)

2. 日志被 systemd / nohup 吞了

在 Linux 上常见场景:

  • systemd 服务
  • nohup xxx > log 2>&1 &
  • supervisor / docker

问题:

  • stdout/stderr 没配置
  • journald 限制
  • 日志写到了你“以为的地方”

✅ 排查:

journalctl -u your-service

✅ 建议:

  • 明确写日志文件(不要只依赖 stdout)
  • systemd 中:
StandardOutput=file:/var/log/app.log
StandardError=file:/var/log/app.log

3. 日志文件被“轮转”但程序还写旧 fd

典型:

  • logrotate 把文件重命名
  • 程序仍写原来的 fd
  • 你看新文件:空的

✅ 表现:

  • 磁盘空间还在涨
  • ls 看到文件,但 cat 没内容

✅ 解决:

  • 使用 支持 SIGHUP 重新打开日志 的 logger
  • 或 logrotate 加:
copytruncate
  • 或 Go 里监听信号重新 open 文件

4. 并发写日志没加锁

Go 多 goroutine 同时写:

  • 文件偏移错乱
  • 日志覆盖 / 丢失 / 损坏

✅ 解决:

  • 用 sync.Mutex
  • 或用 zap(原子写)
  • 不要多个 goroutine 直接 fmt.Fprintf(file)

5. 权限问题(最容易忽略)

  • 日志目录不存在
  • 没写权限
  • 以不同用户运行(systemd vs 手动)

✅ 表现:

  • 没报错(被吞)
  • 或只丢部分日志

✅ 排查:

ls -l /var/log/your.log
id

6. Go panic / runtime 错误导致提前退出

  • panic 没 recover
  • defer 中日志没 flush

✅ 建议:

  • defer logger.Sync()(zap)
  • 全局 recover

二、快速自查清单 ✅

  • [ ] 程序是否异常退出?
  • [ ] 是否用了缓冲 Writer?
  • [ ] 日志是否真写到文件?
  • [ ] 是否被 logrotate 影响?
  • [ ] 是否多 goroutine 写?
  • [ ] 是否 systemd / nohup 环境?

三、推荐做法(省心)

import "go.uber.org/zap"

logger, _ := zap.NewProduction()
defer logger.Sync()

logger.Info("start")

✅ 自动:

  • 无缓冲
  • 并发安全
  • 可配合 logrotate

如果你愿意,可以贴:

  • 日志写法代码
  • 运行方式(systemd / nohup / docker)
  • 丢失的具体场景

我可以直接帮你定位是哪一类问题。

0 踩