Linux下Permission denied主因是可执行位缺失,Go二进制默认无x权限,需显式chmod +x;exec format error实为架构不匹配,须用GOOS/GOARCH交叉编译并验证file输出。

构建产物在目标机器上提示 Permission denied
不是代码问题,是 Linux 文件系统对可执行位的严格控制。Go 构建出的二进制默认没有 chmod +x,尤其当产物通过 cp、tar 或 CI/CD 传输时,原始权限常被剥离。
实操建议:
- 构建后立即检查:运行
ls -l ./myapp,确认输出中包含-rwxr-xr-x(而非-rw-r--r--) - CI/CD 中加一步:构建命令后追加
chmod +x ./myapp - 若用
tar打包,务必加-p参数保留权限:tar -c pzvf app.tar.gz ./myapp - Docker 场景下,COPY 后需显式
RUN chmod +x /app/myapp,不能依赖构建机权限
exec format error 源于 CPU 架构不匹配
这是最常被误判为“编译失败”的问题——实际编译成功了,但产物跑在了错误架构的机器上。比如在 x86_64 宿主机用默认 go build 生成的二进制,扔到 ARM64 的树莓派或 AWS Graviton 实例上就会报这个错。
实操建议:
- 确认目标平台架构:登录机器后运行
uname -m(常见值:x86_64、aarch64、armv7l) - 跨平台构建必须指定
GOOS和GOARCH,例如:GOOS=linux GOARCH=arm64 go build -o myapp-arm64 . - 避免混用
CGO_ENABLED=1和交叉编译:启用 cgo 后,go build会尝试调用目标平台的 C 工具链,大概率失败;纯 Go 程序建议关掉:CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build ... - 验证产物架构:本地用
file ./myapp-arm64查看输出是否含ARM aarch64或ELF 64-bit LSB executable, x86-64
Linux 内核版本太低导致 No such file or directory
这个错误看似路径不对,实则是动态链接器(/lib64/ld-linux-x86-64.so.2 等)缺失或版本过旧。Go 默认静态链接大部分依赖,但若启用了 cgo 或调用了某些系统库(如 net 包在某些发行版中会动态链接 libc),就可能依赖宿主机的 glibc 版本。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
实操建议:
- 优先使用
CGO_ENABLED=0构建,彻底规避 glibc 依赖(绝大多数 HTTP/gRPC/IO 场景完全可行) - 若必须启用 cgo(如需 DNS 解析策略或 SQLite),则构建环境应尽量贴近目标环境的最小内核+glibc 版本(例如 CentOS 7 → glibc 2.17)
- 检查目标机器 glibc 版本:
ldd --version,再对比构建机输出;不匹配时,要么降级构建机,要么用 musl(通过docker buildx+alpine基础镜像)
Windows 构建的 .exe 在 WSL 或 Linux 上直接运行失败
WSL1 不支持原生 Windows PE 格式,WSL2 虽然有改进,但默认仍无法直接执行 Windows 二进制。用户常把 myapp.exe 复制进 WSL 后敲 ./myapp.exe,结果报 cannot execute binary file: Exec format error——这不是权限问题,是格式根本不认识。
实操建议:
- 明确区分构建目标:
GOOS=windows GOARCH=amd64 go build只产出 Windows 可执行文件,不能在 Linux/WSL 下运行 - 在 WSL 中运行 Go 程序,应统一用
GOOS=linux构建(即使开发机是 Windows) - 若需从 Windows 主机向 WSL 传产物,确保传的是 Linux 构建版(无
.exe后缀),且已设可执行位
关键点容易被忽略:多平台构建不是“换个参数就能跑”,它牵扯权限继承、ABI 兼容性、链接模型三重约束。哪怕 file 显示架构正确,ldd ./binary 输出非空(尤其出现 not found)就说明仍有动态依赖未满足。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










