
Go 默认日志输出到标准错误(stderr),而 daemonize 会关闭所有标准流;需显式调用 log.SetOutput() 指向文件,或改用更现代的进程管理方式(如 systemd)。
go 默认日志输出到标准错误(stderr),而 `daemonize` 会关闭所有标准流;需显式调用 `log.setoutput()` 指向文件,或改用更现代的进程管理方式(如 systemd)。
在 Go 中开发 Web 服务(如 tracking_api)后,常需将其作为后台守护进程长期运行。但直接使用 daemonize 工具配合简单重定向(如 1>> log)往往无法捕获日志——这是因为 Go 的 log 包默认写入 os.Stderr,而非 stdout;而 daemonize 在启动子进程时会主动关闭 stdin、stdout 和 stderr,导致日志“静默丢失”。
✅ 正确做法一:在代码中显式设置日志输出文件
推荐在 main() 函数起始处初始化日志文件句柄,并通过 log.SetOutput() 重定向:
package main
import (
"log"
"os"
)
func main() {
// 打开日志文件(追加模式)
f, err := os.OpenFile("/var/www/repo/bin/tracking_api.log",
os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatalf("无法打开日志文件: %v", err)
}
defer f.Close()
// 将 log 包全局输出重定向到文件
log.SetOutput(f)
// 后续所有 log.Print/log.Printf/log.Fatal 都将写入该文件
log.Println("服务已启动,监听中...")
// ... 启动 HTTP server 等逻辑
}
⚠️ 注意:务必在
log调用前完成SetOutput,且避免在defer f.Close()后继续写日志(否则可能丢失末尾内容)。生产环境建议使用支持轮转的库(如golang.org/x/exp/slog或github.com/sirupsen/logrus)。
✅ 正确做法二:改用 systemd(更可靠、更标准)
Linux 生产环境强烈推荐弃用 daemonize,改用 systemd 管理 Go 进程——它原生支持日志采集、自动重启、资源限制等:
- 创建服务文件
/etc/systemd/system/tracking-api.service:[Unit] Description=Tracking API Service After=network.target
[Service] Type=simple User=www-data WorkingDirectory=/var/www/repo/bin ExecStart=/var/www/repo/bin/tracking_api Restart=always RestartSec=10 StandardOutput=journal StandardError=journal SyslogIdentifier=tracking-api
[Install] WantedBy=multi-user.target
2. 启用并启动服务: ```bash sudo systemctl daemon-reload sudo systemctl enable tracking-api.service sudo systemctl start tracking-api.service
- 查看实时日志:
sudo journalctl -u tracking-api.service -f
✅ 优势:无需修改 Go 代码、日志自动归档、支持依赖管理、权限隔离清晰、便于监控集成。
❌ 不推荐的临时方案(仅调试用)
若坚持使用 daemonize,必须确保日志不依赖标准流:
# 错误:只重定向 stdout,stderr 仍被 daemonize 关闭 daemonize /var/www/repo/bin/tracking_api 1>> log.log # 无效:daemonize 会强制关闭所有 std*,重定向失效 daemonize /var/www/repo/bin/tracking_api 2>&1 >> log.log
因此,代码内重定向是唯一兼容 daemonize 的可靠方式,但不推荐用于新项目。
总结
- Go 日志默认输出到
stderr,daemonize会关闭它 → 必须在代码中用log.SetOutput()指向文件; - 更佳实践是采用
systemd管理进程,兼顾健壮性、可观测性与运维规范性; - 避免在日志文件路径中硬编码,可通过命令行参数或环境变量注入(如
LOG_PATH=$HOME/tracking_api.log)提升可移植性。










