go 语言交叉编译后无法运行

2022-02-21 12:04:55 +08:00
 heqichang

最近又重新做一个 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")
}
4726 次点击
所在节点    Go 编程语言
31 条回复
12101111
2022-02-21 12:20:37 +08:00
gdb 运行编译出来的程序, 看看是为什么不能运行
盲猜是因为 CentOS7 的内核太老了
CEBBCAT
2022-02-21 12:33:28 +08:00
可以把复现代码放在 GitHub 上一份吗? go build 可以通过指定文件,也可以指定 package 。我不知道它们之间究竟有没有区别,但我用的一直都是 package 的方式,例如:

go build -o bin/api src/api_gateway
CEBBCAT
2022-02-21 12:44:12 +08:00
各个组件的版本号贴一下,我 Google 到一个 issue ,那边好像判断下来是 CPU 太老了,编译的时候使用了新的指令集,造成不兼容

macOS 、Aliyun 、Google Cloud 的 go env 、uname -a 。如果方便的话,sysctl 也可以贴一下,比如 sysctl -a | grep 'machdep.cpu'
CEBBCAT
2022-02-21 12:44:29 +08:00
ch2
2022-02-21 12:45:00 +08:00
用这个试试:
CGO_ENABLED=0 go build -o test -a -ldflags '-extldflags "-static"' .
Mohanson
2022-02-21 13:19:02 +08:00
估计 CPU 版本问题. amd64 指令集有不同的版本, 最基础的是基线版本 baseline, 后面还有 v2, v3, v4... 理论上现在你能用到的所有 amd64 cpu 都支持基线版本的指令集, 但是不一定会支持更高版本的指令集(如果你的 CPU 太旧的话). 你在 mac 进行交叉编译, 只告诉了编译器目标操作系统和目标架构, 却没有告诉它目标架构的版本, 那么它很可能用了更高版本的指令.

https://github.com/golang/go/issues/50589
Moker
2022-02-21 13:57:42 +08:00
可以看下是不是依赖库有问题
elechi
2022-02-21 14:02:10 +08:00
goarch 改成 386 试试
learningman
2022-02-21 14:39:51 +08:00
ldd 在服务器上看下
liaohongxing
2022-02-21 14:59:25 +08:00
powershell: $Env:GOOS="linux"
powershell: go build

我的机子 win10 64bit , cpu ryzen 2600, 交叉编译很多年,一直没有问题。
heqichang
2022-02-21 15:05:56 +08:00
@12101111 线上的 ubuntu 14 ,我没管理员权限,找运维帮我运行的, 输出是 Segmentation fault (core dumped)
heqichang
2022-02-21 15:16:57 +08:00
@CEBBCAT 就是个 hello world 程序,以前知道有这个问题,所以这次 go 17.2 版本再试试,结果还是不能运行。阿里云上面的机器没有装 go 开发环境,就是单纯的 ubuntu 14 。 正式开发我们还是有单独的 linux 机器去做编译部署。感谢你提供的链接。
heqichang
2022-02-21 15:22:40 +08:00
@Mohanson 嗯,以前运行不成功我也猜测可能和 CPU 有关,不过太底层的知识我不了解。阿里的服务器应该不会老吧,我的 mac 电脑倒是 13 年款的 :doge
fovecifer
2022-02-21 15:24:24 +08:00
env GOPROXY=https://goproxy.cn GOOS=linux GOARCH=amd64 go build
BrettD
2022-02-21 15:26:45 +08:00
Ubuntu 14 太老了,glibc 版本都不知道多少年前的
heqichang
2022-02-21 15:28:30 +08:00
@liaohongxing 我放我虚拟机里的 linux 运行也没问题,就是放云服务器上运行不成功。我记得之前在 google vm 上的是 intel xeon cpu ,没体验过这种 u
12101111
2022-02-21 15:39:39 +08:00
@BrettD go 程序关了 cgo 是不会调 libc 的
BrettD
2022-02-21 16:18:31 +08:00
@12101111 那估计是内核版本太老,Go 的有些系统调用在旧内核无法正常工作
zhangsanfeng2012
2022-02-21 17:18:24 +08:00
通过什么协议把二进制文件传到服务器上的?有 FTP 吗
Reficul
2022-02-21 17:35:53 +08:00
2.6 老内核 Go 的系统调用不一样,你用老版本的 Go 试试看(比如 1.6 ),如果可以运行可能就是这个原因。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/835368

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX