news 2026/9/12 3:24:29

Jetson平台glibc升级指南:手动dpkg解决GLIBC_2.28 not found

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Jetson平台glibc升级指南:手动dpkg解决GLIBC_2.28 not found

相信不少在 NVIDIA Jetson 平台(Nano、TX2、Xavier NX、AGX Xavier 都算)上折腾 Ubuntu 18.04 的朋友,都碰到过这种鬼事情:明明模型训练好了、代码写完了,一部署到板子上,GLIBC_2.28 not found或者GLIBCXX_3.4.26 not found直接糊脸,查了一圈发现是系统自带的 glibc 版本太老,死死卡在 2.27,好多新编译的二进制根本跑不起来。我这回在 Jetson Xavier NX 上部署一个基于 Python 3.8 的推理服务,就被这个版本坑了两天,最后通过 APT 配合 Ubuntu 20.04 的 ARM64 软件包,把 glibc 从 2.27 安全升到了 2.31(满足 2.28+ 的要求)。整个过程把依赖链、安装顺序、急救方案都摸了一遍,这里完整写出来,给同样被卡住的人一个可以直接抄作业的参考。

Jetson 平台和普通 x86 台式机不一样,NVIDIA 的 JetPack 体系是基于 Ubuntu 18.04 深度定制的,内核、设备树、GPU 驱动、CUDA 用户态库全是绑定的,不能像 PC 上那样直接换源升级整个系统。所以这篇文章的核心思路是:只通过 APT 从 Ubuntu 20.04 的 ARM64 仓库下载 glibc 相关的几个关键包,手动 dpkg 安装,做到最小化升级,既绕过版本卡点,又不破坏 JetPack 的底层体系。下面从问题根源讲起,把整个方案拆开揉碎,包括我踩过的坑和最终验证结果。

1. 问题根源:Jetson 上 glibc 2.27 为什么会成为瓶颈

1.1 glibc 是程序运行的地基

glibc(GNU C Library)是 Linux 系统里最底层的动态链接库,几乎所有用户态程序都要跟它打交道。你可以把它理解成程序和内核之间的翻译官,程序调用文件读写、内存分配、网络连接这些基础能力,都是通过 glibc 去跟内核沟通的。这个翻译官的版本太低,很多"外语"(新程序里用到的新系统调用和符号)它就听不懂了,直接甩给你一句version GLIBC_2.28 not found

在 x86 平台想升级 glibc,网上一搜一大把教程,但 Jetson 这边情况完全不同。Jetson 的 JetPack 4.x 全系列都基于 Ubuntu 18.04,自带 glibc 版本是 2.27,这个版本对应的是 2018 年的生态。你现在随便去 PyPI 拉一个较新的 PyTorch 或者 TensorFlow 的 ARM wheel,很多都是用 manylinux2014 标准编译的,这个标准的最低 glibc 要求就是 2.28,老版本直接拒绝运行。

检查当前版本很简单,一条命令就够:

ldd --version

输出结果会显示ldd (Ubuntu GLIBC 2.27-3ubuntu1.6) 2.27这样的信息。另外也可以用getconf GNU_LIBC_VERSION确认。如果输出是 2.27,那你就已经被卡在门槛外了。

1.2 Jetson 平台不能直接抄 x86 的升级方案

有人会说,Ubuntu 18.04 不能升级到 20.04 吗?升到 20.04 之后 glibc 就是 2.31,直接满足要求,干嘛要这么麻烦?

问题就出在 Jetson 的体系上。NVIDIA 的 L4T(Linux for Tegra)BSP 是深度定制的,内核版本、设备树、GPU 内核模块、CUDA 用户态库、多媒体编解码库全部都是针对 Ubuntu 18.04 编译和验证的。JetPack 5.x 虽然基于 Ubuntu 20.04,但 NVIDIA 官方只把它适配到了更新的硬件上,像 Jetson Nano、TX2 这些老平台,最后支持的版本就是 JetPack 4.6,也就是 Ubuntu 18.04。

如果在 Jetson 上强行做整系统升级,APT 会把内核、systemd、udev 这些核心组件全部替换成 20.04 的版本,但 NVIDIA 的驱动模块还是 18.04 时代的配套,DKMS 编译大概率会失败,轻则 CUDA 起不来,重则开机直接卡死在设备树加载阶段。所以我在这篇文章里说的升级,不是升级 Ubuntu 版本,而是只针对 glibc 和 libstdc++ 这几个关键用户态库做定点升级。

1.3 哪些场景真的需要 glibc 2.28+

我在自己的板子上总结了一下,遇到下面几类情况,基本就是 glibc 版本卡脖子的典型信号:

场景典型报错最低要求
新版 PyTorch / TensorFlow ARM wheelGLIBC_2.28 not foundglibc 2.28
Node.js 18+ 官方预编译包version GLIBC_2.28 not foundglibc 2.28
Python 3.8+ 编译安装fatal error: gnu/stubs-32.h或链接失败glibc 2.28
新版 Redis / Nginx 二进制GLIBC_2.29 not foundglibc 2.29
部分 ROS 2 相关二进制GLIBCXX_3.4.26 not foundlibstdc++ 10.x

注意最后一行,光升 glibc 还不够。有些 C++ 程序报的GLIBCXX错误,是 libstdc++.so.6 这个 C++ 标准库的版本问题,它和 glibc 是两个独立的库。Ubuntu 18.04 自带的 libstdc++6 是 8.x 版本,对应 GLIBCXX 到 3.4.25,而很多新程序需要 3.4.26 甚至更高。所以在升级计划里,libstdc++6 也必须一并升级,这个点很多人会漏掉。后面实操部分我会把两个包都带上。

2. 方案选型:为什么最终选择手动 dpkg 而不是直接改源

2.1 把 sources.list 改成 focal 是最危险的操作

网上有些教程会让你把/etc/apt/sources.list里的bionic改成focal,然后apt update && apt dist-upgrade,觉得这样就能把整个系统升到 Ubuntu 20.04,glibc 自然也变成 2.31 了。这个方法在普通 PC 上可行,但在 Jetson 上几乎是自杀式操作。

原因很简单:Jetson 的内核和 rootfs 是 NVIDIA 深度定制的,linux-imagenvidia-l4t-*这些核心包全部来自 NVIDIA 自己的源。一旦你放了 focal 的源进去,APT 会尝试把内核、initramfs、systemd、库文件全部升级到 focal 版本。这个过程中 nvidia-l4t 的驱动模块和新内核大概率出现兼容性问题,DTB 设备树也可能因为版本不一致而加载失败。我在一个测试用的 Nano 上尝试过一次,升级到一半就开始报错,重启后 HDMI 输出直接没了,只能通过 SDK Manager 重刷镜像救回来。

所以,整源升级在 Jetson 上不是"技术难度"问题,而是"这套 BSP 根本不支持"的硬伤。如果你的板子承载了业务数据,千万不要走这条路。

2.2 APT pinning 方案看着灵活,实际上坑也不少

第二种思路是保留 bionic 源,额外追加 focal 源,然后通过 APT 的 pinning 优先级机制,只让 APT 从 focal 安装 glibc 相关的少数包。做法大致是这样:

echo "deb http://ports.ubuntu.com/ubuntu-ports focal main universe" | sudo tee /etc/apt/sources.list.d/focal-temp.list cat <<EOF | sudo tee /etc/apt/preferences.d/glibc-focal Package: libc6 libc-bin libc6-dev libc-dev-bin libstdc++6 Pin: release n=focal Pin-Priority: 1001 Package: * Pin: release n=focal Pin-Priority: 100 EOF sudo apt-get update sudo apt-get install -t focal libc6 libc-bin libc6-dev libc-dev-bin libstdc++6

听起来很完美,但实际操作中 APT 的依赖解析不会那么听话。libc6 在 focal 里依赖 libgcc-s1 和 libcrypt1,libstdc++6 依赖 libgcc-s1,而 libgcc-s1 又依赖 gcc-10-base。你给了 libc6 一个 1001 的优先级,APT 为了满足依赖,就会尝试把 libgcc-s1、libcrypt1、gcc-10-base 这些包也一起从 focal 拉过来,甚至可能拖入 dpkg、bash 等底座包的 focal 版本,导致系统变成 bionic 和 focal 文件混装的"缝合怪"。这种混合状态一旦出问题,排查难度比直接升级 glibc 还大。

2.3 手动 dpkg 是最可控的路线

最终我选择的是手动下载几个 .deb 包,然后用dpkg -i直接安装。这个方案的好处是:只安装你自己明确的几个包,APT 不会自作主张去升级其他东西,系统的其余部分保持 Ubuntu 18.04 原样不动。缺点是需要自己处理依赖关系,有时候还要用--force-depends这种强制参数,对新手不太友好。

三种方案对比下来:

方案可控性风险等级是否推荐
篡改 sources.list 整源升级极低极高,容易变砖强烈不推荐
APT pinning 定点升级中等中等,依赖解析不可控不推荐新手
手动 dpkg 安装指定 deb极高低,但需要理解依赖推荐

手动 dpkg 本质上是在把系统当成一个"只要关键文件版本对得上,其他都不动"的黑盒来处理。glibc 和 libstdc++ 都遵循向后兼容原则,新版本能运行所有旧版本编译出来的程序,所以我们只需要保证升级后的版本号满足新软件的最低要求,不用太担心旧程序被破坏。

3. 实操:在 ARM64 架构下把 glibc 和 libstdc++ 升到 2.31

3.1 升级前必须做的备份和风险评估

裸奔升级 libc 这种核心库,就像在高速公路上换轮胎,准备工作不到位就是拿系统生命开玩笑。我在正式动手之前做了这么几件事:

第一,确认板子型号和当前 JetPack 版本。用jetpack_version或者查看/etc/nv_tegra_release文件,确认自己确实运行在 Ubuntu 18.04(bionic)上。JetPack 5.x 的读者不需要看这篇文章,因为你的系统本来就是 Ubuntu 20.04。

第二,备份数据。把/home下重要目录、项目代码、模型权重文件通过rsync或者scp同步到外部存储。这个操作属于底线保障,虽然升级出问题的概率不高,但万一真出问题,有备份就还有退路。

第三,检查磁盘空间。df -h确认 rootfs 至少有 500MB 空闲,因为 dpkg 安装 libc6 的时候会解压大量文件到/lib/aarch64-linux-gnu/,磁盘写满会导致安装中断,那才是真正的灾难。

第四,准备串口调试线。Jetson 开发板上有 Debug UART(调试串口),用 USB-TTL 转接线连到电脑,可以绕开 SSH 直接进入系统控制台。这一步很多人会忽略,但真遇到 SSH 断连、系统启动异常的时候,串口是唯一的救援通道。Jetson Nano 是 40-pin 扩展口旁边的那个 4-pin 插针,Xavier NX 模块需要配合载板上的调试口。关于内核兼容性,glibc 2.31 理论上最低支持 Linux 3.2 内核,Jetson 的 4.9 内核跑它完全没有问题,这个我在后面验证过,可以放心。

3.2 下载 Ubuntu 20.04 的 ARM64 软件包

Jetson 是 ARM64 架构(aarch64),所以不能去archive.ubuntu.com那边下,那里主要是 amd64 的包。ARM 架构的 Ubuntu 仓库统一在ports.ubuntu.com

我用的下载方式是直接在板子上临时加一个 focal 源,然后用apt-get download把指定的包拉下来,这样版本号会由 APT 自动解析,不会出现手误写错版本号的问题。

mkdir -p ~/glibc-upgrade && cd ~/glibc-upgrade # 临时添加 focal 源(只用 download,不安装) echo "deb http://ports.ubuntu.com/ubuntu-ports focal main universe" | sudo tee /etc/apt/sources.list.d/focal-temp.list sudo apt-get update # 用 download 参数把关键包下载到当前目录 apt-get download libc6 libc-bin libc6-dev libc-dev-bin libstdc++6 libgcc-s1 gcc-10-base libcrypt1

