直接用 systemd 管理 gin 服务是生产环境标准做法,支持自动拉起、启动顺序控制、资源限制与日志统一;需配置 type=simple、restart=always、environment 传参,并配合 nginx 反向代理及防火墙端口放行。

直接用 systemd 管理 Gin 服务,别用 nohup
nohup + & 是临时跑一下可以,但生产环境必须用 systemd。它能自动拉起崩溃进程、控制启动顺序、限制资源、统一日志路径,还能和 firewalld / nginx 协同工作。用 nohup 的后果是:进程挂了没人知道,日志散落在各处,重启服务器后服务不自动起来。
操作步骤:
- 确保你的 Gin 二进制已编译好(
GOOS=linux GOARCH=amd64 go build -o server main.go),且上传到服务器固定路径,比如/opt/myapp/server - 创建服务文件:
sudo vi /etc/systemd/system/myapp.service - 填入内容(注意替换
User、WorkingDirectory和ExecStart):
[Unit] Description=Gin Web Service After=network.target [Service] Type=simple User=www-data WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/server Restart=always RestartSec=5 Environment=GIN_MODE=release Environment=PORT=8080 [Install] WantedBy=multi-user.target
重点注意:Type=simple(Gin 默认是前台阻塞式运行,不是 fork 出子进程),Restart=always 要配,否则 panic 后就停了;Environment 用来传运行时变量,比硬编码更安全。
Gin 绑定端口前先确认防火墙放行
CentOS 7/8 默认开 firewalld,Gin 启动成功不代表能被访问——很可能端口被拦了。常见错误现象:curl localhost:8080 能通,但外网 curl your-ip:8080 超时,基本就是这个原因。
检查和放行方法:
- 查当前开放端口:
sudo firewall-cmd --list-ports - 临时加端口(测试用):
sudo firewall-cmd --add-port=8080/tcp - 永久生效(上线必做):
sudo firewall-cmd --permanent --add-port=8080/tcp - 重载规则:
sudo firewall-cmd --reload
别用 systemctl stop firewalld 关防火墙——这是偷懒,也是安全隐患。如果用的是阿里云/腾讯云,还要去控制台安全组里额外放行对应端口,firewalld 只管系统层。
生产环境别直接暴露 Gin,默认监听 127.0.0.1
Gin 的 router.Run(":8080") 默认绑定 0.0.0.0:8080,意味着所有网卡都可访问。但生产上应该让它只监听 127.0.0.1:8080,再由 nginx 做反向代理。原因有三:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- nginx 提供 gzip、静态文件缓存、限流、SSL 终止等 Gin 不该承担的功能
- 避免 Gin 直接面对公网攻击面(比如慢速 HTTP 攻击、恶意 header)
- 方便后续横向扩展多个 Gin 实例,nginx 做负载均衡
改法很简单,在代码里显式指定地址:
router.Run("127.0.0.1:8080") // 而不是 ":8080"
然后配 nginx(示例):
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
记得 sudo nginx -t && sudo systemctl reload nginx 生效。
日志别打屏,也别全扔给 systemd journal
systemd 默认把 stdout/stderr 推给 journal,查日志得用 journalctl -u myapp.service -f。问题在于:journal 日志默认只保留最近 1–2 周,且没按天轮转,线上出问题时容易覆盖关键记录。
更稳妥的做法是 Gin 主动写文件日志:
- 用
gin.DefaultWriter重定向到文件,例如:gin.DefaultWriter = io.MultiWriter(logFile, os.Stdout) - 配合
lumberjack库做切割(github.com/natefinch/lumberjack),设置MaxSize、MaxBackups - 确保
User在myapp.service里有写权限(比如/var/log/myapp/目录 chown www-data:www-data)
systemd journal 仍保留,作为兜底(比如启动阶段的 panic),但主力日志走文件——排查时翻 /var/log/myapp/access.log 和 error.log 更直观、可归档、易对接 ELK。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










