最可靠方法是运行 systemd-detect-virt:返回 none 为物理机,kvm/vmware/hyperv 等为虚拟机,container 则为容器;它综合多路径检测,结果明确且无需额外安装。

直接看 systemd-detect-virt 的输出最可靠:返回 none 就是物理机,返回 kvm、vmware、hyperv 等就是虚拟机。
用 systemd-detect-virt 快速判断
这是 systemd 提供的专用工具,不依赖额外包(多数现代发行版自带),结果明确、无歧义。
- 在物理机上执行:
systemd-detect-virt输出none - 在 KVM/QEMU 中执行:输出
kvm或qemu - 在 VMware 中执行:输出
vmware - 在 Hyper-V 中执行:输出
hyperv - 如果运行在容器里(如 Docker)但不是完整 VM,可能输出
container—— 注意这和虚拟机是两回事
它内部综合了多种检测路径(DMI、CPUID、/sys/hypervisor 等),比单查一个文件更鲁棒。
lscpu | grep Hypervisor 为什么有时不显示
这个命令只在内核启动时识别到 hypervisor 并完成初始化后才写入 Hypervisor vendor 字段。常见失效场景:
- 系统刚启动不久,内核尚未完成 hypervisor 探测(可稍等再试或重启后重查)
- 使用轻量级虚拟化(如某些 LXC 配置、Firecracker)不暴露 hypervisor 信息
- 内核编译时禁用了相关探测逻辑(极少见,多见于定制嵌入式内核)
- QEMU 启动时没加
-machine accel=kvm或未启用 KVM 模块,lscpu就不会显示Hypervisor vendor
所以它适合快速确认,但不能作为唯一依据;空输出 ≠ 物理机。
dmidecode -s system-manufacturer 和 product_name 的陷阱
这两个字段读取的是 DMI/SMBIOS 表,虚拟机厂商常伪造这些值来匹配宿主机行为,但容易被绕过或误判:
-
dmidecode -s system-manufacturer返回QEMU或VMware, Inc.是强信号,但返回Dell Inc.不代表就是物理机——有些云厂商(如 AWS、Azure)会透传宿主硬件标识 -
cat /sys/class/dmi/id/product_name在容器或某些精简镜像中可能权限受限或根本不存在(非 root 用户读不到,或 sysfs 未挂载完整) - 部分 KVM 镜像被手动修改过 DMI 信息,导致显示为
System Product Name这类默认占位符,失去判别意义
建议仅作辅助验证,尤其当 systemd-detect-virt 和 lscpu 结果不一致时交叉比对。
遇到 OpenVZ/LXC 等容器环境怎么办
它们不是虚拟机,但常被误认为“虚拟机”。systemd-detect-virt 会返回 container,而 virt-what 可能输出 openvz 或 lxc。关键区别:
- 没有独立内核,共享宿主内核 →
uname -r和宿主机一致 - 无
/proc/xen/、/proc/vz/等虚拟机特有目录(但 OpenVZ 有/proc/vz) -
dmesg | grep -i hypervisor完全无输出
如果你看到 systemd-detect-virt 返回 container,就别再拿虚拟机工具去调试——网络、存储、cgroup 行为都完全不同。
真正容易被忽略的是:同一台机器上可能混用多种虚拟化层(比如 KVM 里再跑 Docker),systemd-detect-virt 只报告最外层,内层容器需要单独用 facter virtual 或检查 /proc/1/cgroup 判断。