执行完成后,当前目录会出现一堆.deb文件。注意apt-get download只会下载包体,不会解析或安装依赖,也不会改动系统状态,这个操作本身是安全的。下载完成后立即删除临时源并重新apt-get update,避免后续误操作把系统指向 focal:

# 移除临时 focal 源,恢复 bionic 环境 sudo rm /etc/apt/sources.list.d/focal-temp.list sudo apt-get update

如果你对版本有强迫症,想完全固定版本号再复制到板子上,也可以在任一台 Ubuntu 20.04 的 ARM64 设备上下载,或者直接用 wget 从 ports 仓库拉取指定版本文件。我当时拿到的大致版本是libc6_2.31-0ubuntu9.9_arm64.deb这一批。这里有一个细节,focal 的 glibc 小版本补丁是持续更新的,比如 2.31-0ubuntu9.9、2.31-0ubuntu9.16 之类的,只要大版本是 2.31,小版本号不影响结论,选最新补丁版反而更安全。

3.3 安装顺序、依赖链与 force 参数的正确用法

这是整篇博文最核心的部分。先说结论:所有 .deb 一次性放进同一条dpkg -i命令里安装,不要一个一个装。

为什么不能分开装?因为 libc6 和 libc-bin 这两个包之间有循环依赖。libc6 是主库文件,libc-bin 里面装的是ldconfiggetconflocale-gen这些工具,而ldconfig本身要链接新版本的 libc6 才能运行。你把 libc6 先装了,libc-bin 还是旧版,旧版工具链新库可能有问题;反过来先装 libc-bin 更不行,因为它的动态链接器直接指向新版 libc6。所以必须同时安装,让 dpkg 在一个事务里把它们全部解压到系统,然后在配置阶段统一处理。

libstdc++6 的情况类似,它虽然不跟 libc6 有循环依赖,但它依赖 libgcc-s1,而系统的 libgcc1 包提供的是旧版libgcc_s.so.1。libgcc-s1 是 focal 里对 libgcc1 的重命名,两者提供同一个文件路径,直接装 libgcc-s1 会发生文件覆盖冲突。

我自己最终用的安装命令是这样的:

cd ~/glibc-upgrade sudo dpkg -i --force-depends --force-overwrite \ libc6_*.deb \ libc-bin_*.deb \ libc6-dev_*.deb \ libc-dev-bin_*.deb \ libstdc++6_*.deb \ libgcc-s1_*.deb \ gcc-10-base_*.deb \ libcrypt1_*.deb

命令里的参数说明:

  • --force-depends:强制忽略依赖关系。因为 focal 的 libc6 会声明依赖 libgcc-s1 和 libcrypt1,而当前 bionic 系统的包管理器信息里没有这些包(libgcc1 提供的是旧文件名),dpkg 会报"依赖未满足"的错。加上这个参数后,dpkg 会直接把包装上,不检查依赖是否满足。
  • --force-overwrite:允许包覆写其他包已有的同名文件。这个主要解决 libgcc-s1 和系统里 libgcc1 的libgcc_s.so.1文件冲突问题。

这里我要特别说明一个注意事项:--force-depends不是让你无脑跳过所有依赖。它跳过的只是"包管理器层面"的依赖检查,但如果某个库文件在运行时真正缺失,程序启动时还是会error while loading shared libraries。所以我们选择一次性把libgcc-s1gcc-10-baselibcrypt1这些外围支持包也下载下来并一并安装,尽量让文件层面的依赖也自洽。

安装过程中,dpkg 会输出一大段日志,里面会看到Processing triggers for libc-bin (2.31-0ubuntu9.9)这样的一行,这是系统在运行ldconfig重建动态链接库缓存,属于正常现象。这段期间系统会短暂"停顿"几秒钟,千万不要强行关电源或者按 Ctrl+C,等它跑完就没事了。

3.4 升级结果的验证清单

装完之后,验证就是最关键的一步,别急着跑业务程序,先按顺序检查下面这些:

第一个必查项,glibc 版本:

ldd --version

正常输出会显示类似ldd (Ubuntu GLIBC 2.31-0ubuntu9.9) 2.31。这一步说明 libc.so.6 已经更新成功。

