Update Error on libc and libcrypt

  1. 因为最近有需求需要更新 libc 到 2.35,但是我的 Ubuntu 系统是 20.04,最高版本是 2.31(当时我以为是 22.04,所以可以升级到 2.35),然后就从源码中更新 libc,编译、安装,make install 之后,不仅发生错误,而且系统直接崩溃,命令都无法使用!!!
  2. 当我修复好系统之后,又手贱更新了 libc-bin,导致 libcrypt 出错,再次崩溃!!!
  3. 系统:Ubuntu 20.04,系统架构: x86_64

1. 系统崩溃时如何操作

当系统故障时,输入所有命令都无效,系统无法正常启动,此时有以下两种方法:

1.1 救援模式

开机时,按下 SHIFT + ESC 进入 GRUB 引导加载器页面

1
2
3
4
-----------------------------
|*Ubuntu |
|Advanced options for Ubuntu|
-----------------------------

下面有两种方式进入救援模式:

1.1.1 Ubuntu

  • 选择第一个选项并按 e 键进入编辑模式
  • 在以 linux 开头的一行末尾,删除字符串 $vt_handoff 并添加字符串 systemd.unit=rescue.target
  • 修改完之后,按 Ctrl + xF10 进入救援模式

1.1.2 Advanced options for Ubuntu

选择第二个选项后继续选择内核的 recover mode,并选择 root 进入救援模式

1.2 USB 启动盘

当救援模式也无法进入系统,可以使用 USB 启动盘来修复系统,制作方法如下:

  1. 准备一个 U 盘,建议 8G 以上,U 盘中的文件会被格式化,确保 U 盘中的文件已备份。
  2. 下载 Ubuntu 20.04 系统镜像文件
  3. 使用 Rufus 工具制作启动盘
  1. 选择 Ubuntu 的 iso 文件。
  2. 然后点击开始,等待完成即可。
  3. 开机时,一直按 F2 进入 BIOS 界面,找到 USB 启动盘启动选项, 调整优先级后保存并启动。
  4. 进入 Ubuntu 系统后,选择 Try Ubuntu 进入系统。

1.3 挂载崩溃系统

此时通过前两种方法可以使用命令行或者图形界面进入系统,此时需要先挂载崩溃系统,然后再修复系统。

  1. 查看崩溃系统的分区

    1
    sudo fdisk -l

    根据自己之前分区的情况,找到崩溃系统的分区,例如我的崩溃系统是 /dev/nveme0n1p7

  2. 挂载崩溃系统

    1
    sudo mount /dev/nveme0n1p7 /mnt
  3. 修复系统 ……

  4. 查看是否修复成功

    通过更换到崩溃系统的分区,如果没有核心已转储,能够正常进入,即修复成功。

    1
    sudo chroot /mnt

2. libc 引起的系统崩溃

  • 当我弄一些东西的时,从源码更新 libc 到 2.35,编译、安装,make install 之后,系统直接崩溃,命令都无法使用!!!

    1
    2
    3
    4
    5
    make[2]: *** [Makefile:84: da.mo] Segmentation fault (core dumped)
    make[2]: Leaving directory '/root/glibc-2.35/po'
    make[1]: *** [Makefile:215: po/subdir_install] Error 2
    make[1]: Leaving directory '/root/glibc-2.35'
    make: *** [Makefile:12: install] Error 2
  • 崩溃原因:

    • libc.so.6 是 C 运行时库 glibc 的软链接,程序启动和运行时,是根据 libc.so.6 软链接找到glibc库
    • lib64/libc.so.6 是一个软链接,指向 /lib64/libc.so-2.1x,2.1x 表示其对应版本,去兼容相应 Ubuntu 版本
    • 很多基本命命令依赖 glibc,libc.so.6 链接对应版本不一致将导致系统的几乎所有程序不能工作

2.1 方法一

  • 此时不要重启服务器,不要关闭当前终端,还有救!!!(仅限于系统中存在版本正确的 libc.so.6,不然就直接跳转到下面,)

  • 如果系统中还有 glibc-2.31.so(此时备份的重要性),则创建软连接即可

    1
    2
    ln -s /usr/lib64/libc-2.31.so /lib64/libc.so.6
    ln -s /usr/lib64/ld-2.31.so /lib64/ld-linux-x86-64.so.2
  • 并且删除 2.35 相关文件

2.2 方法二

  1. 进入救援模式,挂载崩溃系统

  2. 查看系统适配的 glibc 版本

    1
    ldd --version

    输出结果如下:

    1
    2
    3
    4
    5
    ldd (Ubuntu EGLIBC 2.31-0ubuntu6.6) 2.31
    Copyright (C) 2020 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions. There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    Written by Roland McGrath and Ulrich Drepper.
  3. 查看 libc 中 GLIBC 的版本

    1
    strings /lib64/libc.so.6 | grep -E "^GLIBC" | sort -V -r | uniq

    输出结果如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    GLIBC_2.35
    GLIBC_2.34
    GLIBC_2.33
    GLIBC_2.32
    GLIBC_2.31
    GLIBC_2.30
    GLIBC_2.29
    GLIBC_2.28
    GLIBC_2.27
    GLIBC_2.26
    ...
  4. 发现 glibc 还是 2.35 版本,需要降级到 2.31 版本,此时崩溃系统中没有 libc-2.31.so 文件,我发现 USB 启动盘中有这个文件(所以制作启动盘时最好和崩溃系统的版本相同),此时需要将其复制到崩溃系统中

    1
    2
    cp /usr/lib/x86_64-linux-gnu/libc-2.31.so /mnt/lib64/
    cp /usr/lib/x86_64-linux-gnu/ld-2.31.so /mnt/lib64/
  5. 然后创建软链接

    1
    2
    ln -s /lib64/libc-2.31.so /mnt/lib64/libc.so.6
    ln -s /lib64/ld-2.31.so /mnt/lib64/ld-linux-x86-64.so.2
  6. chroot /mnt 查看是否能正常进入,到此修复成功!!!

3. libcrypt 引起的系统崩溃

  • 当我修复好系统之后,又手贱更新了 libc-bin,导致 libcrypt 出错,再次崩溃!!!

    1
    /sbin/init: /lib/libcrypt.so.1: version `XCRYPT_2.0` not found (required by lib/systemd/lib/systemd-shared-245.so)
  • 崩溃原因:

    • 程序运行需要 libcrypt.so.1 库中的 XCRYPT_2.0 版本,但系统当前的 libcrypt.so.1 版本不支持 XCRYPT_2.0,由于库版本不兼容导致
  • 进入救援模式,挂载崩溃系统

  • 查看 libsystemd-shared-245.so 依赖的 libcrypt.so.1 版本

    1
    ldd /lib/systemd/libsystemd-shared-245.so | grep libcrypt.so.1

    输出结果如下:

    1
    2
    /lib/systemd/libsystemd-shared-245.so:/lib64/libcrypt.so.1:version ‘XCRYPT_2.0’ not found(required by /lib/systemd/libsystemd-shared-245.so)
    libcrypt.so.1 => /lib/libcrypt.so.1 (0x00007f2636167000)

    表示依赖的 libcrypt.so.1 链接于 /lib/libcrypt.so.1

  • 查看 libcrypt.so.1 版本

    1
    strings /lib/libcrypt.so.1 | grep "XCRYPT_2.0"

    没有输出,说明 /liblibcrypt.so.1 中没有 XCRYPT_2.0 版本

  • 发现 /liblibcrypt.so.1 中确实没有 XCRYPT_2.0 版本,此时需要一个正确的 libcrypt.so.1 文件。

3.1 下载兼容的 libcrypt1

1
2
3
4
5
6
7
8
9
10
# apt 可用
apt download libcrypt1

# apt 不可用
wget http://deb.debian.org/debian/pool/main/libx/libxcrypt/libcrypt1_4.4.33-2_amd64.deb

sudo dpkg -i libcrypt1_4.4.33-2_amd64.deb

# 修复依赖关系
apt install -f

3.2 创建软连接

若系统存在包含 XCRYPT_2.0 版本的 libcrypt.so.1 文件(用 strings 查看),则创建软连接即可

1
ln -s /usr/lib/x86_64-linux-gnu/libcrypt.so.1 /lib/libcrypt.so.1

此时使用 perl 命令查看是否修复(崩溃时 perl 也错误),即可大功告成!

4. 总结

  • 对于系统的库文件,一定不要轻易去修改,特别是在 root 权限下!!!
    1. 内核级 /lib64
    2. 系统级 /usr/lib64
    3. root 用户级 /usr/local/lib64
  • 任何重要或不确定的文件改动不要轻易执行删除,一定要先备份,以备出现故障后能尽快恢复。
  • 可以使用救援模式或 USB 启动盘来启动第二个系统作为备份和修复已崩溃系统的平台。

Reference

本文作者:jujimeizuo
本文地址https://blog.jujimeizuo.cn/2025/04/16/update-error-on-libc-and-libcrypt/
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0 协议。转载请注明出处!