4. 设备发现与资产登记

当 Jetson 设备从几台扩展到几十台、上百台时,运维的第一道门槛不是刷机,也不是部署模型,而是“我到底有哪些设备、它们现在在哪、叫什么、能不能连上”。设备发现与资产登记要解决的就是这个问题:把散落在局域网里的 Jetson 变成一份可查询、可追踪、可批量操作的清单。本节围绕四条互补的发现路径展开——主动扫描、mDNS 名称解析、DHCP 租约读取、批量信息采集,并说明它们各自适合什么场景、如何组合使用。

四条发现路径的定位与互补关系

没有任何单一方法能覆盖全部设备。主动扫描能发现“在线但没登记”的设备,但依赖 IP 可达;mDNS 依赖设备广播主机名,适合开发调试环境;DHCP 租约能拿到“曾经分配过地址”的历史记录,即使设备当前离线也能看到痕迹;批量采集则是在已知地址后,把序列号、型号、JetPack 版本等资产字段抓回来。四者的关系可以用下面的信号与数据流图表示:

局域网 192.168.1.0/24 Jetson 设备群 有线 / Wi-Fi 混合接入 ① 主动扫描 nmap / arp-scan ② mDNS 解析 avahi-browse / .local ③ DHCP 租约 dnsmasq.leases ④ 批量采集 SSH + 资产脚本 候选设备池 IP / 主机名 / MAC 去重与合并 资产登记表 CSV / SQLite 序列号·型号·版本 路径选择建议 • 首次盘点:DHCP 租约 + 主动扫描,快速拿到 IP/MAC 全集 • 开发调试:mDNS 直接按主机名访问,无需记 IP • 资产入库:对在线设备批量 SSH 采集序列号、型号、JetPack 版本 • 离线设备:仅 DHCP 租约可保留历史痕迹,用于追踪

主动扫描:先摸清网段里有什么

主动扫描适合“完全不知道有哪些设备”的初始阶段。最直接的方式是用 nmap 对目标网段做 ping 扫描,再对存活主机做端口探测。Jetson 默认开启 SSH(22 端口),因此可以用 22 端口作为筛选条件:

# 第一步:发现存活主机
nmap -sn 192.168.1.0/24 -oG - | awk '/Up$/{print $2}'

# 第二步:筛选出开放 22 端口的 Jetson 候选
nmap -p 22 --open 192.168.1.0/24 -oG jetson_scan.gnmap

# 第三步:从结果中提取 IP 列表
grep "22/open" jetson_scan.gnmap | awk '{print $2}' > candidates.txt

如果局域网内设备数量多、扫描耗时较长,可以改用 arp-scan,它基于 ARP 协议,速度更快,且能直接拿到 MAC 地址,便于后续与 DHCP 租约做关联:

sudo arp-scan --interface=eth0 --localnet

扫描结果中需要重点关注三类信息:IP 地址、MAC 地址、开放端口。MAC 地址是设备的物理标识,即使 IP 变化也能追踪;开放端口则帮助判断设备角色,例如同时开放 22 和 8888 的可能是运行 Jupyter 的开发机。需要注意的是,主动扫描只能发现“当前在线且允许 ICMP/ARP 响应”的设备,离线设备不会出现在结果中。

mDNS:用主机名代替 IP

Jetson 出厂镜像默认启用 Avahi,主机名通常形如 nvidia-desktop.local 或 jetson-orin.local。mDNS 的价值在于:设备 IP 由 DHCP 动态分配时,你仍然可以用固定主机名访问,不必每次查 IP。在 Ubuntu 主机上安装 avahi-utils 后,可以这样浏览局域网内的 mDNS 服务:

# 浏览所有 mDNS 服务
avahi-browse -a -t

# 只浏览 SSH 服务
avahi-browse -r _ssh._tcp -t

# 解析指定主机名
avahi-resolve -n jetson-orin.local

mDNS 的局限也很明显:它依赖设备主动广播,如果设备关机、mDNS 服务未启动,或网络隔离了组播流量(例如跨 VLAN),就无法解析。因此 mDNS 更适合开发调试环境,而不是大规模生产运维的唯一手段。

DHCP 租约:离线设备的历史档案

如果局域网由一台 Linux 网关或路由器负责 DHCP,租约文件就是一份天然的设备分配记录。以 dnsmasq 为例,租约文件通常位于 /var/lib/misc/dnsmasq.leases,每行格式为:

# 格式:过期时间戳  MAC地址  IP地址  主机名  客户端ID
1718000000 48:b0:2d:aa:bb:cc 192.168.1.101 jetson-orin-01 01:48:b0:2d:aa:bb:cc
1718003600 48:b0:2d:aa:bb:dd 192.168.1.102 jetson-nano-02 01:48:b0:2d:aa:bb:dd

读取租约后,可以按 MAC 地址去重,得到一份“曾经接入过网络”的设备清单。即使设备当前离线,租约仍然保留,直到过期或被清理。这对于追踪“某台设备最后一次出现是什么时候”非常有用。如果使用 isc-dhcp-server,租约文件在 /var/lib/dhcp/dhcpd.leases,格式略有不同,但同样包含 MAC、IP、主机名和租约起止时间。

批量信息采集:把 IP 变成资产字段

拿到候选 IP 列表后,下一步是批量登录并采集资产信息。核心字段包括:序列号、型号、JetPack/L4T 版本、内核版本、主机名、MAC 地址。这些信息可以通过一条组合命令在每台设备上执行:

#!/bin/bash
# collect_asset.sh —— 在每台 Jetson 上执行
echo "hostname: $(hostname)"
echo "serial: $(cat /proc/device-tree/serial-number 2>/dev/null | tr -d '\0')"
echo "model: $(cat /proc/device-tree/model 2>/dev/null | tr -d '\0')"
echo "l4t: $(cat /etc/nv_tegra_release 2>/dev/null | head -1)"
echo "kernel: $(uname -r)"
echo "mac: $(cat /sys/class/net/eth0/address 2>/dev/null)"

在运维主机上,用 ssh 循环调用该脚本,并把输出汇总为 CSV:

#!/bin/bash
# batch_collect.sh —— 在运维主机上执行
echo "ip,hostname,serial,model,l4t,kernel,mac" > assets.csv
while read ip; do
  result=$(ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 \
    nvidia@$ip 'bash -s' < collect_asset.sh 2>/dev/null)
  if [ -n "$result" ]; then
    hostname=$(echo "$result" | grep '^hostname:' | cut -d' ' -f2)
    serial=$(echo "$result" | grep '^serial:' | cut -d' ' -f2)
    model=$(echo "$result" | grep '^model:' | cut -d' ' -f2-)
    l4t=$(echo "$result" | grep '^l4t:' | cut -d' ' -f2-)
    kernel=$(echo "$result" | grep '^kernel:' | cut -d' ' -f2)
    mac=$(echo "$result" | grep '^mac:' | cut -d' ' -f2)
    echo "$ip,$hostname,$serial,$model,$l4t,$kernel,$mac" >> assets.csv
  else
    echo "$ip,UNREACHABLE,,,,," >> assets.csv
  fi
done < candidates.txt

执行完成后,assets.csv 就是一份可直接使用的资产登记表。判断采集是否成功,可以看两个信号:一是 CSV 行数是否与候选 IP 数量一致;二是 serial 和 model 字段是否为空。如果某台设备 SSH 可达但序列号为空,通常说明 /proc/device-tree 路径不存在或权限不足,需要检查设备是否为 Jetson 原生系统。

建议把 assets.csv 导入 SQLite 或表格工具,并增加“最后发现时间”“备注”两列。每次扫描后做一次增量更新,而不是全量覆盖,这样可以保留设备的历史轨迹,便于排查“某台设备什么时候掉线”这类问题。

组合使用与常见问题

实际运维中,四条路径通常按以下顺序组合:先用 DHCP 租约拿到历史设备全集,再用主动扫描确认当前在线子集,然后用 mDNS 补充主机名映射,最后对在线设备批量采集资产字段。这样既不会遗漏离线设备,也不会把时间浪费在不可达的 IP 上。

常见问题包括:扫描结果里出现大量非 Jetson 设备(如打印机、摄像头),此时应结合 MAC 地址前缀过滤,NVIDIA 设备的 MAC 前缀通常属于特定厂商;mDNS 解析失败但 IP 可达,说明 Avahi 未启动,可登录设备执行 sudo systemctl status avahi-daemon 检查;批量采集时部分设备超时,应把 ConnectTimeout 设为 5 秒以内,避免单台设备拖慢整体进度。把这些判断逻辑固化到脚本里,设备发现与资产登记就能从一次性手工操作变成可重复执行的例行任务。