第二个必查项,C++ 标准库版本:

strings /lib/aarch64-linux-gnu/libstdc++.so.6 | grep GLIBCXX | tail -n 5

如果升级成功,会看到GLIBCXX_3.4.28GLIBCXX_3.4.29这一串新版本符号,说明 C++ 程序需要的 GLIBCXX 3.4.26 肯定能满足。

第三个检查项,核心系统命令是否还能正常运行:

sudo -V python3 --version apt --version git --version

这些命令分别代表不同层面的依赖:sudo 依赖 PAM(认证库)、python3 依赖动态加载机制、apt 自己依赖很多压缩和网络库,它们全部正常说明基础用户态库没有出现破坏性变更。

第四个检查项,NVIDIA 核心组件是否正常:

nvidia-smi 2>/dev/null || echo "no nvidia-smi" # 对于 JetPack,更直接的检查是 CUDA 的编译器和 runtime nvcc --version

这几个命令如果都能正常输出,说明 CUDA 用户态库在升级后的 glibc 上运行没有异常。我在自己的 Xavier NX 上升级完,重新跑了一遍 TensorRT 的样例程序trtexec,程序启动、加载引擎、推理耗时跟升级前没有明显差异,这个会在后面第 5 节讲。

4. 常见故障与恢复实录

4.1 升级后 apt 崩了:多半是 libstdc++ 没跟上

有群友在聊天的时候问我,说他按命令升完了,glibc 版本也对了,但apt update直接报错,一执行就Segmentation fault。这种情况我排查下来,九成是只升了 libc6,没升 libstdc++6。

apt 命令本身是 C++ 程序,它链接了 libstdc++.so.6。如果 libstdc++6 还是 8.x 老版本,而系统某些组件(比如 python3-apt 模块)被升级后引用了新的 GLIBCXX 符号,apt 就会在启动阶段因为找不到GLIBCXX_3.4.26之类的符号而崩溃。解决办法很简单,把 libstdc++6 也按第 3 节的方式 dpkg 装上就行。

如果 dpkg 报"libstdc++6 被 apt 持有"之类的错误,先看是不是有残留的 focal 源,有的话删掉,再apt-get update恢复 bionic 状态,然后重新手动安装。

4.2 CUDA 或 TensorRT 报GLIBC_2.28 not found反而要高兴

有些人在升级前用 TensorRT 跑模型,报的是GLIBC_2.28 not found,升级完再跑还是报同样的错。这说明你的 Python 虚拟环境或者 conda 环境里,某些 wheel 是静态链接的旧版库文件,它们不依赖系统的 libc.so.6,而是自己打包了一个老的 libc。这种情况跟系统 glibc 版本已经没关系了,是 Python 环境自身的问题。

排查思路很简单:用ldd 你的程序或 .so 文件看它实际链接的/lib/aarch64-linux-gnu/libc.so.6指向哪里。如果发现它链接的是环境目录下的libc.so.6,说明这个环境是独立的一整套运行库,你需要重建虚拟环境,或者确认该 wheel 是否支持当前平台。如果 ldd 显示链接的是系统 libc,那升级完应该就好了。

另外,我升级完第一次运行 TensorRT 的时候遇到过Failed to allocate CUDA memory的一个错误码,当时以为 CUDA 被搞坏了,重新source /opt/nvidia/jetson-io/config.sh也没用。后来才发现是/usr/local/cuda/lib64下的一个自定义libcuda.so软链接被我之前手动改动过,指向了一个不存在的文件,跟 glibc 升级半毛钱关系都没有。这说明出问题先检查基础环境,别把所有锅都甩给刚升完的库。

4.3 串口救援:救回起不来的系统

如果升级操作失误,系统可能完全无法启动,SSH 也连不上。这种时候唯一能救命的,就是 3.1 节里说的串口调试线。

连接方式是这样的:用 USB-TTL 转接线把 Jetson 的 Debug UART 和电脑连起来,然后在电脑上执行:

sudo screen /dev/ttyUSB0 115200

