VMware ESXi Ubuntu 虚拟机库依赖缺失导致服务启动失败
Ubuntu 从 20.04 升级到 24.04 后,libcurl 与 libnghttp2 版本不匹配,导致 NetworkManager 启动时符号解析失败而崩溃,大量依赖网络的服务连锁失败。本文记录通过离线方式修复库依赖缺失、恢复系统服务的完整排查与解决过程。
目录
1. 问题现象
VMware ESXi 平台上的 Ubuntu 虚拟机开机后无法进入图形桌面环境,停留在命令行界面。
具体表现:
- 系统可以正常引导,内核加载无异常
- 文件系统检查通过,无损坏
- 但大量系统服务启动失败,特别是 NetworkManager 服务反复崩溃重启
- 无法使用网络功能,无法正常登录桌面
通过 journalctl -xb 查看启动日志,可以观察到大量服务报 Failed 状态,其中核心报错为:
NetworkManager: symbol lookup error:
/lib/x86_64-linux-gnu/libcurl-gnutls.so.4: undefined symbol:
nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation2. 原因分析
2.1 直接原因
NetworkManager 在启动时加载 libcurl-gnutls.so.4(来自 libcurl 8.5.0),而该库在运行时需要解析 libnghttp2.so.14 中的符号 nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation。
但系统中安装的 libnghttp2-14 版本(1.40.0)过低,该符号在 nghttp2 1.57 版本中才引入,导致动态链接器无法解析该符号,NetworkManager 进程启动失败并以退出码 127 退出。
2.2 根本原因
该虚拟机此前从 Ubuntu 20.04 升级到 Ubuntu 24.04。升级过程中,libcurl 相关包被升级到了 8.5.0(Ubuntu 24.04 版本),但 libnghttp2-14 没有同步升级,仍停留在 1.40.0(Ubuntu 20.04 版本)。
同时旧版的 libcurl4(7.68.0)未被正确清理,残留在系统中处于未配置状态(dpkg 状态为 iU),造成了包管理层面的版本混乱。
2.3 版本依赖关系
NetworkManager
└── 依赖 libcurl-gnutls.so.4 (libcurl 8.5.0)
└── 依赖 libnghttp2.so.14 中的符号
nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation
└── 该符号需要 nghttp2 >= 1.57
└── 系统中安装的是 1.40.0 ← 版本过低!2.4 连锁影响
NetworkManager 崩溃后导致以下依赖它的服务连锁失败:
| 服务 | 影响 |
|---|---|
NetworkManager-wait-online | 网络等待超时 |
SSSD 系列 socket 服务 | nss、pam、ssh、sudo 等身份认证不可用 |
gnome-shell | 同样因 libsoup-3.0.so.0 缺少 nghttp2 符号而崩溃 |
pipewire-pulse、cups | 音频、打印等服务不可用 |
3. 解决方案
本方案需要在能联网的机器上提前下载 .deb 包,通过离线方式导入虚拟机。
3.1 第一步:确认问题包的版本信息
在虚拟机中执行以下命令,确认相关包的安装状态:
# 查看 libcurl 和 libnghttp2 的版本与状态
dpkg -l | grep -E "curl|nghttp2"确认 libnghttp2-14 的版本号(例如 1.40.0),以及是否存在 iU(未配置)状态的残留包。
3.2 第二步:下载正确版本的 .deb 包
在能联网的机器上(物理机、其他虚拟机等),下载与系统版本匹配的 libnghttp2-14 包。
关键:版本必须 >= 1.59.0,否则仍然缺少所需的符号。
以 Ubuntu 24.04 (Noble) 为例,下载地址:
http://archive.ubuntu.com/ubuntu/pool/main/n/nghttp2/libnghttp2-14_1.59.0-1ubuntu0.3_amd64.deb可访问 http://archive.ubuntu.com/ubuntu/pool/main/n/nghttp2/ 查看所有可用版本,选择
amd64架构、ubuntu0.3后缀的版本(表示 24.04 的安全更新版本)。
3.3 第三步:将 .deb 包传入虚拟机
由于虚拟机网络不可用,需要通过离线方式传入文件。推荐以下两种方法:
方法 A:VMware 共享文件夹
- 在 VMware 中右键虚拟机 → 设置 → 选项 → 共享文件夹 → 始终启用
- 添加一个 Windows 本地目录作为共享目录
- 将 .deb 文件放入该共享目录
- 在虚拟机中挂载并复制:
mkdir -p /mnt/hgfs
mount -t fuse.vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other
cp /mnt/hgfs/<共享目录名>/libnghttp2-14_*.deb /tmp/方法 B:自建 ISO 镜像
- 使用 ImgBurn、7-Zip 等工具将 .deb 文件打包为 ISO 镜像
- 在 VMware 中将该 ISO 挂载到虚拟机的虚拟光驱
- 在虚拟机中挂载光驱并复制:
mount /dev/sr0 /mnt/cdrom
cp /mnt/cdrom/libnghttp2-14_*.deb /tmp/3.4 第四步:安装更新版本的 libnghttp2-14
# 安装(会自动覆盖旧版本)
dpkg -i /tmp/libnghttp2-14_1.59.0-1ubuntu0.3_amd64.deb
# 确认版本已更新
dpkg -l | grep nghttp23.5 第五步:清理残留的旧版 libcurl4 包
检查 dpkg -l 输出中是否有状态为 iU 的 libcurl 相关包。如果有,强制移除:
dpkg --purge --force-all libcurl43.6 第六步:验证并启动服务
# 确认所需符号已存在于库文件中
nm -D /lib/x86_64-linux-gnu/libnghttp2.so.14 | grep nghttp2_option_set_no_rfc9113
# 重置失败状态并启动 NetworkManager
systemctl reset-failed NetworkManager
systemctl start NetworkManager
# 确认服务正常运行
systemctl status NetworkManagerNetworkManager 正常启动后,其他依赖它的服务(GNOME 桌面、SSSD、音频等)会自动恢复。
3.7 第七步:重启验证
reboot重启后确认系统能正常进入图形桌面,所有服务正常运行。
4. 经验总结
| 经验 | 说明 |
|---|---|
| 大版本升级后务必检查包状态 | 执行 dpkg -l | grep iU 检查是否有未配置的残留包,及时清理 |
| 离线环境提前准备关键依赖包 | 在有网络时下载好常用依赖包的 .deb 文件备用,避免故障时无法获取 |
| 升级时确保依赖链完整 | libcurl、nghttp2、libsoup 等库之间存在强依赖关系,升级时需要确保版本配套 |
本文章已被查看 0 次