在 CentOS 上运行 Go 程序时日志缺失,通常不是 Go 语言本身的问题,而是运行环境、系统配置或日志方式导致的。下面按常见原因给你系统梳理一下。
| 现象 | 可能原因 |
|---|---|
| 程序在终端能输出,后台没日志 | 输出被重定向或丢弃 |
| systemd 启动没日志 | 没用 journald / stdout 未捕获 |
| 日志文件为空 | 路径不存在 / 权限不足 |
| 日志“偶尔丢” | 缓冲未刷新 |
| 容器里没日志 | 写文件而不是 stdout |
| 崩溃前没日志 | panic 前未 flush |
错误示例:
[Service]
ExecStart=/opt/app/app
如果你在代码里用:
log.Println("start")
fmt.Println("xxx")
✅ 正确做法:确保日志输出到 stdout/stderr
systemd 会自动收集到 journalctl
journalctl -u your-service -f
log.SetOutput(os.OpenFile("/var/log/app.log", ...))
CentOS 常见问题:
/var/log 只有 root 可写✅ 检查:
ls -l /var/log/app.log
ps -ef | grep app
✅ 解决:
[Service]
User=appuser
或:
chown appuser:appuser /var/log/app.log
Go 的 log 包不会自动 flush 到磁盘
✅ 推荐写法:
f, _ := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
defer f.Close()
log.SetOutput(f)
或 每次都 flush(重要):
logger := log.New(f, "", log.LstdFlags)
panic("xxx")
✅ 在 main 最外层加:
defer func() {
if r := recover(); r != nil {
log.Println("panic:", r)
}
}()
❌ 错误:
nohup ./app &
可能日志在:
nohup.out
✅ 明确重定向:
./app > /var/log/app.log 2>&1 &
SELinux 会静默拒绝写文件
检查:
getenforce
如果是 Enforcing:
ausearch -m avc -ts recent
✅ 临时关闭测试:
setenforce 0
✅ 永久解决(示例):
semanage fcontext -a -t var_log_t "/var/log/app.log"
restorecon -v /var/log/app.log
❌ 写文件:
log to /app/logs/app.log
✅ 正确方式:
log to stdout / stderr
kubectl logs pod-name
docker logs container
✅ 最佳实践
zap / logruslogger, _ := zap.NewProduction()
defer logger.Sync() // 关键
# 1. 看 systemd 日志
journalctl -u your-service -f
# 2. 看进程用户
ps -ef | grep app
# 3. 看日志文件权限
ls -l /var/log/app.log
# 4. 看 SELinux
getenforce
# 5. 看是否被重定向
cat /proc/<pid>/fd/1
如果你愿意,可以把下面信息发我,我可以直接帮你定位:
我可以直接告诉你到底是哪一步丢的。