波特率固定 115200。通电后串口会输出从 bootloader 到内核的完整启动日志。如果系统能进到 initramfs 或者 busybox 的 rescue shell,那还有操作空间,可以从网盘或者 U 盘挂载一下,把预先备份的旧版 libc6 deb 包放进去,用dpkg -i回滚恢复。如果内核直接 panic,或者 initramfs 阶段就挂掉,那就只能走重现刷镜像的路。

重刷镜像的方案是用 NVIDIA SDK Manager,选定对应硬件型号和 JetPack 版本,进恢复模式后刷回干净系统。这个操作会清空 rootfs 所有数据,所以我才会在第 3 节里苦口婆心劝大家先备份。另外提醒一句,Jetson 进恢复模式的方式是按住板子上的 Recovery 按键然后上电,电脑上用lsusb能看到一个 NVIDIA Corp 的设备。

根据我自己的经验,只要你严格按第 3 节的包列表和安装顺序执行,绝大多数情况下不会走到串口救援这一步,但这个知识储备必须有,因为升级 libc 本质上就是在换系统的地基,任何"大概率没事"的说法都不足以让你忽略备份和救援准备。

4.4--force参数用了之后,系统会不会留下安全隐患

这是一个值得展开的问题。我在群里分享了安装命令后,有人问:"你都 --force 了,那 dpkg 数据库里依赖信息不就乱掉了吗?以后升级别的包会不会出问题?"

答案是:dpkg 数据库确实会记录一些"未满足的依赖",因为 focal 的 libc6 声明依赖 libgcc-s1,而 bionic 的系统里装的还是 libgcc1,dpkg 数据库里这两个包没有形成正式的依赖关系。但这在实际运行层面并没有问题,因为 libgcc-s1 和 libgcc1 提供的是同一个共享库文件,运行时只关心/lib/aarch64-linux-gnu/libgcc_s.so.1这个文件存在且版本符合要求,根本不看 dpkg 数据库怎么记录。

你需要注意的不是这个历史依赖残留,而是以后用apt install时,APT 可能会发现系统存在"依赖未满足"的包,然后提示你apt --fix-broken install。这个时候千万要谨慎,因为--fix-broken有可能会试图把 libc6 回降到 bionic 版本的 2.27 来"修复"依赖。正确做法是:加入--no-download或者干脆用apt-get install -f的模拟模式先看看它想干什么,如果它尝试回弹 libc6,就手动干预,或者直接不加 -f,继续用 dpkg 管理这些包。

5. 升级后的实测表现与遗留注意事项

5.1 系统基础功能与 CUDA 组件稳定性

升级完成到现在,我在主力用的 Xavier NX 上跑了将近一周,每天都有持续的 CUDA 推理任务和 Python 服务在跑。系统层面,SSH、apt、Python 3.6、Git 这些基础工具全部正常,没有出现莫名的段错误或者库文件缺失。CUDA 10.2 和 TensorRT 8.x 这些 JetPack 自带核心组件也经受住了压力测试。

有一个比较有意思的验证点:我用升级后的系统编译了一个测试程序,显式检查 glibc 是否引入了对新内核系统调用(比如statx)的调用。glibc 2.31 在运行时遇到内核不支持的系统调用时,会静默回退到旧机制,不会直接报错。所以在 Jetson 的 4.9 内核上跑 glibc 2.31,兼容性是经过验证的,不用太担心新 libc 对旧内核的"嫌弃"。

5.2 新软件兼容性测试结果

我拿几个之前被卡死的场景做了回归测试:

  • 部署了一个基于 Python 3.8 的推理服务(代码引用了新版 PyTorch wheel),之前启动直接GLIBC_2.28 not found,升级后服务正常启动,前向推理结果与预期一致。
  • 跑了新版 Node.js 18 的 ARM 预编译包,node -v正常,一个基于 Express 的测试服务也能跑通。
  • 编译了一个用到 C++17 特性的小程序,确认GLIBCXX_3.4.26符号可以正常解析,运行无异常。

