Go二进制需交叉编译匹配目标Linux架构(GOOS=linux GOARCH=amd64/arm64),禁用CGO,加-ldflags="-s -w",设执行权限,用systemd托管并监听0.0.0.0,开放防火墙及云安全组端口。

Go 二进制可直接运行,无需安装 Go 环境或依赖库——但必须确保目标 Linux 系统架构匹配、权限与启动方式合理,否则会报 cannot execute binary file: Exec format error 或静默退出。
编译时指定目标 Linux 平台和架构
本地开发机(如 macOS 或 Windows)不能直接用 go build 生成 Linux 可执行文件,除非显式交叉编译。漏掉这步是部署失败最常见原因。
- 先确认服务器 CPU 架构:
uname -m(常见为x86_64或aarch64) - 编译命令必须设两个环境变量:
GOOS=linux GOARCH=amd64 go build -o myapp ./main.go(amd64对应x86_64;ARM 服务器用arm64) - 若用 CGO(比如调用 C 库),需额外设
CGO_ENABLED=0,否则可能链接宿主机动态库,导致上线后报not found - 加
-ldflags="-s -w"可减小体积、去除调试信息(生产推荐)
部署后无法启动:检查权限、路径和动态链接
即使二进制能 copy 上去,也可能因权限不足、缺少共享库或工作目录错误而起不来。
- 给执行权限:
chmod +x ./myapp(Linux 默认不继承可执行位) - 运行前先查依赖:
ldd ./myapp—— 若输出含not found,说明用了 CGO 且没关,或系统缺基础库(如libc版本太低) - 避免相对路径陷阱:程序里用
os.Executable()或os.Getwd()获取路径时,要意识到 systemd 或 cron 启动时工作目录不一定是二进制所在目录 - 建议用绝对路径启动,并在代码中用
filepath.Dir(os.Args[0])定位配置文件位置
用 systemd 托管服务(推荐长期运行)
手动 ./myapp & 启动不可靠,进程随终端关闭、崩溃不自启、日志难收集。systemd 是 Linux 服务管理事实标准。
立即学习“go语言免费学习笔记(深入)”;
- 写 unit 文件(如
/etc/systemd/system/myapp.service):[Unit] Description=My Go App After=network.target [Service] Type=simple User=www-data WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/myapp Restart=always RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
- 注意
Type=simple(Go 程序通常前台阻塞运行);Restart=always防止 panic 崩溃后挂死 - 启用并启动:
sudo systemctl daemon-reload && sudo systemctl enable myapp && sudo systemctl start myapp - 查日志:
journalctl -u myapp -f(比重定向到文件更可控)
HTTP 服务端口被占用或无法外网访问
Go 默认监听 localhost:8080,这在服务器上等于只允许本机访问,外部连不上。
- 监听所有接口:
http.ListenAndServe(":8080", nil)中的":8080"已正确;但若写成"127.0.0.1:8080"就只能本地访问 - Linux 防火墙默认拦非 22/80/443 端口:
sudo ufw allow 8080(Ubuntu)或sudo firewall-cmd --add-port=8080/tcp --permanent(CentOS/RHEL) - 云服务器(如阿里云、AWS)还需在安全组里放行对应端口
- 若想监听 80/443,普通用户无权绑定,要么用
setcap 'cap_net_bind_service=+ep' ./myapp,要么用 nginx 反代
真正麻烦的不是编译或拷贝,而是二进制隐式依赖的运行时行为:当前工作目录、用户权限、信号处理、日志输出位置、以及 systemd 的 RestartSec 和 StartLimitIntervalSec 这类节流参数——它们决定了服务反复崩溃时你能不能及时收到告警。


















