温馨提示×

linux golang日志为何丢失

小樊
48
2026-09-05 15:17:17
栏目: 编程语言

在 Linux 上用 Go 写程序时,“日志丢失”通常不是 Go 本身的问题,而是输出方式、进程管理、缓冲、文件轮转或权限等环境相关原因。下面按最常见原因逐一说明,并给出排查和解决办法。


一、标准输出 / 标准错误被“吞掉”(最常见)

1. 日志写到了 stdout / stderr,但没被收集

很多 Go 程序直接用:

log.Println("xxx")
fmt.Println("xxx")

这写的是 stdout/stderr

如果你是用:

./app

然后关掉终端,或后台运行:

./app &

日志可能:

  • 被 shell 丢弃
  • 被 nohup / systemd 重定向到别处
  • 容器里没挂日志驱动

✅ 解决:

  • 明确重定向:
./app > app.log 2>&1
  • 或用日志库写文件
  • 或用 systemd / docker log driver

二、日志被缓冲,进程退出时没 flush

2. 使用了带缓冲的 Writer

例如:

w := bufio.NewWriter(f)
w.WriteString("log")
// 没调用 w.Flush()

或:

  • 自己封装了 bufio.Writer
  • log 库内部有 buffer 但未 flush

✅ 解决:

  • 使用 defer w.Flush()
  • 或用 log.SetOutput 直接写文件(无缓冲)

三、程序异常退出(panic / kill)

3. panic 或 SIGKILL 导致日志未写入

  • log.Fatal 会调用 os.Exit,不执行 defer
  • kill -9 直接杀进程

✅ 解决:

  • 捕获 panic:
defer func() {
    if r := recover(); r != nil {
        log.Println("panic:", r)
    }
}()
  • 不要依赖 defer 做关键日志
  • 关键日志立即写盘

四、日志文件被轮转 / 删除(logrotate)

4. 文件被 mv / rm,但程序还持有旧 fd

例如:

  • logrotate 把 app.log 改成 app.log.1
  • 你的程序仍写“旧文件”
  • tail 的是“新文件”

✅ 表现:

  • 磁盘空间还在占
  • ls 看不到文件
  • lsof | grep deleted 能看到

✅ 解决:

  • 用支持 SIGHUP 的日志库(如 logrotate + copytruncate)
  • 或用 zerolog / zap + lumberjack
&lumberjack.Logger{
    Filename:   "app.log",
    MaxSize:    100,
    MaxBackups: 3,
    Compress:   true,
}

五、权限问题导致写失败被忽略

5. 写日志失败但没检查 error

f, _ := os.OpenFile("/var/log/app.log", ...)
log.SetOutput(f)

如果:

  • 目录不存在
  • 没权限
  • 磁盘满

你可能完全不知道。

✅ 解决:

  • 检查 error
  • 用 root 或正确权限
  • 监控磁盘

六、systemd 场景下的“日志丢失”

6. 没用 journald 或 stdout 被截断

systemd 默认只保留一定量的 stdout。

✅ 解决:

  • 写文件
  • 或:
StandardOutput=journal
StandardError=journal
  • journalctl -u your-service

七、Docker / K8s 场景

7. 日志没打到 stdout

容器里:

  • 写文件 ≠ 日志
  • kubectl logs 只看 stdout/stderr

✅ 解决:

  • 容器里日志必须输出到 stdout/stderr
  • 或用 sidecar 收集

八、并发写日志未加锁

8. 多 goroutine 写同一文件混乱 / 丢内容

标准 log 是并发安全的,但:

  • 自己实现的 logger 不一定
  • 多个进程写同一文件必丢

✅ 解决:

  • log(默认安全)
  • 或 zap / zerolog
  • 不要多进程写同一文件

快速排查清单 ✅

  1. 日志写的是 stdout 还是文件?
  2. 是否被重定向 / 丢弃?
  3. 是否有缓冲未 flush?
  4. 是否被 logrotate 影响?
  5. 是否 panic / kill -9?
  6. 是否权限 / 磁盘问题?
  7. 是否多进程写同一文件?

如果你愿意,可以把:

  • 日志代码
  • 启动方式(systemd / docker / nohup)
  • 丢失的具体表现

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

0