跳转到主要内容

如何正确升级 Centos7 的 Glibc

本文撰写于 2020年 7 月 3 日,写这篇文章的时候还比较年轻,可能含有错误。
标题中的正确是相对与我参考的错误文章 [某文章教我用 fedora29 的 rpm 包去升级 centos7 的 glibc,于是我的系统挂了]。
不代表这是最佳操作方式,请知悉。
也可以参考在非标准位置安装 Glibc:https://serverfault.com/a/894689

请确保您有能力在系统损坏后救援您的系统!

不到万不得已,你不应该使用不支持的方式升级系统底层包。

Glibc 不可用会导致:bash 无法使用、yum/rpm 无法使用、无法解析名称空间、无法切换用户等,基本相当于系统不可用。

不应该在生产环境做此类操作。特别是升级这种系统底层组件。

不要安装不属于你系统的 RPM 包。

更新完必定会有某些东西有错误。

glibc 是 GNU 发布的 libc 库,即 c 运行库。glibc 是 linux 系统中最底层的 api,几乎其它任何运行库都会依赖于glibc。glibc除了封装 linux 操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。由于 glibc 囊括了几乎所有的 UNIX 通行的标准,可以想见其内容包罗万象。而就像其他的 UNIX 系统一样,其内含的档案群分散于系统的树状目录结构中,像一个支架一般撑起整个操作系统。在 GNU/Linux 系统中,其 C 函数库发展史点出了GNU/Linux 演进的几个重要里程碑,用 glibc 作为系统的 C 函式库,是 GNU/Linux 演进的一个重要里程碑。-------摘自百毒百科

错误的升级 Glibc 或 Glibc 损坏会毁了你的操作系统!


那么如何正确在 Centos7 升级 Glibc 呢


推荐全程在 screen 中运行,防止意外断开造成不可意料的后果。
下面所有组件都是撰写本文 2020/7/3 时的最新版,根据您的需要替换。
以下全部操作都是用 root 账户进行的。


升级 GNU Make 与 GCC,安装 Python3


高于 Glibc 2.4 的版本需要比 Centos7 自带的 make 和 GCC 更高的版本。
INSTALL 文件里面有写,这里精简一下:

如果你只想升级到 Glibc 2.24 则可以跳过此步骤。


1.升级GNU Make 4.3

 

wget https://ftp.gnu.org/gnu/make/make-4.3.tar.gz

wget https://mirrors.aliyun.com/gnu/make/make-4.3.tar.gz
  • 从官方或阿里云的镜像下载,中国大陆从官方下载太慢;
tar -xvf make-4.3.tar.gz
  • 解压;
cd make-4.3
  • 移动到文件夹;
mkdir build && cd build
  • 创建编译文件夹并移动;
../configure
  • 跨上一级文件夹编译器配置;
make -j24
  • 开始编译;
  • -j数值代表编译线程,您可以根据您的处理器核心来决定使用多少线程,如 -j8
  • -j 则为不限制线程,但可能导致错误;
make install
  • 安装;
make --v
  • 验证版本;

如果无意外则会输出:

GNU Make 4.3
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

至此升级 make 完成。



2.升级 GCC 10.1.0
wget https://ftp.gnu.org/gnu/gcc/gcc-10.1.0/gcc-10.1.0.tar.gz
wget https://mirrors.aliyun.com/gnu/gcc/gcc-10.1.0/gcc-10.1.0.tar.gz
  • 从官方或阿里云的镜像下载,中国大陆从官方下载太慢;
tar -xvf gcc-10.1.0.tar.gz
  • 解压;
cd gcc-10.1.0
  • 移动到文件夹;
./contrib/download_prerequisites
  • 下载依赖包;
mkdir build && cd build
  • 创建编译文件夹并移动;
mkdir /usr/local/gcc-10.1.0
  • 创建安装文件夹;
../configure --prefix=/usr/local/gcc-10.1.0 --enable-checking=release --enable-languages=c,c++ --disable-multilib
  • ../configure  跨上一级文件夹编译器配置;
  • --prefix=/usr/local/gcc-10.1.0  指定安装目录;
  • --enable-checking=release  在编译器中执行内部一致性检查;
  • --enable-languages=c,c++  指定支持的语言;
  • --disable-multilib  禁止编译适用于多重架构体系的库,就是 X86 X64 兼容之类的;
