暗色模式

Linux 硬件信息采集:从 lscpu 到 dmidecode 识别物理机与虚拟机

技术教程
2026-09-16
8
0
本文要点
  • Linux 下的硬件信息有三条来源/proc(内核导出的文本)、/sys(设备模型,一个文件一个属性)、用户态工具(lscpu/lsblk/lspci/dmidecode),三者经常互相矛盾,得知道该信谁
  • 识别虚拟机最快的三条命令:systemd-detect-virt 直接输出 kvmdmesg | grep -i "Hypervisor detected" 有开机记录、/proc/cpuinfo 的 flags 里带 hypervisor 标志
  • dmidecode 必须 root,真实原因是 /sys/firmware/dmi/tables/ 下那两个文件权限是 0400;而 /sys/devices/virtual/dmi/id/0444 世界可读——两者读的是同一份 SMBIOS 数据,普通用户走后者就行
  • ⚠️ lsblkROTA 列在虚拟机上不可信:virtio 磁盘上报的 ROTA=1 并不代表它是机械盘,TRAN 列也是空的
  • ⚠️ SMBIOS 里全是模拟数据:本机 dmidecode 报处理器 Max Speed: 2000 MHz,而 CPUID 报的型号是 2.60GHz 的 Xeon Platinum 8272CL——性能相关问题信 lscpu,别信 dmidecode
  • 缓存和 NUMA 拓扑是宿主机的:1 核的虚拟机报告了 35.8 MiB 的 L3(8272CL 的 L3 正是 35.75 MB),别拿它推算自己的资源
  • 虚拟化还会渗透到设备命名:网卡驱动是 virtio_netethtool eth0Speed: Unknown!、USB 总线上挂着一块 QEMU USB Tablet

Linux 硬件信息采集:从 lscpu 到 dmidecode 识别物理机与虚拟机

买机器前想知道配置够不够、迁移前想确认目标机硬件、排障时想知道驱动有没有绑上——这些都叫「采集硬件信息」。麻烦的地方在于同一份硬件,Linux 会给你三套说法,而且它们在虚拟化环境下经常对不上。

这篇文章在一台 1 核 2G 的 NAT 小机(Ubuntu 22.04、内核 5.15.0-30-generic)上把三条路径都走一遍,顺带回答一个很实用的问题:怎么判断你手里这台到底是物理机还是虚拟机。答案不止一条命令,而是五组互相印证的证据。

硬件信息的三条来源

来源形态特点
/proc内核态实时导出的文本反映当前内核看到的硬件,如 /proc/cpuinfo/proc/meminfo
/sys设备模型,一个文件一个属性结构最规整,权限粒度细,适合脚本读取
用户态工具lscpu/lsmem/lsblk/lspci/lsusb/dmidecode把上面两者整理成人话,但各自有自己的数据源和盲区

关键认知是:这三条路径的信息源并不相同lscpu 的数据来自 CPUID 指令和 /proc/cpuinfodmidecode 的数据来自 BIOS/UEFI 填好的 SMBIOS 表;lsblk 来自内核块设备层和 udev 数据库。搞混了就会得出错误结论——后面第六节有个现成的例子。

CPU:lscpu 把 /proc/cpuinfo 整理成人话

lscpu 输出虚拟化厂商为 KVM,systemd-detect-virt 报 kvm,dmesg 里留有 Hypervisor detected 开机记录

lscpu | grep -E "Model name|^CPU\(s\)|Thread\(s\) per core|Core\(s\) per socket|Socket\(s\)|Hypervisor vendor|Virtualization type"; echo "--- 虚拟机检测:"; systemd-detect-virt; dmesg | grep -i "Hypervisor detected"
CPU(s):                          1
Model name:                      Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz
Thread(s) per core:              1
Core(s) per socket:              1
Socket(s):                       1
Hypervisor vendor:               KVM
Virtualization type:             full
--- 虚拟机检测:
kvm
[    0.000000] Hypervisor detected: KVM

