开头部分先聊点实际场景:装好的 VirtualBox 虚拟机用着用着磁盘满了,Windows 弹“空间不足”,Linux 直接报 no space left on device。很多人的第一反应是新建一块盘挂载上去做数据盘,但这治标不治本——根分区还是那么小,系统盘塞满了照样容易出问题。真正干净利落的做法是“给原来的虚拟磁盘扩容”,让系统直接认出更大的空间,把根分区扩大,整个过程不用重装系统、不用迁移数据。
这篇文章就专门讲清楚 VirtualBox 里给虚拟机增加磁盘大小的完整链路,从命令行调整虚拟磁盘文件,到虚拟机内部的系统分区扩展,每一步的原理、参数依据和踩坑点都会说到。适合已经会装 VirtualBox、但没折腾过磁盘扩容的人,也适合给团队内部虚拟机做磁盘瘦身和扩容的运维朋友参考。我会把 VirtualBox 5.x 到 7.x 都覆盖到,因为热词里大量出现 5.2.44 这个版本,很多旧环境的坑都得按老版本的命令习惯来处理。
1. 扩容前的准备与整体思路
1.1 先搞清楚你要动的是哪一层
给虚拟机“增加磁盘大小”实际上涉及两层完全不同的操作:
第一层是虚拟磁盘层。VirtualBox 里的虚拟磁盘就是一个文件,后缀可能是 .vdi、.vmdk、.vhd 等。VBoxManage 能对这个文件做 resize,也就是增大文件里虚拟磁盘的可用上限。这一步做了之后,虚拟机外面(宿主机上)看到的是虚拟磁盘变大了,但虚拟机里面操作系统看到的还是原来的分区大小,因为分区表里的分区尺寸并不会随虚拟磁盘自动变化。
第二层是操作系统层。操作系统需要重新读取磁盘的分区表,把新增的空间加入到现有分区里,然后扩展文件系统。这一步在 Windows 和 Linux 上做法完全不同,而且必须在虚拟机内部操作。
很多人只做了第一层就以为完事了,进系统一看 C 盘还是原样,就到处找问题。所以务必先建立这个认知:扩容 = 扩大虚拟磁盘文件 + 扩展系统内分区文件系统,两步缺一不可。
1.2 规划扩容前的必要检查
理论上只要虚拟磁盘文件所在宿主机分区有足够剩余空间,扩容的主要限制就是这么几个点:
- 虚拟磁盘当前格式:VDI、VMDK、VHD,不同格式的扩容命令略有差异,这个后面详细说。
- 磁盘是否有快照链:如果虚拟机当前有快照,VirtualBox 的 resize 操作可能会报错或不生效,因为子虚拟磁盘是在快照之后产生的,布局和基础盘不一样。
- 系统分区在磁盘上的位置:Windows 系统盘一般在第一个分区,后面通常没有悬念;Linux 比较复杂,尤其是有 /boot、LVM 逻辑卷的情况,需要先确认分区布局再决定怎么扩。
- 虚拟磁盘是动态分配还是固定大小:动态分配 VDI 在宿主上实际占用小,扩容后文件大小上限变大;固定大小 VDI 直接全量占用宿主空间,扩容时就要保证宿主空间足够。如果是固定大小,可以考虑顺便换成动态分配,命令后面给。
官方命令在不同版本里的写法不一样,VirtualBox 5.x 以前用VBoxManage modifyhd,从某个版本开始推荐VBoxManage modifymedium。这两个命令很多老教程混着出现,其实功能一样,只是新版本统一到了modifymedium。建议先执行VBoxManage --version看一眼版本,再对应选用命令,避免敲了报“unknown command”的尴尬。
2. VirtualBox 虚拟磁盘扩容的完整操作
2.1 关机并在宿主机上执行 resize
无论虚拟机里装的是什么系统,扩容虚拟磁盘都要求虚拟机处于关机或至少是通电但不活动的状态。最简单的路径:关闭虚拟机电源,然后打开宿主机终端执行命令。
老版本命令格式(VirtualBox 5.2 等常见环境):
VBoxManage modifyhd /path/to/your.vdi --resize 51200新版本命令(VirtualBox 6.x / 7.x):
VBoxManage modifymedium disk /path/to/your.vdi --resize 51200这里的51200单位是MB,也就是扩容后的总大小。比如原来是 40GB,想扩到 50GB,就用51200(50 * 1024)。注意--resize后面填的是扩容后的最终目标尺寸,不是增加的量。我见过不少人以为这是增量,直接把 40GB 的盘填了个 40,结果跑完一看还是 40GB,白等半天。
如果虚拟磁盘是 VDI 且由动态扩展改成固定大小,可以加--variant Fixed:
VBoxManage modifymedium disk /path/to/your.vdi --resize 51200 --variant Fixed这个操作比较慢,因为要把整个文件重新写一遍,不是必要建议别做。反之,如果原来固定大小想转动态,用--variant Standard。不过在扩容场景里,这两者都不太常用,了解即可。
2.2 不同虚拟磁盘格式的差异与特殊处理
VirtualBox 原生格式是 VDI,扩容最顺。VMDK 和 VHD 是兼容格式,VirtualBox 虽然能操作,但有细节差异:
- VMDK:如果当初用其他虚拟化产品创建,VirtualBox 对它的支持要看类型。动态 VMDK 直接 resize 基本可行,但固定 VMDK 或带有描述文件依赖的 VMDK 可能报错。
- VHD:老式 Hyper-V 兼容格式,VirtualBox 5.2 之后能处理,但尽量先转换成 VDI 再扩容更稳,转换命令
VBoxManage clonemedium disk input.vhd output.vdi --format VDI,转换过程会做一次完整拷贝,占用时间取决于磁盘数据量。
我个人的实操建议:如果磁盘格式不是 VDI,且虚拟机不是特别紧要的生产环境,先克隆一份 VDI 再扩容,操作成功后再替换原磁盘文件。这也是最安全的链路。VirtualBox 的克隆命令能保留磁盘 UUID,避免开了虚拟机后出现找不到磁盘的“UUID already exists”类错误,但要配合--keepalluuid等参数使用,具体可以VBoxManage clonemedium --help查看。
另外,热词里多次出现 VirtualBox 5.2.44 这个版本,这个版本算是 5.2 系列的收尾版本。遇到modifymedium不识别的时候,多半是版本太老,这时回退到modifyhd即可。命令历史原因造成的坑,先查版本再敲命令,能省不少事。
2.3 通过 GUI 图形界面完成扩容
命令行是主流,但部分用户喜欢用 VirtualBox 主界面操作。VirtualBox 6.0 以上版本,打开虚拟机的“设置 -> 存储”,选中控制器里的 SATA 项后,在详细信息面板会出现“磁盘大小”的滑块,直接拖动即可调整。
这个滑块在新版本里支持调整 VDI 大小,效果和命令行一样。实际上 GUI 操作时,VirtualBox 底层也是调 VBoxManage,所以两者本质上没有区别。
但 GUI 操作有个缺点:看不到很多底层输出,中间报错信息不够明确。如果产线环境里不想折腾命令行,可以用 GUI 拉到目标大小,然后继续下面操作系统内的分区扩展。如实说,我个人更推荐命令行,因为 GUI 有时候把可用空间上限显示得比较保守,列出的是当前磁盘格式允许的最大值,命令行界定的边界更清楚。
3. 虚拟机内部:Windows 系统的分区扩展
3.1 Windows 磁盘管理直接扩展卷
Windows 7 到 Windows Server 2019/2022 都适用这个方法。前提是新增的未分配空间紧跟在需要扩展的分区后面,而且该分区和未分配空间在同一个磁盘上。
操作路径:控制面板 -> 管理工具 -> 计算机管理 -> 磁盘管理。或者更快的办法,Win + R 输入diskmgmt.msc回车。在磁盘图上能看到虚拟磁盘尾部多出了一段“未分配”。
右键点击 C 盘分区,如果“扩展卷”按钮是亮的,直接点,按向导完成即可。VirtualBox 扩容出来的空间排在原分区后面,所以大多数情况下扩展卷可用。
需要注意几点:
- 分区必须是 NTFS 或 ReFS,FAT32 不支持直接扩展,只能转格式。
- 系统分区带引导性质,磁盘管理中如果“扩展卷”灰掉,通常是分区表类型或分区本身有问题,要进命令行手工处理(见 3.2)。
- 如果磁盘上有恢复分区夹在系统和未分配空间之间,扩展卷也会灰掉,因为逻辑上分区不连续。这种就得用第三方分区工具强行移动恢复分区。
3.2 命令行 diskpart 扩展与常见限制
磁盘管理的扩展卷功能简单,但遇到扩展卷灰色、跨分区不连续、动态磁盘这些情况就得请出 diskpart:
diskpart list disk select disk 0 list partition select partition 1 extendextend不加参数时,默认把该分区后面所有可用的未分配空间全部扩展到当前分区。如果要指定大小,用extend size=10240,单位 MB。
diskpart 用来处理跨区域分配很灵活,但两条硬性限制:
- 只能扩展 NTFS 或未格式化分区。
- 如果目标分区前面有未分配空间(比如要把前面空出来的空间加到后面分区),diskpart 做不到,Windows 原版分区管理也不支持前移。
遇到这种布局,网上的通用做法是使用 DiskGenius、傲梅分区助手、MiniTool Partition Wizard 这类 Windows 下的第三方分区工具。它们支持把分区“向左移动”,把未分配空间挪到目标分区旁边,再执行扩展。操作前务必备份重要数据,第三方工具一旦断电或误操作,风险比原生工具高很多。
3.3 实际案例:Windows 7 虚拟机 C 盘扩容的完整过程
拿一个很有代表性的场景说吧:VirtualBox 里装 Windows 7 虚拟机做测试,装的时候只给了 20GB,装了软件后剩余空间不足 2GB。按标题的做法,我执行了下面几步:
宿主机终端:
VBoxManage list vms VBoxManage modifyhd "D:\VirtualBox VMs\win7\win7.vdi" --resize 40960虚拟机内部:
- 磁盘管理里看到磁盘 0 尾部多出约 20GB 未分配。
- 右键 C 盘 -> 扩展卷,大小直接填 20480 MB,确定。
- 等待几秒,C 盘从几十 GB 变成 40GB,重启后生效。
这里有个小细节:Windows 7 的磁盘管理在虚拟机重启后才会刷新可用空间,有时未分配空间明明有了,扩展卷还是灰的。最简单的方法是重启虚拟机一次再试,比在磁盘管理里点“操作 -> 重新扫描磁盘”更彻底。
4. 虚拟机内部:Linux 系统的分区扩展
4.1 先确认分区布局与文件系统类型
Linux 下的扩容比 Windows 复杂很多,因为没有统一的磁盘管理界面,而且不同发行版的分区方案差异很大。拿到一台需要扩容的 Linux 虚拟机,先执行一组排查命令:
lsblk df -hT sudo fdisk -l /dev/sda重点关注三件事:
- 磁盘设备名:一般是 /dev/sda,NVMe 虚拟盘可能是 /dev/nvme0n1,不同设备后续操作路径不同。
- 分区类型:MBR 分区表使用 fdisk,GPT 分区表用 gdisk 或 parted。两者对扩展分区操作的限制不同。
- 文件系统是普通分区还是 LVM:LVM 逻辑卷的扩展方式要额外多一层 lvextend,即使扩容了虚拟磁盘,也要先把空间分配给 PV、LV,再扩展文件系统。
4.2 普通分区(非 LVM)的扩展流程
以最常见的发行版 Ubuntu/CentOS 为例,假设虚拟机磁盘 /dev/sda,当前系统分区 /dev/sda1,文件系统 ext4。扩容虚拟磁盘后,系统内第一步是扩大分区,第二步是扩大文件系统。
先删掉旧分区表再重建,这是很多教程的写法,也比较刺激:
sudo fdisk /dev/sda进入交互界面后,依次:
- 输入
p打印分区表,记住 sda1 的起始扇区。 - 输入
d删除分区,输入分区号 1。 - 输入
n新建分区。 - 分区号默认 1,起始扇区默认沿用之前的,最关键的一步是确认起始扇区和原分区完全一样,如果 fdisk 自动给的默认值变了,分区数据会丢失。
- 结束扇区直接回车表示用到磁盘最大空间,或手动指定想要的大小。
- 输入
w保存退出。
这一步本质是用新的结束位置重建了同样起始位置的分区,分区数据不变,只是分区表记录的分区边界扩大了。很多新人对“删除分区”这一步吓一跳,其实只要起始扇区不变,数据就不会破坏。但还是要再次强调:操作之前做数据备份,没有例外。
删除并重建分区后,让内核重新读取分区表:
sudo partprobe /dev/sda然后扩展文件系统。ext4:
sudo resize2fs /dev/sda1XFS(CentOS 7+ 默认):
sudo xfs_growfs /注意 resize2fs 和 xfs_growfs 的操作对象不同,xfs 只能挂载态扩展,而且只能扩不能缩,所以分区时别贪心一步到位,或者做好后续调整的准备。
4.3 LVM 逻辑卷的常见扩容流程
很多 Linux 虚拟机安装时会自动启用 LVM,比如 CentOS 默认就是。这种布局下,虚拟磁盘扩容后要走四步:
第一步,扩展物理卷 PV:
sudo pvresize /dev/sda2pvresize会检测到磁盘尾部新增的空间,自动把 PV 扩展到最大。执行完pvs可以看到 PV 大小变了。
第二步,检查卷组 VG 可用空间:
sudo vgs如果卷组里空闲 PE 不为 0,说明空间已经进入了卷组池。
第三步,扩展逻辑卷 LV。先lvdisplay或lvs找到要扩容的 LV,比如根分区是 /dev/centos/root,然后:
sudo lvextend -l +100%FREE /dev/centos/root-l +100%FREE表示把卷组所有剩余空间都给这个 LV。如果只想加固定大小,用-L +10G这种写法。
第四步,扩展文件系统。ext4:
sudo resize2fs /dev/centos/rootXFS:
sudo xfs_growfs /LVM 的链路虽然看着长,但其实是 Linux 扩容里容错最高的一种方式,因为 PV、LV、文件系统是分层管理的,每层都有查询命令可以确认空间到哪儿了。排错思路也按层排查:虚拟磁盘 -> PV -> VG -> LV -> 文件系统,哪一层没变大,就卡在哪一层。
4.4 用 GParted Live 图形化扩容的备选方案
如果不想敲命令或者害怕 fdisk 删分区重建,还有一个很多人验证过的稳妥办法:下载 GParted Live ISO,挂载到虚拟机光驱里,从光驱启动,用图形界面分区。
操作步骤:到 SourceForge 下载 gparted-live 的 ISO -> 虚拟机设置里把 ISO 挂到光驱 -> 启动顺序调整为光驱优先 -> 启动后进入 GParted 界面 -> 右键系统分区选择 Resize/Move -> 把新空间纳入分区 -> Apply 应用。
GParted 的好处是支持调整分区边界、移动分区,图形化展示每一步操作结果,遇到分区中间有未分配空间的情况比命令行直观得多。缺点是 ISO 启动比较费时间,而且 GParted 版本如果太老,对 NVMe 虚拟磁盘的支持可能不到位。我一般只在命令行方案遇到“分区起始位置不好处理”时才用这个。
5. 扩容后的验证与常见问题处理
5.1 验证扩容是否真正生效
Windows 系统里,磁盘管理看分区大小、我的电脑里看盘符可用容量即可。C 盘如果没变大,先确认扩展卷是否成功,再看未分配空间是否还在,可能在另一个物理磁盘上。
Linux 系统里,验证分几步:
lsblk df -h sudo pvs sudo vgs sudo lvslsblk 看分区是否占满了整个虚拟磁盘,df -h 看文件系统可用空间,如果文件系统大小没变,大概率是只扩了分区忘了扩文件系统,或者 LVM 层没执行 lvextend。
这里有个常见情况:ext4 文件系统在resize2fs成功后,df -h 需要一小段时间才刷新,如果看到空间没变,先等一下再执行一次df -h,不要着急重启。
5.2 快照导致扩容失败的处理
这是 VirtualBox 老用户最容易踩的坑。如果虚拟机创建过快照,执行 VBoxManage resize 时可能直接报错。原因是虚拟磁盘有多个快照子文件时,磁盘链的结构变了,扩容操作不能直接作用在基础盘上。
常见手段是“删除快照合并后再扩容”。但这会丢失快照历史,在操作之前VBoxManage snapshot list vmname看看快照列表,评估是否要保留。如果快照里有想要的数据,另一种做法是“导出虚拟机再导入”,导出的 OVA 会自动把所有快照合并成单盘,然后对导入后的新虚拟机执行扩容。
真实案例里,我碰到过一台带 6 个快照的开发虚拟机,扩容时提示无法修改。我选择克隆虚拟机(不包含快照状态),再对克隆体扩容,原机器留着当备份。这个思路在意数据安全时更为可靠。
5.3 动态扩展磁盘与宿主空间不足报错的处理
很多人扩容虚拟磁盘后,虚拟机内部空闲空间有了,但宿主机的磁盘空间已经见底。因为动态 VDI 虽然看起来只是改了个大小上限,但如果虚拟机内开始写入大量数据,VDI 文件会逐渐膨胀,直到占满宿主机分区。
遇到这种情况,处理顺序:
- 先在宿主机清理临时文件、其他不再使用的虚拟机文件,腾出空间。
- 考虑把虚拟磁盘存储目录迁移到空间更大的分区,VirtualBox 全局设置里的默认虚拟机目录可以改,但迁移前记得先把虚拟机关机,再移动整个 VDI 文件。
- 使用 VBoxManage 压缩 VDI 文件大小。注意压缩前必须在虚拟机内部用工具把空闲空间清零。Linux 下可以用
zerofree,启动单用户模式执行;Windows 下可以用 sdelete 的 -z 选项。然后关机,宿主机执行VBoxManage modifymedium disk xxx.vdi --compact。这步能回收未用空间,也是 VirtualBox 用户日常维护的好习惯。
5.4 快速问题排查速查表
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| VBoxManage 提示 Unknown command | VirtualBox 版本过旧 | 检查版本,改回 modifyhd 命令 |
| 虚拟机内部未分配空间不出现 | 分区表未刷新 | Windows 重启,Linux 执行 partprobe |
| 扩展卷/扩展功能灰色不可用 | 分区不连续/文件系统不支持 | 查看分区布局,必要时用 GParted |
| resize2fs 报错设备忙 | 分区被占用 | 卸载分区后用 Live CD 环境处理 |
| lvextend 无可用空间 | 卷组没扩 PV | 执行 pvs/vgs 检查,补 pvresize |
| 扩容后系统无法启动 | 分区表写入错误 | 备份数据,重建分区表或用 GParted 修复 |
| 快照后无法 resize | 快照链限制 | 合并快照或克隆虚拟机后再扩容 |
这个表我在给团队做文档时也写过一版,遇到问题先匹配现象,再顺着三层定位:虚拟磁盘层、分区层、文件系统层,基本能解决九成问题。
5.5 扩容的几个实操心得
第一点心得:永远先备份再扩容。虽然纯扩容操作本身风险不高,但 Linux 分区删除重建那一步是风险高峰,备份不是可选项。最简单的备份方式是VBoxManage export导出 OVA,或者直接复制 VDI 文件,注意关机状态下复制。复制 VDI 文件时必须保证虚拟机处于完全关闭状态,不能是“暂停”或“保存状态”,否则会复制到不一致的磁盘状态。
第二点心得:一开始创建虚拟机时就不要把磁盘给得太小。VirtualBox 的动态扩展 VDI 在宿主上并不预占全部空间,装系统时给 80GB、100GB 并不会立刻消耗宿主机空间,只是设置了上限。很多人图省事给 20GB 或 30GB,结果后续频繁扩容,每次都要整这套流程。如果只是测试环境,直接在创建时把磁盘上限给足,省事得多。如果担心宿主机空间不够,等真的需要时再按这篇文章的流程扩充,数据都在,不存在“配错磁盘就得重装”的说法。
第三点心得:虚拟机内部空间不足时,优先看根分区还是独立数据分区。有时候系统盘满了,但 SQL 数据库或日志目录在 /data 独立分区,这时扩容系统盘不如把新空间直接挂到 /data 下更合适。扩容之前先想清楚“扩出来的空间到底要给谁”,这句话值很多时间成本。我维护的几台服务器里,有一台就是这种情况:虚拟磁盘增加了 50GB,结果系统盘空间一直没涨,一查才意识到根分区和 /data 是独立分区,改挂载点后问题立刻解决了。
最后再分享一个小技巧
VirtualBox 里给虚拟机扩容磁盘,其实还有一条别人很少提的快路径:如果只是想要“系统盘剩余空间变大”,而且虚拟机里没有存必须保留的数据,最快的办法是备份数据、直接重建一台磁盘更大的虚拟机,然后装好系统再恢复数据。这个办法在测试环境里比磁盘扩容整套流程快得多,还能顺便换新版操作系统。但生产环境、有大量配置和依赖包的虚拟机,强烈建议用本文的正规扩容路径,毕竟配置和状态迁移的成本远远高于磁盘扩容的那几分钟操作。
另一个常用的小技巧:扩容后顺手给虚拟磁盘做一次快照。这里的快照不是扩容前的那张,而是扩容成功之后的“干净状态”。以后如果再折腾系统更新或装新软件,随时能回滚到这个刚扩容完成、空间充足的节点。这个习惯帮我省过好几次返工时间,也推荐给你。