Golang Go语言交叉编译后无法运行

发布于 1周前 作者 songsunli 来自 Go语言

Golang Go语言交叉编译后无法运行

最近又重新做一个 go 项目,但是我本地是 mac ,放阿里云 linux 还是没法运行,这是我很早以前在 sf 上的一个提问:go build 之后的文件放服务器上不能运行,cpu 不同导致?,当时通过 docker 打包在容器里去运行,但是没人解释出根本的原因。

编译命令:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o test main.go

编译的代码也很简单:

func main() {
	fmt.Println("hello world")
}

更多关于Golang Go语言交叉编译后无法运行的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

32 回复

gdb 运行编译出来的程序, 看看是为什么不能运行
盲猜是因为 CentOS7 的内核太老了

更多关于Golang Go语言交叉编译后无法运行的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


可以把复现代码放在 GitHub 上一份吗? go build 可以通过指定文件,也可以指定 package 。我不知道它们之间究竟有没有区别,但我用的一直都是 package 的方式,例如:

go build -o bin/api src/api_gateway

各个组件的版本号贴一下,我 Google 到一个 issue ,那边好像判断下来是 CPU 太老了,编译的时候使用了新的指令集,造成不兼容

macOS 、Aliyun 、Google Cloud 的 go env 、uname -a 。如果方便的话,sysctl 也可以贴一下,比如 sysctl -a | grep ‘machdep.cpu’

用这个试试:
CGO_ENABLED=0 go build -o test -a -ldflags ‘-extldflags “-static”’ .

估计 CPU 版本问题. amd64 指令集有不同的版本, 最基础的是基线版本 baseline, 后面还有 v2, v3, v4… 理论上现在你能用到的所有 amd64 cpu 都支持基线版本的指令集, 但是不一定会支持更高版本的指令集(如果你的 CPU 太旧的话). 你在 mac 进行交叉编译, 只告诉了编译器目标操作系统和目标架构, 却没有告诉它目标架构的版本, 那么它很可能用了更高版本的指令.

https://github.com/golang/go/issues/50589

可以看下是不是依赖库有问题

goarch 改成 386 试试

ldd 在服务器上看下

powershell: $Env:GOOS="linux"
powershell: go build

我的机子 win10 64bit , cpu ryzen 2600, 交叉编译很多年,一直没有问题。

线上的 ubuntu 14 ,我没管理员权限,找运维帮我运行的, 输出是 Segmentation fault (core dumped)

就是个 hello world 程序,以前知道有这个问题,所以这次 go 17.2 版本再试试,结果还是不能运行。阿里云上面的机器没有装 go 开发环境,就是单纯的 ubuntu 14 。 正式开发我们还是有单独的 linux 机器去做编译部署。感谢你提供的链接。

嗯,以前运行不成功我也猜测可能和 CPU 有关,不过太底层的知识我不了解。阿里的服务器应该不会老吧,我的 mac 电脑倒是 13 年款的 :doge

env GOPROXY=https://goproxy.cn GOOS=linux GOARCH=amd64 go build

Ubuntu 14 太老了,glibc 版本都不知道多少年前的

我放我虚拟机里的 linux 运行也没问题,就是放云服务器上运行不成功。我记得之前在 google vm 上的是 intel xeon cpu ,没体验过这种 u

go 程序关了 cgo 是不会调 libc 的

那估计是内核版本太老,Go 的有些系统调用在旧内核无法正常工作

通过什么协议把二进制文件传到服务器上的?有 FTP 吗

2.6 老内核 Go 的系统调用不一样,你用老版本的 Go 试试看(比如 1.6 ),如果可以运行可能就是这个原因。

我碰到过非常老的 linux 不能运行交叉编译的文件,印象是依赖库问题。
不过项目本身会有韵味那边在线上环境再次编译才会上线,运行没问题,所以没在研究。

试试老版本的 go
以前我在新系统里非交叉编译的拿到 centos5 上不能运行,查了一下因为 kernel API 变动而不兼容,于是降级 go 版本搞定

楼主,之前碰到过类似问题,参见

嗯,FTP 传的


感谢提供的链接

缺少静态编译参数

是不是用 ascii mode 传的,换成 binary mode 上传试试

我擦,结案了,可以运行了,还真是 FTP 的鬼,我用的 FileZilla ,设置里如果传的文件没有扩展自动转 ascii ,所以文件被损坏了。我怎么也没想到是它是它是它 :doge

你…… hash 都不对比一下的?

针对您提到的Golang交叉编译后无法运行的问题,以下是一些可能的解决思路:

  1. 检查环境变量:确保在交叉编译时正确设置了GOOS和GOARCH环境变量,以指定目标操作系统和架构。同时,确认CGO_ENABLED是否根据需求正确设置为0(禁用CGO)或1(启用CGO)。
  2. 验证代码结构:确保main函数位于main包中。在Golang中,main包的main函数是程序的唯一入口。如果main函数位于其他包中,编译后的二进制文件将无法运行。
  3. 检查依赖关系:如果程序中使用了CGO来调用C代码或其他外部库,请确保这些依赖在目标平台上也可用。对于带CGO的交叉编译,可能需要使用特定的交叉编译工具链。
  4. 考虑系统调用差异:不同操作系统间的系统调用可能存在差异。如果代码中直接调用了操作系统API,请确保这些调用在目标平台上也是有效的。
  5. 调试和错误信息:如果可能的话,尝试在目标平台上运行二进制文件,并查看是否有更详细的错误信息输出。这有助于确定问题的具体原因。

如果以上方法仍然无法解决问题,建议查阅更多的Golang交叉编译文档或在相关社区中寻求帮助。

回到顶部