lscpu 不带参数输出很长,这里挑了几行关键的。几个读法:

  • Socket(s) × Core(s) per socket × Thread(s) per core = 总 vCPU 数1 × 1 × 1 = 1。反过来,如果你看到 Socket(s): 1Core(s) per socket: 8Thread(s) per core: 2,那就是 16 个逻辑 CPU。这比直接看 CPU(s): 更能说明机器的物理形态。
  • Hypervisor vendor: KVM:这一行是 CPUID 直接告诉你的,只有当 Linux 跑在 hypervisor 之上才会出现。物理机上这一行根本不存在——它不是一个显示为 none 的字段,而是整个字段都没有。这是判断虚拟机的第一手证据。
  • Virtualization type: full:全虚拟化。与之对应的 para 表示半虚拟化。

顺便看几个容易被忽略的字段:

lscpu | grep -E "Address sizes|BogoMIPS|CPU family|^Model:|Stepping|L1d|L2 |L3 |NUMA"
Address sizes:                   46 bits physical, 48 bits virtual
CPU family:                      6
Model:                           85
Stepping:                        7
BogoMIPS:                        5187.81
L1d cache:                       32 KiB (1 instance)
L2 cache:                        1 MiB (1 instance)
L3 cache:                       35.8 MiB (1 instance)
NUMA node(s):                    1
NUMA node0 CPU(s):               0
  • Address sizes: 46 bits physical:物理地址总线 46 位,理论上限 64TB 内存。虚拟机里这个值来自宿主机 CPU,和你能买多少内存无关。
  • CPU family / Model / Stepping6 / 85 / 7 是识别 CPU 微架构的硬指纹,比型号字符串更可靠(云厂商经常改写型号字符串)。
  • BogoMIPS:内核启动时校准出来的「空转速度」,只适合横向对比同型号机器,不是性能指标。
  • ⚠️ L3 cache: 35.8 MiB 值得单独说:这台虚拟机只有 1 个 vCPU,却报告了 35.8 MiB 的 L3。Xeon Platinum 8272CL 的 L3 正好是 35.75 MB——KVM 把宿主机的缓存拓扑原样透传了进来。所以虚拟机里的缓存大小和 NUMA 拓扑反映的是宿主机,别拿它推算自己的资源边界。

还有个常被漏掉的证据藏在 flags 里:

grep -o -m1 "hypervisor.*" /proc/cpuinfo | cut -c1-60
hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single

hypervisor 这个 CPU 标志位是内核在检测到 CPUID 的 hypervisor present 位后加进去的,物理机上不会有。它和 lscpuHypervisor vendor 同源,但 grep 一下更快——写脚本时尤其方便。

最后别忘了 lscpu 还会列出漏洞缓解状态

lscpu | grep -A20 "^Vulnerability"
Vulnerability Itlb multihit:     Not affected
Vulnerability L1tf:              Not affected
Vulnerability Mds:               Not affected
Vulnerability Meltdown:          Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp
Vulnerability Spectre v1:        Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:        Mitigation; Enhanced IBRS, IBPB conditional, RSB filling
Vulnerability Tsx async abort:   Mitigation; TSX disabled

Not affected 说明该 CPU 型号硬件上不受影响,Mitigation 说明靠软件手段缓解(通常有性能代价)。虚拟机上这份列表还受宿主机微码和 KVM 配置影响——如果你在排查「为什么这台机器比那台慢」,这一节值得对照着看。CPU 侧的深度剖析可以看 perf 性能剖析:从 perf stat 到采样报告定位 CPU 热点

内存:free、lsmem 与 meminfo 三角验证

free -h; echo "--- lsmem:"; lsmem; echo "--- meminfo:"; grep -E "MemTotal|MemAvailable|SwapTotal" /proc/meminfo
               total        used        free      shared  buff/cache   available
Mem:           1.9Gi       184Mi       218Mi       0.0Ki       1.5Gi       1.6Gi
Swap:             0B          0B          0B
--- lsmem:
RANGE                                 SIZE  STATE REMOVABLE BLOCK
0x0000000000000000-0x000000007fffffff   2G online       yes  0-15

Memory block size:       128M
Total online memory:       2G
Total offline memory:      0B
--- meminfo:
MemTotal:        2025116 kB
MemAvailable:    1641164 kB
SwapTotal:             0 kB