make -j24
  • 开始编译;
  • -j数值代表编译线程,您可以根据您的处理器核心来决定使用多少线程,如 -j8
  • -j 则为不限制线程,但可能导致错误;

make install
  • 安装;
export PATH=/usr/local/gcc-10.1.0/bin:$PATH
  • 设置为默认编译器,仅对当前会话有效;
  • 永久启用后文会提到;
vim ~/.bashrc
  • 编辑当前用户的 .bashrc 文件,当然你也可以写到全局配置文件;

在最后一行加入 export PATH=/usr/local/gcc-10.1.0/bin:$PATH 并保存。


source ~/.bashrc
  • 让配置生效;
cd /usr/lib64
  • 移动到 /lib64 目录;
rm -rf libstdc++.so.6
  • 删除老版本的 libstc++ 软连接,使用 rm -rf 删软连接的时候千万不要在后面加 /
ln -s /usr/local/gcc-10.1.0/lib64/libstdc++.so.6.0.28 libstdc++.so.6
  • 把新的 libstc++ 软连接到系统库

然后我建议你在需要的时候链接回老版本,因为之后可能会遇到 lib64/libstdc++.so.6: undefined symbol: libiconv
这样的错误,导致 yum 不可用之类的问题。

连回老版本的方法:

cd /lib64
rm -rf libstdc++.so.6
ln -s libstdc++.so.6.0.19 libstdc++.so.6

gcc -v
  • 检查新的 GCC 是不是生效了

如果无意外则会输出

使用内建 specs。
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/gcc-10.1.0/libexec/gcc/x86_64-pc-linux-gnu/10.1.0/lto-wrapper
目标:x86_64-pc-linux-gnu
配置为:../configure --prefix=/usr/local/gcc-10.1.0 --enable-checking=release --enable-languages=c,c++ --disable-multilib
线程模型:posix
Supported LTO compression algorithms: zlib
gcc 版本 10.1.0 (GCC) 
strings /usr/lib64/libstdc++.so.6 | grep 'CXXABI'
  • 检查新的 libstc++ 是不是生效了

如果无意外则会输出

CXXABI_1.3
CXXABI_1.3.1
CXXABI_1.3.2
CXXABI_1.3.3
CXXABI_1.3.4
CXXABI_1.3.5
CXXABI_1.3.6
CXXABI_1.3.7
CXXABI_1.3.8
CXXABI_1.3.9
CXXABI_1.3.10
CXXABI_1.3.11
CXXABI_1.3.12
CXXABI_TM_1
CXXABI_FLOAT128
CXXABI_1.3
CXXABI_1.3.11
CXXABI_1.3.2
CXXABI_1.3.6
CXXABI_FLOAT128
CXXABI_1.3.12
CXXABI_1.3.9
CXXABI_1.3.1
CXXABI_1.3.5
CXXABI_1.3.8
CXXABI_1.3.4
CXXABI_TM_1
CXXABI_1.3.7
CXXABI_1.3.10
CXXABI_1.3.3

至此升级 GCC 完成。

3.安装Python3

这个略了。


升级 Glibc 2.31

wget https://ftp.gnu.org/gnu/glibc/glibc-2.31.tar.gz
wget https://mirrors.aliyun.com/gnu/glibc/glibc-2.31.tar.gz
  • 从官方或阿里云的镜像下载,中国大陆从官方下载太慢;
tar -xvf glibc-2.31.tar.gz
cd glibc-2.31
mkdir build
cd build
  • 上面解释过了;
../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin
  • ../configure 跨上一级文件夹编译器配置;
  • 不要改 --prefix=/usr ;
  • --prefix=/usr 指定安装目录;
  • --disable-profile 关掉 profiling 信息相关的库文件编译;
  • --enable-add-ons 指示 glibc 使用附加的 NPTL 包作为线程库;
  • --with-headers=/usr/include 指示 glibc 按照这个目录中的内核头文件编译自己,从而精确的知道内核的特性以根据这些特性对自己进行最佳化编译;
  • --with-binutils=/usr/bin 保证在编译 glibc 时不会用错 Binutils;
