Skip to content

Upgrade Gcc&Glibc-1

安装前请注意版本兼容性问题,如升级 Gcc-8.5.0 后编译升级 Glibc-2.34 会报错或需要升级相应的 Python3 来解决

参考链接

一. 安装说明

CentOS 7 官方源的 Gcc 最新版本目前还是 4.8.5,默认的 Gcc 版本无法编译 Glibc 2.28,而安装 Glibc 所需的依赖,需要 Gcc 4.9 以上及 Make 4.0 以下,另外 Gcc 11.2 版本太新,也无法与 Glibc 2.28 兼容。

  • Sys-OS:CentOS Linux release 7.9.2009 (Core)
  • Kernel:Linux pbe-4044-c1 6.5.9-1.el7.elrepo.x86_64
  • Make:GNU Make 4.2.1
  • Gcc:gcc version 8.3.0 (GCC)
  • Glibc:GLIBC_2.28

二. 升级 Gcc

安装 gcc-8.3.0 所依赖的环境

$ yum -y install bison wget bzip2 gcc gcc-c++ glibc-headers

编译升级 gcc-8.3.0

PS:注意此处未选择常规 yum install 方式升级,而是选择耗时的编译方式,后面详细说明

$ wget https://ftp.gnu.org/gnu/gcc/gcc-8.3.0/gcc-8.3.0.tar.gz
$ tar -xf gcc-8.3.0.tar.gz && cd gcc-8.3.0
$ ./contrib/download_prerequisites
gmp-6.1.0.tar.bz2: OK
mpfr-3.1.4.tar.bz2: OK
mpc-1.0.3.tar.gz: OK
isl-0.18.tar.bz2: OK
All prerequisites downloaded successfully.