三处数字需要对齐看:

  • free1.9Gilsmem2Gmeminfo2025116 kB这三个不矛盾2025116 kB ÷ 1024 ÷ 1024 ≈ 1.93 GiBfree -h 按 GiB 显示并保留一位小数就是 1.9Gi,而 lsmem 按内存块向上取整到 2G。报数时想精确就用 kB 值。
  • MemAvailable: 1641164 kB 才是「还能用多少」free 列里的 218Mi 只是完全没被动过的内存。Linux 会把空闲内存拿去做页缓存(buff/cache 高达 1.5Gi),这部分随时可以回收,所以真实可用量看 available
  • Memory block size: 128M / REMOVABLE: yes:内存被切成 16 个 128MB 的块,标记为可移除。这是内存热插拔的粒度——虚拟机上这个值通常很小(方便 balloon 驱动动态调整),物理服务器上常见 1GB 或更大。
  • SwapTotal: 0 kB:这台机器没有交换空间。一旦 MemAvailable 见底就是直接触发 OOM Killer,没有缓冲。内存侧的排查套路见 Linux 内存排查:从 free 到 /proc/meminfo 与 OOM Killer 定位

普通用户读 /proc/meminfo 不需要任何权限,sudo -u nobody head -1 /proc/meminfo 照样能出 MemTotal

磁盘:lsblk 的 ROTA 与 TRAN 有坑

lsblk -d -o NAME,SIZE,ROTA,TYPE,TRAN,MODEL
NAME    SIZE ROTA TYPE TRAN MODEL
loop0  61.9M    1 loop
loop1  79.9M    1 loop
sr0     394K    1 rom       QEMU CD-ROM
vda       8G    1 disk

(这里滤掉了几个 snap 挂载用的 loop 设备,输出更干净。)

  • ROTA=1 表示「可旋转」,按设计是用来区分机械盘(1)和固态盘(0)的。但看 vda——虚拟磁盘也报了 ROTA=1。virtio-blk 默认不上报 rotational 属性,内核就取了保守默认值。所以在云服务器上用 ROTA 判断「这块盘是不是 SSD」基本无效,得去问云厂商或者实测 IOPS(fio 磁盘性能测试:从顺序吞吐到 4K 随机 IOPS 的存储基准)。
  • TRAN 列全空是另一个信号:SATA 盘会显示 sata、NVMe 显示 nvme、USB 显示 usb,而 virtio 设备不属于任何一种物理总线,所以这里是空的。
  • sr0MODELQEMU CD-ROM——这台机器上根本没有物理光驱,这个「光驱」是 QEMU 模拟出来的。设备名里带着 QEMU 三个字母,是虚拟化最直白的签名。

想追这块盘挂在哪个总线上,用 udevadm 读属性:

udevadm info -q property -p /sys/block/vda | grep -E "DEVTYPE|ID_PATH|ID_BUS"
DEVTYPE=disk
ID_PATH=pci-0000:00:05.0

ID_PATH=pci-0000:00:05.0 直接把这块盘定位到了 PCI 地址 0000:00:05.0——拿这个地址去 lspci 里查,就能对上是哪个控制器(见下一节)。这套「从设备名追到物理位置」的方法,和 lsof 进程文件排查:从打开文件到端口占用的完整指南 里追文件占用是同一个思路。

总线:lspci -k 看设备与驱动绑定

lspci -k 显示网卡是 Virtio 设备且驱动为 virtio-pci,lsblk 中 sr0 型号为 QEMU CD-ROM,ethtool -i 报驱动 virtio_net

lspci -k | grep -A3 "Ethernet controller"; echo "--- 块设备:"; lsblk -d -o NAME,SIZE,ROTA,TYPE,TRAN,MODEL | grep -v loop; echo "--- 网卡驱动:"; ethtool -i eth0 | head -3
00:11.0 Ethernet controller: Red Hat, Inc. Virtio network device
    Subsystem: Red Hat, Inc. Virtio network device
    Kernel driver in use: virtio-pci