make -j24
  • 开始编译;
  • -j数值代表编译线程,您可以根据您的处理器核心来决定使用多少线程,如 -j8;
  • -j 则为不限制线程,但可能导致错误;
make install
  • 安装;

这一步可能会出现

Execution of gcc -B/usr/bin/ failed!
The script has found some problems with your installation!
Please read the FAQ and the README file and check the following:
- Did you change the gcc specs file (necessary after upgrading from
  Linux libc5)?
- Are there any symbolic links of the form libXXX.so to old libraries?
  Links like libm.so -> libm.so.5 (where libm.so.5 is an old library) are wrong,
  libm.so should point to the newly installed glibc file - and there should be
  only one such link (check e.g. /lib and /usr/lib)
You should restart this script from your build directory after you've
fixed all problems!
Btw. the script doesn't work if you're installing GNU libc not as your
primary library!
make[1]: *** [Makefile:120: install] Error 1                                                                                
make[1]: Leaving directory '/root/glibc-2.31'                                                                               
make: *** [Makefile:12: install] Error 2

搜索此内容,得出的结果是大概不用管(?)


不放心的可以检测一下 libm.so

ls -l /usr/lib64/libm.so.6

没有意外就是已经连接到新版本了,如下

lrwxrwxrwx 1 root root 12 Jul  3 02:32 /usr/lib64/libm.so.6 -> libm-2.31.so

然后再次尝试安装还是报错,不太懂。
下面的检测看起来已经是安装成功了,系统/程序也没有异样。

ls -l /lib64/libc.so.6
  • 检测是否已经安装,检查软连接;

出现 

lrwxrwxrwx 1 root root 12 Jul  3 02:32 /lib64/libc.so.6 -> libc-2.31.so

即为成功

strings /lib64/libc.so.6 | grep GLIBC
  • 再次验证

如果无意外则会输出

GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.6
GLIBC_2.7
GLIBC_2.8
GLIBC_2.9
GLIBC_2.10
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.17
GLIBC_2.18
GLIBC_2.22
GLIBC_2.23
GLIBC_2.24
GLIBC_2.25
GLIBC_2.26
GLIBC_2.27
GLIBC_2.28
GLIBC_2.29
GLIBC_2.30
GLIBC_PRIVATE

为什么没有 2.31,我也不知道。


更新完可能会有的错误


更新完必定会有错误,这就是代价。


如果你运行 locale 命令报错的话,或者中文或其他语言变成了?????????

那么你需要 

cd glibc-2.31/build
  • 移动到编译 Glibc 的目录;
make localedata/install-locales
  • 编译语言文件;
make install
  • 再安装一次;

然后你的中文或是其他语言应该就不会????????了


遇到 lib64/libstdc++.so.6: undefined symbol: libiconv

这个原因是 libstdc++ 版本不匹配。解决方法:把 libstdc++ 的软连接改回老版本
这个问题应该是经常出现,比如 yum 什么的,多备着吧。

cd /lib64
rm -rf libstdc++.so.6
ln -s libstdc++.so.6.0.19 libstdc++.so.6


遇到 Error: /usr/lib64/libstdc++.so.6: version `CXXABI_1.3.*' not found

这个原因是 libstdc++ 版本不够新,解决方法:把 libstdc++ 的软连接改成新版本

首先找到你的gcc源码编译文件夹,比如我的在/root/gcc-10.1.0/

cd /root/gcc-10.1.0/build/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs
cp libstdc++.so.6.0.28 /usr/lib64/
  • 把最新的 libstdc++.so.6 复制到 /usr/lib64/
cd /usr/lib64
rm -rf libstdc++.so.6
ln -s libstdc++.so.6.0.28 libstdc++.so.6
  • rm -rf libstdc++.so.6 删除老的软连接;
  • ln -s libstdc++.so.6.0.28 libstdc++.so.6  把 libstdc++.so.6.0.28 软连接到 libstdc++.so.6;


更新完如果你的 yum 无任何反应

可能是因为 rpm 数据库有问题导致卡死

rm -f /var/lib/rpm/__db.00*
rpm --rebuilddb
yum clean all
  • rm -f /var/lib/rpm/__db.00*  删除 rpm 数据库文件;
  • rpm --rebuilddb 重建 rpm数据库
  • yum clean all 清理可能的缓存;

然后你的 yum 应该能用了


大功告成