$ mkdir build && cd build
$ ../configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
$ nohup make >& make.log &
true DO=all multi-do # make
$ make install
make[4]: Nothing to be done for `install-data-am'.
# 注意:重启后版本才能生效
$ init 6

重启后验证版本是否升级成功

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-pc-linux-gnu/8.3.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
Thread model: posix
gcc version 8.3.0 (GCC)

# 查看动态库版本情况,如非编译方式是无法升级动态库(libstdc++.so.6)
$ strings /usr/lib64/libstdc++.so.6 | grep GLIBC 
...
GLIBCXX_3.4.19

三. 升级 Make

将默认的 GNU Make 3.82 升至 GNU Make 4.2.1

$ wget http://ftp.gnu.org/gnu/make/make-4.2.1.tar.gz
$ tar -xf make-4.2.1.tar.gz && cd make-4.2.1
$ mkdir build && cd build
$ ../configure --prefix=/usr/local/make
$ make && make install
make[2]: Leaving directory `/usr/local/src/gcc-glibc/make-4.2.1/build'
make[1]: Leaving directory `/usr/local/src/gcc-glibc/make-4.2.1/build'

# 找出旧版本进行备份替换
$ whereis make
make: /usr/bin/make /usr/local/make /usr/share/man/man1/make.1.gz
$ cd /usr/bin && mv make make.bak
$ ln -sv /usr/local/make/bin/make /usr/bin/make
‘/usr/bin/make’ -> ‘/usr/local/make/bin/make’
$ make -v
GNU Make 4.2.1

四. 升级 Glibc

1
2
3
$ wget https://ftp.gnu.org/gnu/glibc/glibc-2.28.tar.gz
$ tar -xf glibc-2.28.tar.gz && cd glibc-2.28
$ mkdir build && cd build

在 Build 前需要修改配置文件,否则后续 make install 过程会报 /usr/bin/ld: cannot find -lnss_test2

1
2
3
4
5
6
7
$ vim ./glibc-2.28/scripts/test-installation.pl
126     if ($name ne "nss_ldap" && $name ne "db1"
127         && $name ne "thread_db"
128         && $name ne "nss_test1" 
129         && $name ne "nss_test2"  # 增加此行
130         && $name ne "libgcc_s") 
...

重新回到 Build 目录进行编译操作,另外编译前需添加 --enable-obsolete-nsl 参数

1
2
3
4
5
6
7
$ ../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin --enable-obsolete-nsl
$ nohup make -j4 >& make.log &
make[2]: Leaving directory '/usr/local/src/test/glibc-2.28/elf'
make[1]: Leaving directory '/usr/local/src/test/glibc-2.28'
$ make install
Your new glibc installation seems to be ok.
make[1]: Leaving directory '/usr/local/src/gcc-glibc/glibc-2.28'

验证服务,可以查看 Glibc 已从 GLIBC_2.17 更新至 GLIBC_2.28

1
2
3
4
5
$ strings /lib64/libc.so.6 |grep GLIBC_2.*
...
GLIBC_2.26
GLIBC_2.27
GLIBC_2.28

五. 升级 GLIBCXX

之前测试安装 NodeJS 18 以上版本时报错,需要更新 GLIBC_2.28GLIBCXX_3.4.21,首次使用 yum install devtoolset-8-gcc 或以上版本,GLIBC_2.28 都可正常编译成功,但动态库则无法更新升级,最终只能通过编译安装 Gcc 来解决,下将讲解为什么选择耗时的编译方式。

****: /lib64/libc.so.6: version GLIBC_2.28' not found (required by ./****)
****: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./****)

首次使用 yum install devtoolset-8-gcc 或以上版本升级结果如下:

$ strings /usr/lib64/libstdc++.so.6 | grep GLIBC 
...
GLIBCXX_3.4.19

$ find / -name 'libstdc++.so.6*'
/usr/lib64/libstdc++.so.6
/usr/lib64/libstdc++.so.6.0.19
/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.19-gdb.py
/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.19-gdb.pyc
/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.19-gdb.pyo
/opt/rh/devtoolset-8/root/usr/share/gdb/auto-load/usr/lib/libstdc++.so.6.0.19-gdb.py
/opt/rh/devtoolset-8/root/usr/share/gdb/auto-load/usr/lib/libstdc++.so.6.0.19-gdb.pyc
/opt/rh/devtoolset-8/root/usr/share/gdb/auto-load/usr/lib/libstdc++.so.6.0.19-gdb.pyo
/opt/rh/devtoolset-8/root/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.19-gdb.py
/opt/rh/devtoolset-8/root/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.19-gdb.pyc
/opt/rh/devtoolset-8/root/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.19-gdb.pyo

# libstdc++.so.6的软链接还是libstdc++.so.6.0.19
$ ls -l /usr/lib64/libstdc++.so*
lrwxrwxrwx. 1 root root     19 May 27 13:54 /usr/lib64/libstdc++.so.6 -> libstdc++.so.6.0.19
-rwxr-xr-x. 1 root root 995840 Sep 30  2020 /usr/lib64/libstdc++.so.6.0.19

尝试更新更高版本的 Gcc & Glibc 也是一样,最后只能全通过编译安装才能解决;

解决方法:编译安装 Gcc-8.3,再重链接动态库

安装方法如上述 升级 Gcc 步骤,但安装成功后并不代表已完成升级,还需要重做软链接至新的动态库

$ find / -name 'libstdc++.so.6*'
/usr/lib64/libstdc++.so.6
/usr/lib64/libstdc++.so.6.0.19
/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.19-gdb.py
/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.19-gdb.pyc
/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.19-gdb.pyo
# 注意:通过编译安装会新增libstdc++.so.6.0.25文件
/usr/local/lib64/libstdc++.so.6.0.25
/usr/local/lib64/libstdc++.so.6
/usr/local/lib64/libstdc++.so.6.0.25-gdb.py
/usr/local/src/test/gcc-8.3.0/build/stage1-x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.25
/usr/local/src/test/gcc-8.3.0/build/stage1-x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6
/usr/local/src/test/gcc-8.3.0/build/prev-x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.25
/usr/local/src/test/gcc-8.3.0/build/prev-x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6
/usr/local/src/test/gcc-8.3.0/build/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.25
/usr/local/src/test/gcc-8.3.0/build/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6

编译安装成功后会有新增文件 libstdc++.so.6.0.25,首先查看现 libstdc++.so.6 使用情况

1
2
3
4
# 目前libstdc++.so.6的软链接还是libstdc++.so.6.0.19
$ ls -l /usr/lib64/libstdc++.so*
lrwxrwxrwx. 1 root root     19 Nov 22 17:07 /usr/lib64/libstdc++.so.6 -> libstdc++.so.6.0.19
-rwxr-xr-x. 1 root root 995840 Sep 30  2020 /usr/lib64/libstdc++.so.6.0.19

现需要将 /usr/local/lib64/libstdc++.so.6.0.25 复制至 /usr/lib64/,删除旧的链接,再新建软链接

$ cp /usr/local/lib64/libstdc++.so.6.0.25 /usr/lib64/
$ ls -l /usr/lib64/libstdc++.so*
lrwxrwxrwx. 1 root root       19 Nov 22 17:07 /usr/lib64/libstdc++.so.6 -> libstdc++.so.6.0.19
-rwxr-xr-x. 1 root root   995840 Sep 30  2020 /usr/lib64/libstdc++.so.6.0.19
-rwxr-xr-x. 1 root root 12171056 Nov 24 16:34 /usr/lib64/libstdc++.so.6.0.25

$ rm -rf /usr/lib64/libstdc++.so.6
$ ln -s /usr/lib64/libstdc++.so.6.0.25 /usr/lib64/libstdc++.so.6
$ ls -l /usr/lib64/libstdc++.so*
lrwxrwxrwx. 1 root root       30 Nov 24 16:35 /usr/lib64/libstdc++.so.6 -> /usr/lib64/libstdc++.so.6.0.25
-rwxr-xr-x. 1 root root   995840 Sep 30  2020 /usr/lib64/libstdc++.so.6.0.19
-rwxr-xr-x. 1 root root 12171056 Nov 24 16:34 /usr/lib64/libstdc++.so.6.0.25

$ strings /usr/lib64/libstdc++.so.6 | grep GLIBC 
...
GLIBCXX_3.4.25

再次执行以下命令来查看,最高版本已到了 GLIBCXX_3.4.25,至此 Gcc & Glibc 完成更新。

六. 异常记录

问题一:重启服务器后登录报错 -bash: warning: setlocale: LC_TIME: cannot change locale (en_US.UTF-8)

问题原因:glibc 编译安装 make && make install 后系统中文和 locale 会有问题,导致中文乱码和程序 encode 等出问题,重新 make localedata/install-locales 即可

1
2
3
4
5
$ cd ./glibc-2.28/build
$ make localedata/install-locales
...
make[2]: Leaving directory '/usr/local/src/gcc-glibc/glibc-2.28/localedata'
make[1]: Leaving directory '/usr/local/src/gcc-glibc/glibc-2.28'

问题二:在 Glibc 进行 configure 编译时报如下错误

1
2
3
configure: error: 
*** These critical programs are missing or too old: make python
*** Check the INSTALL file for required versions.

问题原因:Gcc & Glicb 版本选择过高,需要 Python3 才能编译

$ yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel
$ wget https://www.python.org/ftp/python/3.6.15/Python-3.6.15.tgz
$ tar -xf Python-3.6.15.tgz 
$ cd Python-3.6.15
$ ./configure --prefix=/usr/local/python3
$ make && make install
Installing collected packages: setuptools, pip
Successfully installed pip-18.1 setuptools-40.6.2
$ ln -s /usr/local/python3/bin/python3 /usr/bin/python3
# 添加环境变量
$ vim ~/.bash_profile
# 在第10行添加:/usr/local/python3/bin
10 PATH=$PATH:$HOME/bin:/usr/local/python3/bin
$ source ~/.bash_profile
$ python3 -V
Python 3.6.15
$ pip3 -V
pip 18.1 from /usr/local/python3/lib/python3.6/site-packages/pip (python 3.6)

PS:确认无误后,再回到 Glibc 的编译 configure 操作

问题三:Gcc & Glibc make 过程中报如下错误

1
2
3
4
5
6
make[2]: Entering directory '/usr/local/src/glibc/glibc-2.34/csu'
make[2]: *** Cannot open jobserver /tmp/GMfifo24146r: No such file or directory.  Stop.
make[2]: Leaving directory '/usr/local/src/glibc/glibc-2.34/csu'
make[1]: *** [Makefile:478: csu/subdir_lib] Error 2
make[1]: Leaving directory '/usr/local/src/glibc/glibc-2.34'
make: *** [Makefile:9: all] Error 2

问题原因:使用了 make -j4 多线程编译导致,改为 make 编译即可

PS:make -j4 命令,用于编译软件时指定并行编译的线程数,其 -j4 表示使用 4 个线程进行编译,以加快编译过程