--- 块设备:
NAME    SIZE ROTA TYPE TRAN MODEL
sr0     394K    1 rom       QEMU CD-ROM
vda       8G    1 disk
--- 网卡驱动:
driver: virtio_net
version: 1.0.0
firmware-version:

lspci -klspci 多出的那几行 Kernel driver in use 极其实用——排障时最常见的两类问题就是「设备没被识别」和「设备识别了但驱动没绑上」,这一行直接给出答案。如果某个设备这里是空的,说明内核没有加载对应驱动。

这台机器的完整 PCI 设备清单是这样的:

lspci
00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II]
00:01.2 USB controller: Intel Corporation 82371SB PIIX3 USB [Natoma/Triton II] (rev 01)
00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03)
00:02.0 VGA compatible controller: Cirrus Logic GD 5446
00:03.0 SCSI storage controller: Red Hat, Inc. Virtio SCSI
00:04.0 Communication controller: Red Hat, Inc. Virtio console
00:05.0 SCSI storage controller: Red Hat, Inc. Virtio block device
00:06.0 Unclassified device [00ff]: Red Hat, Inc. Virtio memory balloon
00:11.0 Ethernet controller: Red Hat, Inc. Virtio network device

一眼就能看出是虚拟机:440FX/PIIX3 是 1996 年的 Intel 440FX 芯片组(QEMU 的 i440fx 机型就是照它模拟的)、显卡是 Cirrus Logic GD 5446(1995 年的 2D 显卡,KVM 的默认模拟显卡之一)、四个 Virtio 设备是半虚拟化驱动。在真机上,你不会同时看到这几样东西。

其中 00:05.0 Virtio block device 正好对上了上一节 udevadm 读到的 ID_PATH=pci-0000:00:05.0——磁盘 → 总线地址 → PCI 设备这条链路就串起来了。

网卡还可以再深挖一层,ethtool -i 看驱动信息:

ethtool -i eth0
driver: virtio_net
version: 1.0.0
firmware-version:
bus-info: 0000:00:11.0

bus-info: 0000:00:11.0 又和 lspci 里的 00:11.0 Ethernet controller 对上了。而 firmware-version 是空的——虚拟网卡没有固件,这也是一处环境特征。

顺带一个常见困惑:ethtool eth0 查速率会得到 Speed: Unknown!Duplex: Unknown! (255)这不是故障,是虚拟网卡没有物理链路层,协商速率这个概念不适用;Link detected: yes 说明链路本身是通的。想测真实吞吐量得靠打流工具,网卡自报的速率在虚拟化环境里参考价值有限(HTTP 压测:从 ApacheBench 到 wrk 的 Web 性能测量)。

USB 总线也别漏掉:

lsusb
Bus 001 Device 002: ID 0627:0001 Adomax Technology Co., Ltd QEMU USB Tablet
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

QEMU USB Tablet 是 QEMU 提供给 VNC/SPICE 控制台用的绝对坐标指针设备——服务器上当然没有「USB 数位板」,它纯粹是为了让远程控制台的鼠标不飘。厂商名直接写着 QEMU

整机身份:dmidecode 与 SMBIOS 表

前面看的都是「内核眼里的硬件」,dmidecode 换了个视角:它读的是 BIOS/UEFI 在开机时填好的 SMBIOS 表,也就是主板厂商给自己机器写的「身份证」。

dmidecode 读取系统与 BIOS 信息,显示制造商 Red Hat、产品名 KVM;免 root 的 /sys 路径给出同样结果

dmidecode -t system | grep -E "Manufacturer|Product Name|Version|Family"; echo "--- BIOS:"; dmidecode -t bios | grep -E "Vendor|Version|Release Date"; echo "--- 免 root 的 /sys 读法:"; cat /sys/devices/virtual/dmi/id/product_name /sys/devices/virtual/dmi/id/bios_vendor
    Manufacturer: Red Hat
    Product Name: KVM
    Version: RHEL 7.6.0 PC (i440FX + PIIX, 1996)
    Family: Red Hat Enterprise Linux
--- BIOS:
    Vendor: SeaBIOS
    Version: 1.16.0-1.module_el8.7.0+1140+ff0772f9
    Release Date: 04/01/2014