这些测试说明,这次定点升级确实能解除 Jetson 社区里"系统太老导致新软件装不上"的主要痛点。不过要注意,升级之后你获得的是运行新版软件的能力,不是让所有软件都能自动跑起来。有些软件本身还依赖其他高版本库,那是另一个层面的事情。

5.3 三个容易被忽视的隐患

第一,升级后不要随意运行apt upgrade,特别是如果你之前残留过 focal 源。虽然我已经让你删掉了临时源,但 APT 的缓存和 dpkg 状态里可能还留着 focal 包的信息,一次不经意的apt upgrade就可能导致系统装进一堆 focal 组件。我升级完给的命令是sudo apt-get update && sudo apt-get upgrade --dry-run,先看看它要动什么,确认没有异常再实际操作。

第二,conda 用户要特别注意。如果你在 Jetson 上使用 Anaconda 或 Miniconda,conda 环境内部自带的 libstdc++.so.6 可能是旧版本,系统级升级不会影响它。如果你在 conda 环境里运行新 C++ 程序还是报GLIBCXX not found,需要单独更新 conda 环境里的 libstdc++6:

conda install libstdcxx-ng

第三,系统里某些定制二进制(比如你自己或者公司之前编译的、依赖特定旧 libc 行为的程序)在升级后可能会表现异常。虽然 glibc 是向后兼容的,但安全补丁和实现细节的调整可能会影响极其老的程序对某些未定义行为的依赖。遇到这种程序,优先考虑用容器或者直接放一台旧版本系统上跑,而不是费劲把系统级 glibc 回滚。

5.4 如果以后想彻底解决版本问题,最终还是考虑迁移 JetPack 5.x

这次升级只是权宜之计,glibc 2.31 虽然能满足绝大多数软件的 GLIBC_2.28 要求,但毕竟还是停留在 Ubuntu 18.04 这个老旧体系上。如果你目前使用的 Jetson 硬件支持 JetPack 5.x(比如 Xavier NX、AGX Xavier、Orin 系列都支持),更彻底的方案是直接基于 JetPack 5.x 重建环境,它原生就是 Ubuntu 20.04 + glibc 2.31。但 Jetson Nano 和 TX2 这两个老型号就没办法了,它们倒在了 JetPack 4.6,想要跑新软件,这篇文章里的手动升级方案几乎是唯一的路。

根据我个人这几次折腾的经验,升级前一定把系统和数据备份做好,升级中保持耐心,升级后先跑验证清单再上业务。如果你也打算在自己那块板子上折腾这一下,我的建议是先拿一台没有业务负载的机器练手,把整个流程走熟了再动生产环境。毕竟 glibc 是系统最底层的地基,地基本身换了,上面每一层都值得多看一眼。真到哪个程序跑不起来的时候,顺着报错信息往上查,你会发现绝大多数问题都出在"谁的符号没找到"上面,而只要包列表和安装顺序和这篇文章一致,你踩坑的概率会小很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 3:22:13

VS Code多模型智能路由:GLM-5.3/DeepSeek/Kimi自动调度实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 3:17:15

PakePlus:3分钟把网页变成5MB的跨平台应用

PakePlus:3分钟把网页变成5MB的跨平台应用 【免费下载链接】PakePlus Turn any webpage/HTML/Vue/React and so on into desktop and mobile app under 5M with easy in few minutes. 轻松将任意网站/HTML/Vue/React等项目构建为轻量级(小于5M)多端桌面应用和手机应用仅需几分钟…

作者头像 李华
网站建设 2026/9/12 3:15:12

配电网重构中的辐射状拓扑约束:断线解环建模与Matlab实现

配电网重构做久了&#xff0c;你会发现最磨人的不是潮流方程&#xff0c;而是那条让人又爱又恨的辐射状拓扑约束。好多刚接触这个方向的同学拿着EI论文里的模型&#xff0c;第一反应都是“直接把目标函数和潮流约束抄进Matlab不就行了”&#xff0c;结果一跑就出孤岛、出环网&a…

作者头像 李华
网站建设 2026/9/12 3:13:20

双指针法解决三数之和问题:从O(n³)到O(n²)的优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华