Gin应用需先编译为二进制文件(如./server),再用PM2管理;直接pm2 start main.go会失败,因PM2不识别Go源码。关键参数包括--name、--env、--restart-delay、--cwd;日志需保持输出到stdout/stderr以供PM2捕获;上线前须确认端口权限、无CGO依赖及OS架构一致。

Gin 本身不提供进程守护能力,必须靠外部工具。PM2 是最常用的选择,但它和 Gin 的配合不是“开箱即用”,关键在于启动方式、环境隔离和日志处理这三处。
为什么不能直接用 pm2 start main.go
PM2 默认不识别 Go 文件,它会尝试用 Node.js 去执行 main.go,报错 Error: Cannot find module 'main.go'。Gin 是 Go 写的 Web 框架,编译后是二进制可执行文件,PM2 只能管理已编译的程序,不能管理源码。
- 必须先用
go build -o server编译出可执行文件 - PM2 启动的是
./server,不是main.go - 如果项目依赖
.env或配置文件,需确保 PM2 启动时工作目录正确(用--cwd指定)
pm2 start 的关键参数怎么配
直接 pm2 start ./server 很容易失败——Gin 默认监听 :8080,但端口可能被占;没有环境变量,os.Getenv("PORT") 返回空;进程崩溃后不自动重启。这些都得靠参数补全:
-
--name "gin-api":给进程起名,方便后续pm2 restart gin-api -
--watch:慎用!Gin 编译后是静态二进制,改代码必须重编译,--watch对 Go 源码无效,只对 JS/TS 有效 -
--env production:配合.env.production使用,让os.Getenv读到正确值 -
--restart-delay 1000:避免频繁崩溃重启,留出诊断时间 -
--cwd ./dist:如果server和配置文件不在同一级,必须指定工作目录
日志和标准输出怎么收拢
Gin 默认把日志打到 stdout 和 stderr,但 PM2 的日志机制和 Go 的 log 包行为有差异:PM2 会捕获所有 stdout/stderr 并存为 ~/.pm2/logs/gin-api-out.log,但 Gin 的 gin.DefaultWriter 如果被重定向过(比如写到文件),PM2 就收不到。
- 不要在代码里调用
gin.DefaultWriter = os.Stdout—— 这是默认值,改了反而断掉 PM2 日志链路 - 想加自定义日志(如访问日志),用
gin.LoggerWithWriter并传入os.Stdout,PM2 才能捕获 - 错误堆栈务必用
log.Printf或fmt.Fprintln(os.Stderr, ...),别只写文件 - 查日志用
pm2 logs gin-api,不是tail -f原始文件
上线前必须检查的三个硬性条件
很多人在本地跑通了,一上服务器就挂,往往卡在这三点:
- 服务器是否装了 Go?不需要。Gin 应用编译后是纯二进制,目标机只要 Linux/macOS/Windows,无需 Go 环境
- 端口权限:非 root 用户不能监听
:80或:443,要么改用:3000,要么用 Nginx 反代 - 动态链接库缺失:如果用了
cgo(比如连接 PostgreSQL),编译时要加CGO_ENABLED=0,否则部署机缺libc会报cannot execute binary file
真正麻烦的从来不是启动命令,而是环境一致性——编译机和部署机的 OS 架构、cgo 开关、依赖库版本,差一点就静默失败。











