温馨提示×

为何golang linux日志丢失

小樊
45
2026-10-17 05:06:19
栏目: 编程语言

在 Linux 上用 Go 写程序时“日志丢失”是一个常见但原因多样的问题。下面按最常见 → 较少见的顺序系统说明原因和解决办法。


一、最常见原因

1. 程序异常退出,缓冲未刷新

Go 的 log / fmt 默认是行缓冲或全缓冲:

  • 如果程序 os.Exit()、panic、被 kill -9
  • 缓冲区里的日志不会落盘

✅ 解决:

  • 使用带 Flush 的日志库(zap / logrus)
  • 退出前显式 flush
  • 避免 os.Exit,用 return + defer
defer logger.Sync() // zap

2. 标准输出被重定向但进程被关闭太快

例如:

./app > app.log &
  • 如果父进程退出、管道关闭
  • 子进程 stdout 丢失

✅ 解决:

  • 用 nohup ./app > app.log 2>&1 &
  • 或用 systemd / supervisor

3. systemd 吞日志

如果使用 systemd:

[Service]
StandardOutput=journal

日志在 journald 中,不在文件里

✅ 解决:

  • journalctl -u your-service
  • 或改:
StandardOutput=file:/var/log/app.log

4. 日志文件被轮转(logrotate)

  • 日志被 mv 走
  • 程序仍写旧 fd

✅ 解决:

  • 使用支持信号重开的日志库
  • 或 copytruncate

二、Go 特有原因

5. 多个 goroutine 写文件未加锁

  • 日志错乱、部分丢失

✅ 解决:

  • 使用 zap / logrus(内部已加锁)
  • 或自己 sync.Mutex

6. 日志级别配置错误

  • Info 被忽略
  • Debug 没开

✅ 检查:

logger.SetLevel(logrus.InfoLevel)

三、系统层面原因

7. 磁盘满 / 权限不足

  • 写入失败但被忽略

✅ 检查:

df -h
ls -l /var/log

8. 容器环境日志丢失

  • 容器退出 → stdout 消失
  • 没挂载 volume

✅ 解决:

  • 挂载日志目录
  • 或集中采集(ELK / Loki)

四、快速排查清单

# 是否真的写了
strace -e write -p <pid>

# 看 systemd 日志
journalctl -u your-app -f

# 看文件 fd
ls -l /proc/<pid>/fd

五、推荐做法(生产环境)

✅ 使用:

  • zap + lumberjack
  • systemd / k8s
  • 日志级别 + 文件 + 轮转
writer := zapcore.AddSync(&lumberjack.Logger{
    Filename:   "/var/log/app.log",
    MaxSize:    100,
    MaxBackups: 5,
    Compress:   true,
})

如果你能补充:

  • 用的什么日志库
  • 怎么运行的(直接跑 / systemd / docker)
  • 日志写到哪

我可以给你更精确的定位和代码级建议。

0 踩