Golang中找不到Libc.so.6的解决方法

Golang中找不到Libc.so.6的解决方法 当我在一台机器上运行使用 Go 1.15.5 编译的可执行文件时,会出现以下错误,但使用 1.14.12 版本编译时则运行正常。这让我感到困惑,我原本以为 Go 的可执行文件是静态链接的,没有任何依赖?

./softtube.download: /lib/x86_64-linux-gnu/libc.so.6: 找不到版本 `GLIBC_2.32’ (被 ./softtube.download 需要)

我编译时使用的机器运行的是 Manjaro Cinnamon,而出问题的电脑运行的是 Linux Mint 20。

我在这里有什么地方理解错了吗?难道 Go 的可执行文件不是“独立”的吗?


更多关于Golang中找不到Libc.so.6的解决方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

显然我不太擅长阅读自己的代码 😊

谢谢!

更多关于Golang中找不到Libc.so.6的解决方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


根据我在softtube.download中看到的情况,您引用了internal/softtube.core,而它又引用了github.com/go-sql-driver/mysql,后者使用了net包。

我认为Go语言中有一些功能使用了libc,例如net和os/user包(我想这也是为什么在使用net包时竞态检测器无法工作的原因之一)。如果你没有使用这些包,那么你的程序可以进行静态编译,或者可能有一些编译时选项来使用这些包的纯Go版本。我还在阅读一些相关的错误报告,比如这个

据我所见,在这个特定的可执行文件中,我并没有使用 netos/user 包。

skillian: 如果你没有使用这些包,那么你的程序可以被静态编译

当你说“可以被静态编译”时,这是否意味着我需要在 go build 命令中添加某个参数才能使其静态编译?

skillian: 或者可能有一些编译时选项来使用这些包的纯Go版本。

纯Go?

我必须承认,我对静态链接和动态链接的了解并不深入。但据我所知,net 包使用 cgo 来处理一些对操作系统的调用(例如,我相信将主机名解析为 IP 地址的查找就是通过 libc 完成的)。

编辑:另外,关于选项,我认为你可以在执行 go build 命令之前设置 CGO_ENABLED=0 来禁用 cgo。我认为 cgo 是唯一一处你可能会遇到动态链接的地方,并且需要你明确选择退出。

CGO_ENABLED=0

Go 1.15版本开始,当使用net包且系统支持cgo时,Go会在某些情况下动态链接glibc。这是因为Go 1.15将DNS解析默认切换到了glibc的getaddrinfo函数,以获得更好的本地DNS配置兼容性。

解决方法:

  1. 静态编译(推荐)
CGO_ENABLED=0 go build -o softtube.download

这会完全静态链接,不依赖glibc。

  1. 使用纯Go的DNS解析器
go build -tags netgo -o softtube.download

这会强制使用Go实现的DNS解析器。

  1. 降级glibc依赖(编译时):
go build -ldflags="-extldflags=-Wl,--wrap=getaddrinfo" -o softtube.download

示例验证

# 查看二进制文件的动态库依赖
ldd softtube.download

# 查看glibc版本要求
objdump -p softtube.download | grep GLIBC

根本原因:你的Manjaro系统有较新的glibc(2.32+),而Linux Mint 20的glibc版本较旧。Go 1.15+在动态链接时会绑定编译时的glibc版本符号。

生产环境建议

# Docker多阶段构建示例
FROM golang:1.15-alpine AS builder
RUN apk add --no-cache gcc musl-dev
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o app .

FROM scratch
COPY --from=builder /app/app /app
ENTRYPOINT ["/app"]

这样编译的程序可以在任何Linux发行版上运行,无需考虑glibc版本差异。

回到顶部