先把风险说清楚
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 | 用于从网络下载文件 |
| gcc | C/C++ 编译器 |
| gcc-c++ | C++ 编译器 |
| zlib-devel | zlib 开发库 |
| libcurl-devel | libcurl 开发库 |
| openssl-devel | OpenSSL 开发库 |
| bzip2-devel | bzip2 开发库 |
| gmp-devel.x86_64 | GNU Multiprecision Library 开发库(x86_64) |
| mpfr-devel.x86_64 | MPFR Library 开发库(x86_64) |
| libmpc-devel.x86_64 | MPC Library 开发库(x86_64) |
| libSM-devel.x86_64 | X.Org SM 库开发库(x86_64) |
| libxml2-devel | libxml2 库开发库 |
| gcc-gfortran.x86_64 | Fortran 编译器(x86_64) |
| autoconf | 自动化配置脚本生成器,用于生成 Makefile 文件 |
| automake | 自动化 Makefile 生成器,用于生成 Makefile.in 文件 |
| boost-devel | Boost 库的开发包,用于开发 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。做到这两点,这条路径我们已经反复验证可行。
