cgo 遇到 kernel too old 解决小记

背景
事情是从前几天 loggie 的一次阿里云 ECS 部署开始的,之前有过部署华为云的 EulerOS 没有遇到任何问题,但阿里云 ECS 是 centos6 直接
原因是 loggie 依赖了 go-sqlite3 需要使用 cgo 编译,然后是编译时二进制静态打包的 c lib 需要更高的内核版本,所以我们可以尝试降级编译时使用的 gcc 版本,理论上可以降低运行时要求的 kernel version
尝试 gcc4.8
我们可以在 centos 上测试静态构建看看,一般 centos 6 和 7 都低于 4.8 需要额外安装。
现在你可以通过 gcc 4.8 编译出来一个二进制文件并且可以在 centos 6 上跑了,算是解决了我们当前所遇到的 kernel too old 的问题。
但你会发现,这种方式存在一些缺陷
- 构建过程中有一些 warning 存在,它并不会导致构建失败,而且构建出来的二进制也是能运行的,你需要根据实际情况检查 warning,因为这些 warning 都表示不可用
- 兼容性问题,如果你想要旧的 glibc 环境运行,你就必须使用旧的 glibc 环境构建
- 不适合 Alpine
为了解决上述缺陷,我们可以尝试使用 musl
musl 替换 glibc
还是原来的 gcc 环境,只是编译时 glibc 改为使用 musl
顺利的话 glibc 的 warning 都不会出现,运行也正常。
构建属性选项 –enable-kernel=2.6.32
最近看到还有一种方式是使用 extldflags 添加构建参数 –enable-kernel=2.6.32,在 docker image golang:1.17 尝试一下
看起来还想并没有效果,可能是我的姿势不对。
实际上编译出来的二进制信息还是 for GNU/Linux 3.2.0,理论上还是无法在 2.6.32 的内核上跑(本人太懒,不想再搭一套 2.6.32 的内核环境测试了)
总结
在 glibc 的静态编译下可能会出现一些 warning 信息,并且这些 warning 表示该功能不可用;在我的场景下我觉得可以使用 musl 替代,但 musl 并不是对任何情况都好使,你需要判断 musl 是否满足你需要的 feature,而且 musl 对比 glibc 性能有所下降,还有不少的限制存在没有仔细了解。
转载

本作品由 Jeff 创作,采用知识共享署名 4.0 国际许可协议进行许可。