Debian上Golang日志问题的排查与解决
一 快速定位与通用排查
二 常见症状与对应处理
| 症状 | 可能原因 | 解决要点 |
|---|---|---|
| 日志文件不在预期目录 | 路径配置错误、环境变量影响、并发写入冲突 | 使用绝对路径并在初始化校验;必要时用锁或单实例日志写入;避免依赖未定义的环境变量 |
| 权限被拒绝/无法创建文件 | 目录或文件权限不足 | 启动前用 os.MkdirAll(path, 0755) 创建目录;确保运行用户对日志目录有写权限 |
| 日志中出现乱码 | 系统/终端编码非 UTF-8、程序未正确处理UTF-8 | 设置 LANG/LC_ALL=en_US.UTF-8 或 zh_CN.UTF-8;必要时安装中文字体;在程序中用 unicode/utf8 校验 |
| 日志文件迅速膨胀 | 无轮转策略 | 使用 logrotate 定期轮转与压缩,控制保留天数与文件大小 |
| 高并发下性能瓶颈 | 标准库同步写、频繁系统调用 | 采用高性能库(如 zap)、异步或批量写入、减少频繁字符串拼接 |
| 看不到 DEBUG 信息 | 级别设置过高或未使用带级别日志 | 使用 logrus/zap 设置 DebugLevel;或在标准库中用前缀/封装模拟级别 |
| 服务启动失败但无应用日志 | 标准输出未被 systemd 捕获 | 在 systemd unit 中配置 StandardOutput=journal+console 或写入文件并由 journald 转发 |
三 标准库与第三方库配置示例
package main
import (
"log"
"os"
)
func main() {
f, err := os.OpenFile("/var/log/myapp/app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
log.Fatalf("无法打开日志文件: %v", err)
}
defer f.Close()
log.SetOutput(f)
log.SetPrefix("[APP] ")
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
log.Println("应用启动")
}
package main
import (
"github.com/sirupsen/logrus"
)
func main() {
logrus.SetFormatter(&logrus.TextFormatter{FullTimestamp: true})
logrus.SetLevel(logrus.DebugLevel)
logrus.Info("这是一条信息日志")
logrus.WithFields(logrus.Fields{"key": "value"}).Warn("这是一条带字段的警告")
}
package main
import (
"go.uber.org/zap"
)
func main() {
cfg := zap.Config{
Encoding: "json",
Level: zap.NewAtomicLevelAt(zap.InfoLevel),
OutputPaths: []string{"stdout", "/var/log/myapp/app.json"},
ErrorOutputPaths: []string{"stderr"},
}
logger, _ := cfg.Build()
defer logger.Sync()
logger.Info("zap 日志示例", zap.String("module", "main"))
}
以上示例展示了在 Debian 上使用标准库与 logrus、zap 的基本配置方式,可按需选择。
四 生产环境推荐做法
/var/log/myapp/*.log {
daily
missingok
rotate 7
compress
notifempty
create 640 root adm
copytruncate
}