在Ubuntu中挂载虚拟机硬盘文件的核心方法是使用qemu-nbd将vhd/vdi/qcow2格式的磁盘镜像挂载为块设备,再通过mount命令访问其中的分区,整个过程无需启动虚拟机,适合用于数据恢复、批量修改和迁移场景。
准备工作:确认格式与安装必要组件
先把虚拟机硬盘文件从宿主机拷贝到Ubuntu上,放在一个可读写的目录中,挂载前务必确认镜像文件格式,因为不同虚拟化平台生成的磁盘文件后缀不同,处理方式也有差异。
常见虚拟机磁盘格式包括:
- raw:最原始的镜像格式,就是一个完整的二进制文件,兼容性最好。
- qcow2:QEMU/KVM默认格式,支持快照、压缩和写时复制。
- vdi:VirtualBox默认格式。
- vmdk:VMware Workstation和ESXi常用格式。
- vhd/vhdx:Hyper-V和Virtual PC使用。
挂载前需要具备root权限,并且安装qemu-utils和nbd内核模块,如果系统没有这些工具,执行以下命令安装:
sudo apt update sudo apt install qemu-utils nbd-client
安装完成后,检查当前内核是否支持nbd模块:
modprobe nbd
如果提示模块不存在,可能需要安装linux-modules-extra包,例如Ubuntu 22.04 LTS可以执行sudo apt install linux-modules-extra-$(uname -r)。
行业共识认为,qemu-nbd是处理qcow2和raw格式最稳定的开源方案,它通过内核级网络块设备协议将镜像文件暴露为/dev/nbdX设备。
使用qemu-nbd挂载raw和qcow2镜像
这是最通用的挂载方法,适用于KVM、QEMU和部分VirtualBox导出的raw镜像,如果镜像文件是qcow2格式,需要先加载nbd模块并指定最大分区数量,否则内核只能看到整个磁盘而看不到内部的分区表。
步骤如下:
加载nbd模块并允许4个分区被识别:
sudo modprobe nbd max_part=4
将qcow2镜像连接到nbd设备:
sudo qemu-nbd --connect=/dev/nbd0 /path/to/your-disk.qcow2
查看分区信息:
sudo fdisk -l /dev/nbd0
输出结果会显示类似/dev/nbd0p1、/dev/nbd0p2的分区节点,如果镜像只有一个分区且没有分区表(例如裸文件系统),则直接使用/dev/nbd0。
挂载目标分区到本地目录:
sudo mkdir -p /mnt/vmdisk sudo mount /dev/nbd0p1 /mnt/vmdisk
此时进入/mnt/vmdisk即可查看和修改虚拟机磁盘中的文件,对于raw格式,步骤完全相同,唯一的区别是raw镜像不需要额外的格式转换,qemu-nbd同样可以处理。
挂载完成后必须执行断开操作,否则nbd设备会一直占用镜像文件,导致虚拟机无法正常启动:
sudo umount /mnt/vmdisk sudo qemu-nbd --disconnect /dev/nbd0
挂载VHD和VDI文件的关键差异
vhd和vdi虽然也是磁盘镜像,但qemu-nbd直接支持它们,不需要转换格式,不过需要注意,vhd格式分为固定大小和动态扩展两种,动态扩展的vhd挂载时如果宿主机的磁盘空间不足,可能导致写入失败。
操作流程与qcow2一致,只是把--connect的参数换成vhd或vdi文件路径,例如挂载VirtualBox的vdi文件:
sudo qemu-nbd --connect=/dev/nbd1 /path/to/virtualbox-disk.vdi
然后同样执行fdisk查看分区,挂载到目录。
一个常见坑点:VirtualBox创建的vdi文件默认包含一个有MBR分区表的整盘镜像,如果你的虚拟机只创建了一个分区,那么/dev/nbd1p1就是根分区,如果虚拟机使用LVM逻辑卷,还需要额外处理,此时先挂载/dev/nbd1p1(通常是/boot分区),然后通过vgscan和vgchange -ay激活卷组,再挂载逻辑卷。
国内一些从业者在处理VirtualBox的vdi文件时,常会遇到“挂载后分区读取失败”的问题,业内专家指出这多半是因为vdi镜像存在快照分支,而qemu-nbd只能访问当前活跃分支,检查方法是在VirtualBox中删除所有快照后再导出镜像。
直接挂载vmdk和vhdx的替代方案
vmdk需要区分是完整镜像还是拆分镜像,拆分后的vmdk(多个小文件)不能直接挂载,需要用vmware-vdiskmanager合并,或者用qemu-img转换成qcow2再挂载,完整单文件的vmdk可以尝试用qemu-nbd处理,但由于VMware的格式私有特性,转换后的兼容性往往更好。
对于Hyper-V的vhdx,Ubuntu 22.04及以上版本的内核已支持直接挂载,但更稳妥的方式是先用qemu-img转换为raw:
sudo qemu-img convert -p -O raw /path/to/windows.vhdx /path/to/windows.raw
转换时间取决于镜像大小,一般50GB的vhdx需要5到10分钟,转换成raw的好处是所有工具都能直接识别,坏处是文件变大,无法节省空间。
如果只是想读取文件而不需要写入,使用glusterfs或libguestfs是更安全的选择,尤其当你在排查虚拟机无法启动的问题时,不写回原始镜像可以减少二次损坏的风险。
只读挂载与恢复数据
对于仅需拷贝文件或排查故障的场景,强烈建议使用只读方式挂载,mount命令加-o ro参数即可:
sudo mount -o ro /dev/nbd0p1 /mnt/vmdisk
另一种避免加载内核模块的方法是使用libguestfs的guestfish工具,它通过用户态模拟方式读取镜像,不需要root权限,也不占用nbd设备,安装libguestfs-tools后,可以这样列出镜像内容:
sudo virt-ls /path/to/disk.qcow2 /
或者直接使用guestmount挂载:
sudo guestmount -a /path/to/disk.qcow2 -i /mnt/vmdisk
guestmount的优势在于支持LVM和复杂分区表,缺点是需要libvirt后台运行,在处理大镜像时速度比qemu-nbd慢。
关于恢复误删文件的场景,如果虚拟机文件系统受损,先用fsck检查分区:
sudo fsck /dev/nbd0p1
注意,只读挂载时运行fsck毫无意义,必须在可写挂载状态下执行,但这一步有风险,建议先将整个镜像复制一份再操作,避免数据雪上加霜。
挂载后的文件访问与权限问题
挂载完成后,如果看到Permission denied或者目录空白,可执行如下排查:
- 确认虚拟器内部的用户UID与宿主机不同,使用
ls -n查看数字UID,然后通过chown或sudo访问。 - 虚拟机启用了SELinux(Fedora系)或AppArmor(Ubuntu系)时,安全上下文可能在挂载后表现为奇怪的文件隐藏行为,此时直接跳过文件管理器,用
find /mnt/vmdisk -type f验证存在性。 - 使用vfat或exFAT文件系统时,挂载需要指定uid和gid参数,
sudo mount -o uid=1000,gid=1000 /dev/nbd0p1 /mnt/vmdisk
常见问题排查
nbd设备已被占用无法连接
如果执行qemu-nbd时提示/dev/nbd0 is already in use,用lsblk检查哪些nbd设备活动,确认无人使用后,运行sudo qemu-nbd --disconnect /dev/nbd0强制释放,如果仍不行,重启宿主机是最简单的解决方案。
挂载后看不到任何分区
原因可能是镜像中没有分区表,或者分区类型在Linux中不可识别,先用fdisk -l /dev/nbd0查看,如果显示“disk doesn’t contain a valid partition table”,说明整个镜像就是一个文件系统,直接挂载/dev/nbd0。
支持文件系统类型汇总
| 文件系统 | Linux默认支持 | 挂载命令 |
|---|---|---|
| ext4 | 是 | 直接mount |
| xfs | 是 | 直接mount |
| btrfs | 是 | 直接mount |
| NTFS | 需安装ntfs-3g | mount -t ntfs3 |
| FAT32 | 是 | mount -t vfat |
Ubuntu 22.04及以上默认内核驱动支持ntfs3,但如果遇到写入失败,安装ntfs-3g替代:
sudo apt install ntfs-3g sudo mount -t ntfs-3g /dev/nbd0p1 /mnt/vmdisk
挂载完成后的安全检查
卸载操作务必按顺序执行,避免缓存未刷写导致数据损坏:
- 结束所有正在访问挂载目录的进程,例如
sync命令。 - 卸载分区:
sudo umount /mnt/vmdisk。 - 断开nbd设备:
sudo qemu-nbd --disconnect /dev/nbd0。 - 如果启用了LVM,执行
vgchange -an关闭卷组。
最后检查dmesg输出有没有I/O错误,如果没有,可以安全地关闭宿主机或删除镜像文件。
内存与性能调优
挂载大型虚拟机磁盘(200GB以上)时,mount过程可能较慢,因为内核需要读取整个分区表,此时可以使用losetup配合分区偏移手动挂载,但操作复杂,不推荐新手使用。
一个更实用的技巧是只挂载虚拟机的数据盘而不是系统盘,系统盘往往包含大量日志和临时文件,挂载时容易触发文件系统日志回放,拖慢速度,单独挂载数据盘可以直接访问业务文件,这也是运维人员处理“虚拟机磁盘文件挂载后卡住”问题时的首选思路。
结合虚拟化平台的选择建议
如果你只是临时访问KVM虚拟机磁盘,qemu-nbd是最直接的工具,如果是ESXi迁移出来的vmdk,建议先用qemu-img转换为qcow2,这样在Ubuntu上后续操作更顺手,反过来,如果想把Linux磁盘文件复制到VMware虚拟机里,也是先转vmdk,而不要用qemu-nbd直接挂载后copy文件夹,因为这种拷贝会丢失权限和稀疏文件属性。
价格和成本方面,无论使用qemu-nbd还是libguestfs,都是完全免费的开源解决方案,不需要为虚拟化平台额外支付许可费。
关于在Ubuntu不同版本上的差异
Ubuntu 20.04 LTS和22.04 LTS在挂载方式上没有本质区别,但22.04默认内核支持ntfs3,而20.04只支持ntfs-3g,Ubuntu 24.04 LTS进一步增强了qemu-nbd对vhdx的支持,不过官方文档仍建议复杂格式走转换路线。
如果使用Ubuntu Server版,不要忘记服务器版本默认不带图形界面,所有操作都在终端完成,上面的命令已经覆盖了全部步骤,不需要额外安装任何GUI工具。
虚拟机硬盘挂载的核心结论不变:先确认格式,再选工具,优先只读挂载,操作完成后务必安全断开,按照这套流程处理绝大多数虚拟化平台的磁盘镜像都没有问题,在逻辑卷、LVM或RAID分区等复杂场景下,放慢节奏,分步检查,再执行写入操作,能最大程度避免数据丢失。
常见问题解答
挂载虚拟机磁盘文件时需要关闭虚拟机吗?
需要,虚拟机运行时正在使用磁盘镜像文件,强行挂载会破坏文件系统一致性,导致分区读取失败或数据损坏,正确的做法是先关闭虚拟机,或者至少对虚拟机做热快照后挂载快照文件,而不是直接操作运行中的镜像。
qcow2格式的镜像能否直接挂载到Ubuntu目录?
可以,通过qemu-nbd连接后再mount,就能让qcow2镜像像普通硬盘一样访问,前提是Ubuntu内核加载了nbd模块,并且镜像文件所在分区有足够空间容纳写入数据,如果镜像内部的分区是NTFS,记得先安装ntfs-3g驱动。
为什么挂载vdi文件后无法读取分区内容?
最常见的原因是vdi文件包含动态扩容区域,而qemu-nbd对动态vdi的支持不完全顺利,建议先用VirtualBox的克隆功能把vdi导出为qcow2,再尝试挂载,另一个可能的原因是虚拟机内部使用了LVM逻辑卷,需要先激活卷组才能看到逻辑卷设备。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/626805.html





