在 CentOS 7 上升级 gcc 9.3.0 与 glibc 2.29

先把风险说清楚

CentOS 7 的生命周期将尽,而它自带的 gcc 4.8.5、glibc 2.17 又实在太老,有些新软件(比如我们这边因算法需求要跑的一些组件)根本编不过。于是升级工具链成了绕不开的事。

但必须把话说在前面:升级 glibc 是整个操作里最危险的一步。 gcc 升级相对安全——它可以装到独立前缀、和系统 gcc 共存,用哪个靠 PATH 切换。glibc 不一样,它是系统里几乎所有二进制程序都链接的基础库,一旦替换出问题,轻则命令报错,重则整机起不来、ssh 都进不去。隔三差五就能看到有人升级 glibc 把生产机搞挂的帖子,这不是吓唬。

我们自己也曾因升级 glibc 出过事故,后来因为算法需求反复操练才算熟练。操作有风险,执行需谨慎:请务必先在可快照、可回滚的机器上演练,确认无误再碰生产;升级 glibc 前保证有带外(KVM/IPMI/云控制台)救援手段,别只靠 ssh。

本文的步骤参考了这篇文章并逐项亲自验证可行: https://chandrameenamohan.medium.com/building-nvidia-triton-inference-server-from-scratch-for-tensorflow-backend-873ef0a1f7f3

目标版本:

gcc    4.8.5  -->  9.3.0
glibc  2.17   -->  2.29

升级前的准备

先确认当前版本,升级后好对照:

gcc -v
ldd --version

然后装依赖。建议装之前先配好 EPEL:

包名用途
wget用于从网络下载文件
gccC/C++ 编译器
gcc-c++C++ 编译器
zlib-develzlib 开发库
libcurl-devellibcurl 开发库
openssl-develOpenSSL 开发库
bzip2-develbzip2 开发库
gmp-devel.x86_64GNU Multiprecision Library 开发库(x86_64)
mpfr-devel.x86_64MPFR Library 开发库(x86_64)
libmpc-devel.x86_64MPC Library 开发库(x86_64)
libSM-devel.x86_64X.Org SM 库开发库(x86_64)
libxml2-devellibxml2 库开发库
gcc-gfortran.x86_64Fortran 编译器(x86_64)
autoconf自动化配置脚本生成器,用于生成 Makefile 文件
automake自动化 Makefile 生成器,用于生成 Makefile.in 文件
boost-develBoost 库的开发包,用于开发 C++ 程序
make构建工具,用于自动化软件编译、安装、测试等工作
patchelf用于修改 ELF 文件的符号表和动态链接库依赖项
bison语法分析器生成器,用于生成 C 语言语法分析器
yum install epel-release.noarch -y
yum install wget gcc gcc-c++ zlib-devel libcurl-devel openssl-devel bzip2-devel gmp-devel.x86_64 mpfr-devel.x86_64 libmpc-devel.x86_64 libSM-devel.x86_64 libxml2-devel gcc-gfortran.x86_64 autoconf automake boost-devel make patchelf bison -y

依赖可以按实际系统和库的情况增减。这里面 patchelf 值得留意——升级后如果某些已编好的二进制找不到新的链接器或库,可以用它改 ELF 的 interpreter 和 rpath 来救,是处理 glibc 升级善后的常用工具。

升级和验证

1. 升级 gcc 到 9.3.0

gcc 这一步相对安全,因为它不碰系统现有 gcc。

mkdir gcc-build
cd gcc-build

GCC_VERSION=9.3.0

# 下载指定的 gcc 版本,这里是 9.3.0
wget https://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.gz
# 解压
tar xzvf gcc-${GCC_VERSION}.tar.gz
# 创建编译时目录
mkdir obj.gcc-${GCC_VERSION}
# 进入源码目录,执行 download_prerequisites 脚本下载编译前的依赖
cd gcc-${GCC_VERSION}
./contrib/download_prerequisites

# 到与源码同级的 obj 目录下编译安装
cd ../obj.gcc-${GCC_VERSION}
../gcc-${GCC_VERSION}/configure --disable-multilib --enable-languages=c,c++
make -j 4   # 编译进程数,建议与 CPU 核心数相当
make install

./contrib/download_prerequisites 这一步不能省,它会把 gcc 自己要用的 gmp/mpfr/mpc 等对应版本拉下来放到源码树里,省得你手工对版本。--disable-multilib 表示不编 32 位支持,64 位系统上一般用不到;--enable-languages=c,c++ 只编 C/C++,不编 Fortran 之类,能快不少。版本号、安装目录、编译目录都可以按需要改,不必拘泥。

2. 升级 make 到 4.3

glibc 2.29 要求 make 4.3 及以上,而 CentOS 7 自带的 make 太老,所以先把 make 升上去:

wget https://ftp.gnu.org/gnu/make/make-4.3.tar.gz
tar xf make-4.3.tar.gz
cd make-4.3
./configure --prefix=/usr/local
make
make install

这一步没什么玄机,但要记住 make 被装到了 /usr/local 下。随后 yum remove make 删掉老版本,再改环境变量、或把 /usr/local/bin、/usr/local/sbin 下的新 make 软链到 /usr/bin/、/usr/sbin/,确保后面编译 glibc 时用到的是 4.3。

3. 升级 glibc 到 2.29(高危)

这是真正危险的一步。下面的 --prefix=/usr 会把新的 glibc 装到系统主前缀,也就是替换掉系统正在用的 glibc——这正是风险所在。开始之前再确认一遍:机器可快照、有带外救援通道。

wget https://ftp.gnu.org/gnu/glibc/glibc-2.29.tar.gz
tar xf glibc-2.29.tar.gz
cd glibc-2.29
mkdir glibc-build
cd glibc-build
../configure --prefix=/usr && /usr/local/bin/make
/usr/local/bin/make install

这里有一点务必注意:make 要用上一步升级后的那个,所以显式写成 /usr/local/bin/make,而不是系统默认的老 make,否则 glibc 2.29 会因为 make 版本不够而编不过。其余没有特别的。

验证

ldconfig
gcc --version
ldd --version

gcc --version 应显示 9.3.0,ldd --version 应显示 2.29。装完先跑一遍 ldconfig 刷新动态库缓存,再验证。

小结

记住风险的分层:gcc、make 都可以装到独立前缀、和系统共存,出了问题影响有限;glibc 不同,--prefix=/usr 是在替换全系统的基础库,一步走错整机可能起不来。所以真正该守住的两条底线是——glibc 这一步必须在可快照、有带外救援的环境里做;编 glibc 时务必用升级后的 /usr/local/bin/make。做到这两点,这条路径我们已经反复验证可行。

Published At (Updated At) Tagged with