
前两天帮朋友排查一台二手Jetson Nano的部署问题现象是启动Python脚本后直接报undefined symbol: cudnnCreate换了几个PyTorch版本都救不回来。我连代码都没细看先到终端敲了一条cat /etc/nv_tegra_release看到REVISION: 2.2心里就有数了——这台板子刷的是JetPack 4.2时代的L4T系统而朋友在PC上下载的PyTorch轮子是按较新JetPack版本的cuDNN编译的符号对不上自然一跑就炸。这其实不是个例。Jetson Nano玩的人虽多但不少教程开头都默认你已经知道板子上跑的是哪一版JetPack。实际上JetPack版本决定了你能装哪版CUDA、哪版cuDNN、哪版TensorRT也决定了哪些预编译容器可以直接拉取运行。本文就把查询JetPack版本的三种方法、版本之间的对应关系以及官网匹配指南一次讲清楚。适合刚拿到板子的新手也适合手里有不少旧板子、需要按项目环境做版本归档的老手。1. 为什么“查JetPack版本”比记住“我装的Ubuntu 18.04”有用得多1.1 JetPack不是“一个软件”而是“一套全家桶”很多人第一次接触Jetson平台时会把JetPack理解成类似Photoshop那种“安装一个大软件”的东西但实际完全不是。NVIDIA JetPack SDK是一整套开发套件的总称里面至少包含四层内容底层是L4TLinux for Tegra也就是板子的BSP负责内核、bootloader、设备树、根文件系统之上是CUDA Toolkit提供GPU并行计算工具链再往上是cuDNN、TensorRT这类加速库最后还有多媒体API、OpenCV、VPI等针对视觉场景的组件。所以当你问“我的板子JetPack版本是多少”时实际上是在问这一整套SDK的基线版本。底层L4T版本决定了内核和驱动行为上层库版本决定了你能跑什么框架、能加载什么模型。这也解释了为什么Ubuntu系统版本不能替代JetPack版本。有人在群里说“我板子上是Ubuntu 20.04能不能装这个容器”结果翻车了。Ubuntu版本只是根文件系统的一部分真正决定软件生态兼容性的是L4T和JetPack版本号。1.2 版本不匹配时实际报错长什么样版本不匹配的报错不总是很直白常见的有这几种安装PyTorch时提示“no matching distribution”或者“Could not find a version that satisfies the requirement”运行TensorRT程序时提示Cannot deserialize plan file说明引擎文件和当前TensorRT版本不一致拉取Docker镜像时提示manifest格式不对因为镜像tag里写的L4T版本和当前板子不匹配编译带GPU加速的OpenCV时链接阶段找不到libcudnn.so或libnvinfer.so更隐蔽的是程序能跑但性能异常低某些算子回退到CPU执行。这些问题的根源多数不是代码写错了而是你的程序或预编译包是按照另一套JetPack环境构建的。尤其Jetson平台不像普通PC那样可以随便升级显卡驱动L4T、CUDA、cuDNN、TensorRT都是联动发布的。手动单独替换其中一个库很容易破坏整条依赖链。1.3 这篇文章适合谁如果你是这几种情况这篇文章基本就是给你写的刚入手Jetson Nano正要刷系统不知道该选哪一版JetPack拿到二手板子跑起来才发现各种库版本诡异想先搞清楚现状项目要从Xavier/Orin迁移到Nano需要确认软件版本能不能对齐买了Nano但照着新教程装包发现失败率奇高想系统地排查环境。读完之后你会拿到一套明确的命令组合、一张常用版本对应表以及一份可以直接参考的官网翻查路径。2. 终端三板斧先把L4T和JetPack版本号从系统里捞出来2.1 第一招cat /etc/nv_tegra_release这是整个Jetson环境查询里最值得记住的一条命令。L4T系统装好后会在/etc目录下放一个名为nv_tegra_release的文本文件记录当前刷入的BSP基线。在JetPack 4.6.1的板子上输出大致长这样$ cat /etc/nv_tegra_release # R32 (release), REVISION: 6.1, GCID: 23942481, BOARD: t210ref, EABI: aarch64, DATE: Mon Jun 21 15:38:26 UTC 2021这一行信息量很大R32表示L4T的release line是R32系列REVISION: 6.1表示当前L4T具体版本是R32.6.1BOARD: t210ref表示这是Tegra 210参考板Jetson Nano/MX系列模块都基于这个硬件平台DATE是BSP打包日期可以用来粗略判断是否被重新刷过。拿到L4T版本R32.6.1之后对照NVIDIA官方版本关系就能映射到JetPack版本。比如R32.6.1对应JetPack 4.6和4.6.1R32.7.3对应JetPack 4.6.4。这里有一个高频误区很多人看到REVISION: 6.1就以为板子是JetPack 6.1这是不对的后面我会专门展开讲。我在多台板子上试过这条命令在所有官方L4T系统里都存在只要rootfs没被过度精简基本都能出结果。所以它可以作为“有没有装过正宗JetPack”的第一判断依据。2.2 第二招dpkg -l 和 uname -a 交叉验证单看release文件还不够最好再结合包管理器和内核版本做交叉验证。dpkg -l | grep nvidia-jetpackJetPack作为Debian包安装时会有一个名为nvidia-jetpack的元包版本号就带着JetPack版本信息。在JetPack 4.6.1板子上输出类似ii nvidia-jetpack 4.6.1-r32.6.1-... arm64 NVIDIA Jetpack注意版本字段里同时出现了4.6.1和r32.6.1这两段分别对应JetPack版本和L4T版本正好可以和/etc/nv_tegra_release对上。再配合内核版本uname -aJetPack 4.x对应的L4T R32系列内核是4.9版本输出里会出现4.9.253-tegra这样的字符串。JetPack 5.x/6.x对应的L4T R35/R36系列内核则升级到5.10或更高。仅凭内核大版本也能快速排除掉一大半错误判断。另一个有用信息是根文件系统版本cat /etc/os-releaseJetPack 4.x基于Ubuntu 18.04JetPack 5.x基于Ubuntu 20.04JetPack 6.x基于Ubuntu 22.04。如果os-release里显示的系统版本和你说听的JetPack版本对不上那就要警惕了。2.3 第三招一键汇总脚本如果你不想每次敲五六条命令可以直接把这些命令写进一个脚本里以后在任何Jetson板子上都能用。我在实际维护板子时习惯把下面这个脚本存成nvcheck.sh#!/bin/bash echo L4T baseline cat /etc/nv_tegra_release 2/dev/null || echo nv_tegra_release not found echo Kernel / OS uname -a grep -E ^(ID|VERSION_ID) /etc/os-release echo JetPack metapackage dpkg -l | grep -E nvidia-jetpack || echo nvidia-jetpack not found echo CUDA export PATH/usr/local/cuda/bin:$PATH nvcc --version 2/dev/null || /usr/local/cuda/bin/nvcc --version 2/dev/null || echo nvcc not found echo cuDNN dpkg -l | grep -E libcudnn || echo cuDNN package not found echo TensorRT dpkg -l | grep -E libnvinfer || echo TensorRT package not found /usr/src/tensorrt/bin/trtexec --version 2/dev/null || echo trtexec not found把内容保存后给执行权限chmod x nvcheck.sh ./nvcheck.sh运行一次就能拿到板子当前L4T版本、内核、CUDA、cuDNN、TensorRT组件全貌。后续无论排查问题还是做环境交接这份输出都是很重要的参考。2.4 可选用jetson_release一键看汇总如果你不想亲自写脚本也有一个社区工具可以代劳名字叫jetson-stats。它封装了各种Jetson板卡的查询逻辑安装后直接运行jetson_release就能输出一份很友好的环境汇总。安装方式一般是sudo -H pip3 install -U jetson-stats装完后执行jetson_release输出大致是这样Platform: NVIDIA Jetson Nano JetPack: 4.6.1 L4T: 32.6.1 Ubuntu: 18.04.6 LTS Kernel: 4.9.253-tegra CUDA: 10.2.89 cuDNN: 8.2.1.32 TensorRT: 8.2.1.8 OpenCV: 4.1.1这份输出非常直观适合给人汇报环境信息时使用。不过需要说明的是jetson-stats是社区维护的工具不是NVIDIA官方随镜像预装的。它读取信息的来源本质上还是前面提到的那些系统文件和dpkg记录所以如果你手头有板子但没法联网装这个工具用命令行查询也完全够用。3. 把组件包摊开CUDA、cuDNN、TensorRT版本逐个核对有时候只知道JetPack整体版本还不够。比如你想用某个PyTorch预编译包对方文档里可能明确写着“适用于JetPack 4.6 / CUDA 10.2 / cuDNN 8.2”那就需要进一步确认单个组件的版本是否满足要求。3.1 JetPack在dpkg里的安装形态JetPack整套环境并不像普通PC上装个NVIDIA驱动那样只有一个包。它会拆成一组nvidia-l4t-*的底层包以及若干上层库包。元包nvidia-jetpack只负责声明依赖关系真正干活的是下面这些具体包。可以先用这条命令看看板子上装了哪些NVIDIA底层组件dpkg -l | grep nvidia-l4t | head -30输出里会看到类似nvidia-l4t-core、nvidia-l4t-cuda、nvidia-l4t-multimedia、nvidia-l4t-bootloader这样的包。如果这些底层包版本都不一致说明系统可能被奇怪的升级方式动过后患比较大。如果你用SDK Manager刷完镜像后又在板子上手动apt upgrade过某些组件的版本会和初始JetPack版本产生漂移。这也是为什么我建议先把组件版本逐项核对清楚而不只是满足于“JetPack写的是4.6.1”这样一个笼统答案。3.2 CUDA版本怎么查才不被迷惑CUDA版本查询有个经典误区。很多PC玩家习惯用nvidia-smi看CUDA Version在Jetson板子上这一招会坑人。nvidia-smi显示的准确来说是当前GPU驱动所支持的最高CUDA版本不是你当前开发环境里实际安装的CUDA Toolkit版本。在JetPack 4.6板子上驱动是470系列nvidia-smi输出里会显示----------------------------------------------------------------------------- | NVIDIA-SMI 470.104.01 Driver Version: 470.104.01 CUDA Version: 11.4 | -----------------------------------------------------------------------------但实际JetPack 4.6捆绑的CUDA Toolkit是10.2。如果你只看了nvidia-smi误以为板子上跑的是CUDA 11.4后面装包、编译大概率会踩坑。想确认实际可用的CUDA编译工具链要看nvccexport PATH/usr/local/cuda/bin:$PATH nvcc --versionJetPack 4.6板子上输出类似nvcc: NVIDIA (R) Cuda compiler driver Cuda compilation tools, release 10.2, V10.2.89这里写的release 10.2才是你写CUDA代码、编译PyTorch扩展时真正会用到的CUDA版本。3.3 cuDNN和TensorRT对应的包名cuDNN在Jetson系统里通常是libcudnn8这个包查询命令dpkg -l | grep cudnnJetPack 4.6.1板子上会看到类似ii libcudnn8 8.2.1.32-1cuda10.2 arm64 NVIDIA cuDNNTensorRT的查询稍微隐蔽一点因为它的Debian包名用的是nvinfer也就是NVIDIA Inference的缩写。查询命令dpkg -l | grep nvinfer输出类似ii libnvinfer8 8.2.1.8-1cuda10.2 arm64 TensorRT runtime ii libnvinfer-plugin8 8.2.1.8-1cuda10.2 arm64 TensorRT plugins如果只装了runtime没装dev包编译TensorRT插件时会找不到头文件。所以在核对环境时最好把带-dev后缀的包也一起看一遍dpkg -l | grep -E libnvinfer|libcudnn | grep dev很多人在板子上编译TensorRT相关工程报“找不到NvInfer.h”一查就是dev包缺失。3.4 用工具自检trtexec、Python绑定和OpenCV除了看dpkg记录还可以直接运行工具来二次确认。TensorRT一般会附带一个性能测试工具trtexec位置在/usr/src/tensorrt/bin/下/usr/src/tensorrt/bin/trtexec --version如果TensorRT安装正常输出里会带有构建版本信息。Python环境下的验证更直观python3 -c import tensorrt as trt; print(trt.__version__) python3 -c import cv2; print(cv2.__version__)不过要提醒一下JetPack 4.6镜像里预装的OpenCV是4.1.1即使版本较老也不代表系统有问题。OpenCV在JetPack里的更新节奏并不跟着大版本走所以不要用OpenCV版本反推JetPack版本。4. 刷机之前怎么确认镜像版本SDK Manager与镜像文件名的门道前面几种方法都要求板子能正常开机。但有一种很常见的情况是板子还没刷机或者刷完不开机甚至你拿到的只是一张写好了系统的SD卡。这时候又该怎么确认版本4.1 SDK Manager你选的版本就是你要刷的版本NVIDIA官方刷机工具叫SDK Manager。它的工作流是你在电脑上选择要安装的JetPack版本然后SDK Manager会把这个版本对应的BSP、根文件系统、CUDA、TensorRT等组件打包下载下来再烧录或安装在板子上。所以用SDK Manager确定版本的方法很简单在“Step 01”的JetPack Version下拉框里你选中哪一版之后烧进板子里的就是哪一版。它会同时显示目标硬件型号和JetPack版本比如Jetson Nano Developer KitJetPack 4.6.4。这一步别随便选尤其是手头有多个型号板子的人选错版本很容易烧出和硬件不匹配的镜像。SDK Manager还有一个好处就是下载页会展示当前JetPack版本对应的组件组成。刷机前把这张组件列表截图存档之后再和板上实际dpkg记录做对比就能知道系统是否被后续改动过。4.2 从镜像文件名和MD5校验判断不少人喜欢直接在官网下载SD卡镜像然后用Etcher之类的工具写入SD卡。这时候版本信息其实写在文件名里。常见的镜像文件名会有两类命名风格包含JetPack版本比如Jetson-Nano-JetPack-4.6.4-SD-Card-Image.zip包含L4T版本比如可以看到r32.7.3这样的字段。如果是BSP源码包或驱动包命名更像这样Tegra_Linux_R32.6.1_aarch64.tbz2文件名里的R32.6.1就是L4T版本对应JetPack 4.6.1。如果文件名看不出来可以把压缩包解压在里面的Linux_for_Tegra目录下找readme或版本说明文件通常第一页就写着L4T版本号。另外官网下载页都会给每个镜像提供MD5校验值。我建议下载完后先校验一下再做镜像写入。别小看这一步很多刷完板子起不来的问题根源就是镜像下载不完整。4.3 板子开不了机或拿到旧卡时的处理如果板子已经开不了机或者你从别人那里拿到一张不知道内容的SD卡也有办法绕过开机直接查。把SD卡用读卡器插到任意一台Linux电脑上挂载它的根文件系统分区然后直接读取sudo cat /media/ubuntu/rootfs/etc/nv_tegra_release只要分区没有被破坏/etc/nv_tegra_release文件就在那里L4T版本一目了然。如果板子完全空板没有任何系统那就只能根据板号做选择了。比如Jetson Nano和Jetson Orin Nano是两款不同的硬件前者最高支持JetPack 4.6.4后者原生支持JetPack 5.x/6.x。这一点在刷机前一定要分清。还有一个土办法很多老玩家会做拿到板子后先用cat /proc/device-tree/model确认硬件型号。输出类似NVIDIA Jetson Nano Developer Kit或NVIDIA Jetson Orin Nano Developer Kit刷机前记下这个硬件型号再对照官网支持矩阵选JetPack版本基本不会出大错。5. 官网匹配指南JetPack版本号到L4T/CUDA/TensorRT的翻译表与操作步骤5.1 两套版本体系JetPack 4.x背后其实是L4T R32.x很多第一次接触Jetson的人会被版本号搞晕原因是平台上存在两套并行的版本体系。JetPack版本是NVIDIA面向开发者发布的SDK版本号比如4.6.1、5.1.2L4T版本是底层BSP的版本号格式是R32.6.1、R35.1.0这样的形式。两者不是简单的“JetPack 4对应L4T 4”而是有一定的映射规则。规律大概是JetPack 4.x对应L4T R32.xJetPack 5.x对应L4T R35.xJetPack 6.x对应L4T R36.x。很多Docker镜像和容器tag用的是L4T版本号比如nvcr.io/nvidia/l4t-pytorch:r32.6.1-pth1.10-py3。如果你只记住了JetPack版本是4.6.1却不知道对应的L4T是R32.6.1很可能在拉容器时找不到合适的tag。5.2 常用JetPack版本与组件对照表下面这份对照表是我在平时刷机和维护板子过程中整理出来的主要覆盖Jetson Nano生命周期内会碰到的版本。由于NVIDIA偶尔会针对老版本推送补丁个别组件的小版本可能会有变化刷机前最好还是以官网Release Notes为准。JetPack版本L4T版本UbuntuCUDAcuDNNTensorRT主要适配板卡JetPack 4.2.xR32.2.x18.0410.07.35.0Nano、TX2JetPack 4.3R32.3.x18.0410.07.67.0Nano、XavierJetPack 4.4R32.4.218.0410.28.07.1.3Nano、Xavier NXJetPack 4.5R32.5.018.0410.28.07.1.3Nano、Xavier NXJetPack 4.6/4.6.1R32.6.118.0410.28.2.18.2.1Nano、Xavier NXJetPack 4.6.4R32.7.318.0410.28.2.18.2.1Nano、TX2、Xavier长期维护JetPack 5.0R35.1.020.0411.48.4.18.5.2Xavier NX、AGX OrinJetPack 5.1.2R35.4.120.0411.48.6.08.5.3Xavier NX、Orin系列JetPack 6.0R36.3.022.0412.28.9.48.6.3Orin系列对Jetson Nano来说最需要关注的是前几行。如果你要追求最好的TensorRT 8系列支持和长期维护包JetPack 4.6.4是Nano比较稳妥的终点版本。5.3 在官方Archive页面找数据的操作路径官网匹配的关键页面是NVIDIA嵌入式平台的JetPack Archive。这个页面会列出所有历史JetPack版本操作路径大概如下打开NVIDIA开发者网站的JetPack Archive页面地址是developer.nvidia.com/embedded/jetpack-archive找到你关心的JetPack版本点击进入详情在详情页里找到“Release Notes”查看组件版本表里面会写明该版本对应的L4T、CUDA、cuDNN、TensorRT、OpenCV等版本看“Supported Platforms”确认你的板卡型号在当前版本的支持列表里如果还需要下载镜像或BSP在“Driver Package (BSP)”和“Sample Root File System”区域下载对应文件文件名里通常带L4T版本号。举个例子你手上是Jetson Nano想用TensorRT 8.x做推理加速那就应该找JetPack 4.6或4.6.4因为4.4/4.5里TensorRT还是7.1.3。如果你想编译某个老版本项目项目代码里写明了需要TensorRT 7.1.3那反而应该选择JetPack 4.5。5.4 Jetson Nano能升到哪个版本平台生命周期是硬约束市面上有一些较新的教程标题写着“在Jetson上部署xxx”但实操时用的是Xavier NX或Orin。NPU、GPU架构都不一样不能直接照搬。Jetson Nano包括4GB和2GB版本属于上一代平台官方支持的最高JetPack版本是4.6.4对应L4T R32.7.3。换句话说Nano官方不支持JetPack 5.x和6.x。如果你看到某个工具明确要求JetPack 5.0以上就应该意识到Nano不是目标平台要么找老版本替代方案要么换Orin Nano这类新硬件。这里也要区分一下“Jetson Nano”和“Jetson Orin Nano”。Orin Nano是后来推出的新一代产品支持JetPack 5.x/6.x外形相似但性能与生态完全不同。刷机时如果选错镜像照片可能根本起不来。6. 排查实录版本查询中最容易翻车的几个判断点6.1 把REVISION 6.1当成了JetPack 6.1这是我见过最多、也最害人的一个坑。/etc/nv_tegra_release输出是# R32 (release), REVISION: 6.1, ...有人一看到6.1立刻拿着“JetPack 6.1”去搜教程结果找回来的全是JetPack 6.0/6.0 DP的刷机资料下载的BSP完全不匹配。这里必须反复强调release文件里写的是L4T版本不是JetPack版本。R32.6.1对应的是JetPack 4.6/4.6.1而不是什么JetPack 6.1。正确的翻译方法是去查官方对照表或者用dpkg -l | grep nvidia-jetpack看元包版本。更极端的例子是JetPack 4.6.4它的L4T版本是R32.7.3。如果不看表根本猜不到“R32.7.3”这个底层版本号对应的居然是JetPack 4.6.4。6.2 nvidia-smi显示CUDA 11.4实际工具链却是10.2这是另一个高频误解。Jetson设备上的nvidia-smi虽然能正常输出驱动信息但它显示的CUDA Version代表的是驱动支持的CUDA上限而不是当前板子安装的CUDA Toolkit版本。在JetPack 4.6上驱动是470分支支持CUDA 11.4但板子实际捆绑的CUDA Toolkit是10.2。所以你会看到nvidia-smi 显示 CUDA Version: 11.4 nvcc --version 显示 release 10.2两者同时存在并不矛盾。真正编译代码时以nvcc的版本为准。需要引入的CUDA运行库也要看/usr/local/cuda目录下的具体版本。所以我的建议是在Jetson板子上不要用nvidia-smi判断JetPack版本也不要拿它判断CUDA可用版本。想看CUDA直接看nvcc --version和dpkg -l | grep cuda的输出。6.3 dpkg查不到nvidia-jetpack元包有时候输入dpkg -l | grep nvidia-jetpack回显是空的。这不一定是系统没装JetPack可能是两种情况第一种你刷的是厂商定制镜像或者是别人精简过的rootfs把元包相关描述移除了但底层组件还在。这时候可以查nvidia-l4t-core或libcudnn这类具体包一般都能找到版本线索。第二种系统是用SDK Manager只烧了BSP和根文件系统没有在后续步骤里安装完整的运行时组件。这种板子能开机但你没有CUDA、TensorRT环境查询结果自然为空。判断标准是看/etc/nv_tegra_release文件是否存在存在就只能说明L4T在JetPack上层组件有没有还得单独确认。6.4 我的建议排查顺序如果你面对一台陌生的Jetson板子又想知道自己该按哪个JetPack版本去匹配软件我的建议顺序是先跑cat /etc/nv_tegra_release确定L4T基线用上面的对照表或官网Release Notes把L4T翻译回JetPack版本再跑nvcc --version和dpkg -l | grep -E libcudnn|libnvinfer逐项确认CUDA、cuDNN、TensorRT版本是否和JetPack版本匹配如果需要用容器或预编译库记录下L4T版本去镜像仓库搜索对应tag发现组件版本对不上时不要单独手动升级某个库除非你很清楚后果。更稳妥的做法是用SDK Manager重新刷一套完整镜像。这套顺序看起来很基础但我实际排查过不少环境问题最后都能落到“版本不对齐”这一个根因上。最后再分享一个有点土但很管用的习惯每刷完一批板子先执行一遍nvcheck.sh把输出重定向到$HOME/jetpack_info_$(hostname).txt存档。下次客户或同事问“你这板子是什么环境”直接把这个文件发过去比任何描述都准。版本查询这事本身不难难的是每次靠猜猜来猜去迟早会踩到REVISION 6.1那个坑。