--- 免 root 的 /sys 读法:
KVM
SeaBIOS

-t 后面跟类型,常用的几张表:

类型内容
biosBIOS/UEFI 厂商、版本、发布日期
system整机厂商、产品名、序列号、UUID
baseboard主板信息
chassis机箱类型
processor处理器插槽、厂商、速度、核心数
memory每根内存条的容量、类型、频率、插槽位置

Manufacturer: Red Hat + Product Name: KVM + Vendor: SeaBIOS 三件套,是 QEMU/KVM 虚拟机的标准签名(QEMU 用开源 BIOS 实现 SeaBIOS 充当固件)。

为什么 dmidecode 非要 root

很多人被 dmidecode 的权限卡过。真实原因可以直接查出来:

ls -l /sys/firmware/dmi/tables/; sudo -u nobody dmidecode -t system 2>&1 | head -3
total 0
-r-------- 1 root root 476 Sep 15 21:00 DMI
-r-------- 1 root root  31 Sep 15 21:00 smbios_entry_point
# dmidecode 3.3
/sys/firmware/dmi/tables/smbios_entry_point: Permission denied
Scanning /dev/mem for entry point.
/dev/mem: Permission denied

/sys/firmware/dmi/tables/ 下两个文件的权限是 0400(只有 root 可读),普通用户读不到;dmidecode 退而求其次去扫 /dev/mem,那里的权限更严。两条路都堵死,所以必须 sudo

免 root 的替代方案

但 SMBIOS 里的常用字段其实有世界可读的出口:

ls -l /sys/devices/virtual/dmi/id/product_name; sudo -u nobody cat /sys/devices/virtual/dmi/id/product_name
-r--r--r-- 1 root root 4096 Sep 11 21:05 /sys/devices/virtual/dmi/id/product_name
KVM

/sys/devices/virtual/dmi/id/ 目录下每个文件对应一个 SMBIOS 字段,权限是 0444(所有人可读)sudo -u nobody cat 照样能读出 KVM。写脚本采集资产信息时,能用 /sys 就别调 dmidecode——不用提权,输出还更规整。

⚠️ 陷阱:SMBIOS 里全是模拟数据

这是本文最值得记住的一条。看 dmidecode -t processor 的输出:

dmidecode -t processor | grep -E "Version|Max Speed|Current Speed|Core Count|Thread Count"
    Version: RHEL 7.6.0 PC (i440FX + PIIX, 1996)
    Max Speed: 2000 MHz
    Current Speed: 2000 MHz
    Core Count: 1
    Thread Count: 1

Max Speed: 2000 MHz。可 lscpu 明明说这是一颗 2.60GHz 的 Xeon Platinum 8272CL。

两个都没撒谎,但只有一个是真的。 lscpu 的型号来自 CPUID 指令,是 CPU 硬件自报家门;dmidecodeMax Speed 来自 QEMU 填进 SMBIOS 表的一个固定值——它压根没打算模拟真实的频率。同理,Version: RHEL 7.6.0 PC 是 QEMU 的 i440fx 机型写死的机型字符串,和实际跑什么系统毫无关系。

所以:性能、容量、拓扑相关问题信 lscpu//proc;资产编号、序列号、机箱型号这类问题才信 dmidecode

同一份表里的内存信息也是模拟的:

dmidecode -t memory | grep -E "Size|Form Factor|Locator|Type:|Speed|Manufacturer"
    Size: 2 GB
    Form Factor: DIMM
    Locator: DIMM 0
    Type: RAM
    Speed: Unknown
    Manufacturer: Red Hat
    Configured Memory Speed: Unknown

Size: 2 GB 这个大方向是对的(虚拟机的内存确实配了 2GB,和 lsmem 对得上),但 Speed: UnknownManufacturer: Red Hat 说明内存条的厂商和频率是编不出来的——虚拟机没有真实内存条,QEMU 只能填空值。Form Factor: DIMM 更是纯装饰。

把证据串起来:判断物理机还是虚拟机

现在可以系统回答开头那个问题了。不要只信一条命令,交叉验证才站得住:

证据命令本机结果物理机上会是什么
虚拟化检测systemd-detect-virtkvmnone
开机日志`dmesg \grep -i "Hypervisor detected"`Hypervisor detected: KVM无输出
CPU 标志位grep -c hypervisor /proc/cpuinfo10
SMBIOS 身份dmidecode -t systemManufacturer: Red Hat / Product Name: KVM真实整机厂商(Dell、Supermicro…)
PCI 设备`lspci \grep -i virtio`4 个 Virtio 设备

systemd-detect-virt 一条命令就能出结果,最省事;但它依赖 systemd 的环境判断,某些精简系统或容器环境下可能不准,所以另外四条是它的后手。

反过来,在物理机上你会看到systemd-detect-virt 输出 nonelscpu 里没有 Hypervisor vendor 那一行、lspci 里出现真实的网卡(Intel I350、Mellanox 之类)和 NVMe 控制器、dmidecode -t system 报出具体品牌型号。

这台机器的硬件画像

把上面所有输出汇总成一张表:

项目来源
虚拟化平台KVM(全虚拟化)systemd-detect-virtlscpu
固件SeaBIOS 1.16.0dmidecode -t bios
机型QEMU i440fx(440FX + PIIX3)lspcidmidecode -t system
CPU 型号Intel Xeon Platinum 8272CL @ 2.60GHzlscpu(CPUID)
vCPU1(1 插槽 × 1 核 × 1 线程)lscpu
L3 缓存35.8 MiB(宿主机的lscpu
内存2025116 kB ≈ 1.93 GiB,16 × 128MB 可移除块/proc/meminfolsmem
交换空间/proc/meminfo
磁盘8G virtio-blk,挂在 PCI 00:05.0lsblkudevadm
网卡virtio-net,挂在 PCI 00:11.0lspci -kethtool -i
显卡Cirrus Logic GD 5446(模拟)lspci
光驱QEMU CD-ROM(模拟)lsblk

采集系统信息、做资产盘点时,这类表格可以顺手用一个脚本生成——lscpulsblk/proc/meminfo 都是纯文本,非常适合作管道输入(Linux 管道与重定向:从文件描述符到进程替换 里的手法在这里很好用)。

几个容易踩的坑

  1. lsblkROTA 在虚拟机上不可信。vda 报 ROTA=1 不等于机械盘,TRAN 列为空也是 virtio 的正常表现。
  2. SMBIOS 是模拟的,别拿 dmidecode 的频率、速度字段做性能判断。要性能就用 fio 磁盘性能测试:从顺序吞吐到 4K 随机 IOPS 的存储基准 这类实测。
  3. 缓存和 NUMA 是宿主机的。虚拟机看到的 L3 大小和 NUMA 节点拓扑反映宿主机,不构成你的资源配额。
  4. dmidecode 需要 root,脚本里要提权;能用 /sys/devices/virtual/dmi/id/ 就读它。
  5. /proc/cpuinfo 只反映当前 CPU。多路机器上直接 cat /proc/cpuinfo 会打印所有逻辑核,脚本里记得 grep -m1lscpu 汇总。
  6. 别只看一个来源freefree 列、lsmem 的向上取整、meminfo 的精确 kB 值三者含义不同,报数前先确认口径。

小结

想干什么用什么
CPU 型号、核心拓扑、缓存、漏洞状态lscpu
内存总量与可用量free -h / /proc/meminfo
内存块与热插拔粒度lsmem
块设备、大小、总线类型lsblk -d -o NAME,SIZE,ROTA,TYPE,TRAN,MODEL
设备与驱动绑定关系lspci -k / lsusb
网卡驱动与总线地址ethtool -i
设备物理位置追溯udevadm info -q property -p /sys/block/<dev>
整机身份(需 root)dmidecode -t system,bios,processor,memory
整机身份(免 root)cat /sys/devices/virtual/dmi/id/*
判断虚拟机systemd-detect-virt + dmesg + /proc/cpuinfo flags

一句话总结这篇文章:Linux 给你的硬件信息来自不同源头,CPU 说的、SMBIOS 说的、设备模型说的可能互相打架——知道每个值从哪来,才知道该信哪一个。

发表评论

暂无评论,快来抢沙发吧!