☰
VirtualBox 虚拟磁盘扩容实战:从 VBoxManage 到分区文件系统调整
2026/9/30 3:47:57 网站建设 项目流程

1. 磁盘扩容前,先认清你的虚拟磁盘格式

VirtualBox 虚拟机的磁盘一旦提示"磁盘空间不足",很多人第一反应是去网上搜"virtualbox 增加磁盘大小",然后照着帖子用 VBoxManage 敲了两条命令,结果重启系统发现没有任何变化。其实问题十有八九出在第一步——没有搞清楚自己的虚拟磁盘到底是个什么格式、有没有做快照、磁盘大小计算方式对不对。

先说最基础的一个概念:VirtualBox 的虚拟磁盘有好几种格式,最常见的是 VDI(VirtualBox 自家的默认格式)、VMDK(VMware 虚拟磁盘格式)、VHD/VHDX(微软虚拟磁盘格式)。不同格式的扩容方式并不完全一样,虽然 VBoxManage 都能处理,但 VMDK 和 VDI 在扩容后的检查方式、兼容性表现都有区别。你装的系统如果是从 VMware 迁移过来的,磁盘很可能就是 VMDK,这类磁盘在 VirtualBox 里扩容并不是不能做,只是处理逻辑你要额外留个心眼。

第二步是看磁盘分配方式。VDI 又分为"动态分配"和"固定大小"两种。动态分配的 VDI,文件一开始只有很小体积,随着虚拟机里写入数据会慢慢膨胀到上限;固定大小的 VDI 则创建时就占满物理硬盘空间。扩容操作对这两种都有效,但事后验证的方法不同——固定大小磁盘扩容后宿主机上的文件体积会立即增大,动态分配磁盘则只有在客户机真实写入新数据后文件才会增长。这也是为什么有人执行完 resize 命令后,看宿主机里的 .vdi 文件大小没怎么变就以为扩容失败了,其实命令早就生效了。

还有一个最容易忽视的点:快照。只要你之前对虚拟机做过快照,VirtualBox 的磁盘链就变复杂了。快照之后产生的所有数据差异都存在快照文件中,虚拟磁盘文件本身并不会在你扩容时"原地长胖"。我遇到过不少人在带快照的状态下执行扩容,之后系统启动出现异常,其实不是扩容本身的问题,而是快照链和 resize 后的磁盘尺寸发生了错位。所以扩容前先确认当前虚拟机有没有快照,有就认真考虑要不要保留。

在动手之前,请在宿主机里打开终端,执行这条命令:

VBoxManage list hdds

输出里能看到每个虚拟磁盘的 UUID、格式、容量和实际占用文件路径。记下你目标磁盘的 UUID,然后继续往下走。顺便说一句,如果这台虚拟机是 Vagrant 管的,通常在 VirtualBox 里会看到一个很奇怪的硬盘名字,路径在~/VirtualBox VMs/或者你自己自定义的目录下,别认错了盘。

2. 用 VBoxManage 做扩容:关键命令与数值计算

确认磁盘格式和 UUID 之后,扩容本身其实就一条命令。先关掉虚拟机(不是保存状态,是彻底关机,否则扩容时 VBoxManage 会直接报错提示有进程在占用磁盘),然后执行:

VBoxManage modifymedium disk "你的磁盘文件或UUID" --resize 51200

这里的51200单位是 MB,也就是 50GB。注意,网上老帖子可能会写VBoxManage modifyhd,在新版 VirtualBox 里这个命令也能用,只是官方更推荐用modifymedium,因为modifyhd只能处理磁盘文件路径,处理 UUID 或不同介质类型时不如modifymedium灵活。

关键问题是:到底该填多少?很多人在这里算错。

VirtualBox 的 resize 参数单位是 MiB(也就是 1024 * 1024 字节),不是很多人以为的 1MB = 1000KB。如果你想扩到 100GB,最严谨的算法是100 * 1024 = 102400。但问题是,你在客户机操作系统里用 fdisk、磁盘管理看容量时,看到的往往是十进制换算后的结果。比如你想要 Windows 里显示 100GB,可能填 102400MB 之后,Windows 看到的是 100GB 左右;如果你填 100000MB,Windows 看到的会是 97.6GB 左右。不能说哪个是错的,关键是你在扩容前先在客户机里看清自己白己的"当前容量"和"期望容量"到底差多少,按差值 + 余量来算,而不是拍脑袋填数字。

我个人的习惯是给余量。假设当前磁盘 40GB,打算扩到 120GB,目标是多 80GB 空间。填--resize 122880?不对,这不是简单在 40 的基础上加 80。我先明确目标总容量:120GB,计算得到120 * 1024 = 122880,然后执行--resize 122880。

为什么建议多给一点余量,而不是"刚好够用"?因为 Linux 根分区扩容时,parted、resize2fs 对分区表对某块区域的边界有一定要求,如果分区表结束位置恰好卡在磁盘末尾附近,某些工具判断会有调整空间为 0 的尴尬情况。多出一点空间不会影响使用,反而能让后面的分区调整过程更顺畅。

另外注意,扩容是针对"整块虚拟磁盘"的,不是针对某个分区。好比把一个箱子的外壳做大了一圈,但里面的隔板还留在原来的位置,这就是为什么扩容后客户机里看不到变化——分区还没动,文件系统更没动。别急着骂 VirtualBox 没生效,它只是完成了它该做的"扩大箱子"这一步,剩下的"重新隔断",需要我们进客户机处理。

执行完 resize 命令后,可以用VBoxManage showhdinfo "磁盘文件或UUID"确认容量是否已更新。如果输出中的容量变大了,说明 VirtualBox 这一层已经搞定。

3. 扩容后客户机看不到新空间?分区表才是关键

这是我见过最多人卡住的一步。VirtualBox 层面扩容成功后,开机进系统,打开"我的电脑"或df -h,发现空间居然一点没变。原因很简单:虚拟磁盘虽然变大了,但磁盘上的分区表依然只认识原来的那一小段区域,多出来的空间还没有被分配给任何分区。

这里的核心概念是分区表有两个时代:MBR 和 GPT。

MBR 是老一代分区表,多见于 Windows 7 以及早期 Linux 系统。MBR 支持的最大磁盘是 2TB,最多 4 个主分区。如果你的虚拟磁盘扩容后总容量超过 2TB,但分区表还是 MBR,那多出来的空间会非常尴尬——你建新分区可能建不了,主分区也扩展不到 2TB 之外。解决办法是转成 GPT,但这个操作有风险,不建议新手直接在数据盘上做,系统盘更麻烦。

GPT 是现代分区表,支持大容量,没有 4 个主分区的限制。Windows 10/11 和新的 Linux 发行版默认基本都是 GPT。GPT 下扩容分区通常更顺利,只要分区表里有空闲空间,就可以用工具把分区边界往后推。

具体到操作层面,你需要分两种情况处理:

第一种情况:你只想把新空间做成一个全新的独立分区,比如在 Windows 里出现一个新的 D 盘,或者 Linux 里挂载一个新的 /data。这种情况下,你不需要动原来那个系统分区分区表,只需要在空闲空间上新建成一个分区、格式化、挂载即可。这种做法安全、简单,尤其适合数据盘。

第二种情况:你希望把新空间直接合并到现有的系统分区或者数据分区,比如 C 盘从 40GB 变成 120GB,或者 Linux 的根目录 / 直接变大。这种情况需要先扩大分区表里的分区边界,然后再扩大分区内的文件系统。整个过程有先后顺序:先分区表,后文件系统,顺序搞反一定报错。

为什么必须先分区后文件系统?因为文件系统是搭在分区之上的,分区多大,文件系统才能"管理"多大。很多人在 Linux 里直接resize2fs /dev/sda1,结果提示 nothing to do,就是因为分区本身没变大,文件系统自然无处可扩。

在我处理过的案例里,Windows 客户机相对友好一点。Windows 的"磁盘管理"控制台(diskmgmt.msc)能看到扩展卷选项,只要磁盘尾部有未分配空间,右键点击现有分区选择"扩展卷"就能直接把空间并进来。但也有坑——如果你的系统分区之后夹着一个恢复分区,扩展卷按钮就会是灰色,因为未分配空间没有紧挨着系统分区。这种时候你需要用第三方分区工具,比如 DiskGenius 这类工具去移动分区位置,或者干脆放弃合并,把新空间建独立分区。

Linux 的情况更依赖具体分区工具,因为不同场景用的工具不同。如果分区表是 MBR,常用的工具是 fdisk;如果分区表是 GPT,可以考虑 parted、gdisk,或者新一代的 growpart 工具配合 LVM 使用。我用得最多的是growpart+resize2fs这套组合拳,尤其是扩容云镜像、Vagrant box 时几乎屡试不爽。

4. Windows 与 Linux 客户机的分区扩容实操

4.1 Linux 客户机:growpart 与 resize2fs 组合

先说说 Linux 下的扩容流程,这里以一个常见的 Ubuntu/Debian 系统为例。假设虚拟磁盘/dev/sda从 40GB 扩容到 120GB,原来的根分区是/dev/sda1,分区表类型是 GPT。

先确认当前分区情况:

sudo parted /dev/sda print free

这个命令会打印磁盘的分区布局,包括空闲空间的位置。执行后你可能会看到分区 1 后面有一段"空闲空间",这就是我们扩容时多出来的那 80GB。注意 free 输出中的 Start 和 End 位置,后面会用到。

接着确认文件系统类型:

df -hT /

如果是 ext4 就继续往下,如果是 XFS,扩容命令要换成xfs_growfs,不能使用 resize2fs。

然后执行 growpart 扩容分区:

sudo growpart /dev/sda 1

growpart 的用法是:磁盘路径 + 分区号,中间有空格,别把/dev/sda1整个传进去。它会自动读取磁盘大小,把分区 1 的结束边界推到这个新磁盘的末尾。执行成功后,如果你再次运行parted /dev/sda print free,会发现空闲空间消失了,分区已经顶到磁盘末尾。

最后扩大文件系统:

sudo resize2fs /dev/sda1

resize2fs 检测到分区变大了,就会自动把文件系统扩展到整个分区。运行完再df -h /,你会发现根目录容量已经更新。

如果你的系统用了 LVM(逻辑卷管理),会稍微多两步。先sudo pvresize /dev/sda1让物理卷感知新空间,然后sudo lvextend -l +100%FREE /dev/mapper/你的卷组-你的逻辑卷,最后再对文件系统做扩展,ext4 用resize2fs,XFS 用xfs_growfs。LVM 的好处是以后想再扩容量,不用像操作裸分区那样小心翼翼,其实这也是我推荐服务器虚拟机从一开始就上 LVM 的原因。

4.2 Linux 客户机:如果是 XFS 文件系统

说个真实场景。我之前扩容一台 CentOS 7.9,根分区文件系统是 XFS,结果执行resize2fs直接给我报错:Couldn't find valid filesystem superblock。当时我一拍脑袋才想起来,XFS 的工具链完全不同。

XFS 的扩容命令是这样的:

sudo growpart /dev/sda 1 sudo xfs_growfs /

xfs_growfs的挂载点和resize2fs的设备路径参数不同,它直接传入挂载点即可,文件系统会在线扩。整个过程不需要卸载分区,生产环境也能用。

所以动手前,一进系统先看文件系统类型,比什么都重要。lsblk -f可以一次性显示磁盘、分区和文件系统类型,推荐先跑这条命令。

4.3 Windows 客户机:磁盘管理扩展卷

Windows 的流程要省心不少,但也有它自己的坑。

在虚拟机里按Win + X,选择"磁盘管理",找到你的虚拟磁盘。如果磁盘布局是简单的单分区+后面未分配空间,右键分区选择"扩展卷",按向导一路下一步,搞定。

但真实世界没这么顺利。我扩容过一台 Windows Server 2019,系统盘后面怼着一个 500MB 的恢复分区,坑就来了:C 盘的扩展卷按钮是灰色的,因为未分配空间和 C 盘中间隔了个恢复分区,Windows 不允许跨分区合并。后来我把恢复分区删掉才扩成功,但这种操作有风险——恢复分区用于系统修复启动,删掉后某些恢复工具会失效。

另一种常见坑是:Windows 磁盘管理里显示的未分配空间"在磁盘末尾",但虚拟机的系统分区前面有个系统保留分区(System Reserved),导致盘符总是变来变去。处理起来比较繁琐:要么用第三方工具,要么干脆把系统保留分区的盘符取消挂载。遇到这种问题,别死磕磁盘管理,直接用 DiskGenius 这类图形工具,它会给你一个可视化的分区条,拖拽边界即可,比系统自带的工具好理解得多。

我建议在扩容一台上古 Windows 7 虚拟机之前,先检查 MBR 与 GPT:如果磁盘是 MBR 且容量已经将要超过 2TB,那么你最好提前规划是否转为 GPT,别等扩容完措手不及。

4.4 Vagrant 虚拟机扩容的特别提醒

很多人的 VirtualBox 不是直接装的,而是跟着 Vagrant 跑的。Vagrant 管理虚拟机时,默认会创建一个动态 VDI 磁盘挂在默认路径。扩容前,你需要先vagrant halt彻底关机,再用VBoxManage list hdds找到对应的 VDI 文件路径,执行 resize。之后启动虚拟机再按前面 Linux/Windows 的流程处理分区。

这里有个易错点:Vagrant box 的默认磁盘通常很小(很多只有 10GB 或 20GB),而云镜像的根分区可能是 LVM 或普通 ext4,处理方式差异很大。Vagrant 官方其实没有专门支持在 VirtualBox provider 下自动扩盘,很多 box 里甚至没有预装 growpart,需要你自行apt install cloud-guest-utils或yum install cloud-utils-growpart。

5. 扩容过程中容易踩的坑与处理办法

这一节我把它当成避坑清单,把我踩过的、身边朋友反复踩的坑都列出来,希望你不用经历第二次。

5.1 带快照扩容导致启动失败

快照就像时光机,每次快照都记录了一个"时间点"上的磁盘状态。问题是,如果你在带快照的情况下扩容,磁盘链中某一个节点的容量信息会变得不一致,某些场景下虚拟机会卡在启动界面甚至直接报:"Parent disk does not match the size of the medium"。

碰到这个报错,处理方式有两条:

  1. 把快照全部删除(这会丢失快照之后的状态变化,但至少保住当前系统);
  2. 用VBoxManage clonehd把当前状态导出成一个全新的 VDI,再对克隆后的磁盘做扩容,这样安全但需要额外空间。

我最推荐的是从源头避免:扩容之前留出一段维护窗口,先检查快照,能删就删,不能删就把虚拟机导出备份,再重新导入。数据无价,虚拟机的数据也一样。

5.2 resize 后宿主机文件大小没变大

前面提到过,动态分配的 VDI 扩容后,文件大小不会立刻膨胀。你要看的是逻辑容量,而不是文件物理大小:

VBoxManage showhdinfo "你的vdifile"

看Capacity字段有没有变大。如果容量已经变大,那就说明 VirtualBox 没问题,问题在客户机分区表。如果容量没有变化,检查一下你是不是执行 resize 时还开着虚拟机,或者命令里填错了磁盘 UUID。

填错 UUID 这个坑,我也踩过——VBoxManage list hdds输出好几行,每一行都有一个 UUID,其中Location是你的文件路径。复制 UUID 时一定要对应到正确那行,否则你扩容的是另一块磁盘,还以为是原盘,折腾半天发现容量没变。

5.3 新空间分配不到现有分区上

growpart 报错unexpected input或者no space left on partition table,通常是分区表的空闲区域不连续,或者磁盘末尾正好被一段保护性的元数据占住。这种情况下可以借助 parted 的交互模式:

sudo parted /dev/sda (parted) resizepart 1 100% (parted) quit

对于某些特殊情况(比如前面有一堆小分区的 GPT 盘),resizepart 比 growpart 更灵活。但注意,resizepart 直接改分区边界,万一磁盘上有其他分区,务必定向到正确分区号和边界。

5.4 磁盘扩容后虚拟机无法启动

这种情况多半发生在"文件系统大小与分区大小不一致"的时候。Linux 的内核挂在根分区时,如果分区信息里文件系统的 metadata 与实际大小不符,可能直接 kernel panic。此时先从宿主机挂载虚拟磁盘检查一下(用VBoxManage clonemedium克隆出一份再挂载,或者进 Live CD 修复),不要裸奔直接启动。

我自己的习惯是:先克隆一份,再对克隆体做测试扩容。测试通过再对原盘操作,虽然多花点时间,但安全得多。尤其是生产环境里存着数据库、代码、几百 GB 数据的虚拟机,千万别省这一步。

5.5 为什么 VMDK 扩容后会有额外的坑

如果你用的是 VMware 迁移来的 VMDK,VirtualBox 虽然可以读写它,但涉及到扩容时有一个著名的限制:VirtualBox 不能扩张 VMDK 文件在 VMware 中创建的某些变体格式,比如 split(分卷)或者 streamOptimized。如果你拿到的 VMDK 是这样一种格式,VBoxManage modifymedium会直接报错"cannot resize this medium"。

解决办法就是先转换格式:

VBoxManage clonemedium "源.vmdk" "目标.vdi" --format VDI

转换出来一份 VDI 之后,再对 VDI 做扩容,这也是最稳妥的办法。从这里也能看出,VDI 在 VirtualBox 生态里兼容性最好,新部署的环境建议直接用默认的 VDI 格式,少给自己找麻烦。

5.6 扩容后客户机磁盘空间显示没有变化

我在 VMware 相关热词里看到有人问"为什么 vmware 调整磁盘大小后,实际没有变化",其实 VirtualBox 完全一样。这类问题的排查顺序我按优先级列一下:

  1. 确认 VirtualBox 层 Capacity 已变化;
  2. 确认客户机系统已经"看到"大磁盘:lsblk或者磁盘管理里磁盘的总容量;
  3. 确认分区表里是否有多余空闲空间:parted print free;
  4. 确认文件系统是否已扩展到分区边界:df -hT。

只要这四步逐一排查,90% 的问题都能定位到具体卡在哪一个环节。别跳步骤。

6. 关于缩小磁盘与格式转换的补充经验

很多人会在扩容之后问我:既然能扩大,能不能缩小?这里我直接泼盆冷水——VirtualBox 官方不支持在线缩小虚拟磁盘。`.

如果你确实需要缩小,常规做法是:

  1. 在客户机内部先缩小文件系统,比如 ext4 用resize2fs /dev/sda1 20G;
  2. 然后用分区工具把分区边界缩小到 20G 左右;
  3. 最后用 VBoxManage 把磁盘缩小,但仅支持 VDI 且只能缩小到分区实际位置之后,误差较大;
  4. 更常见的方式是:VBoxManage clonemedium --variant Fixed克隆一份固定大小 VDI 文件,新文件只包含实际数据量,等于间接压缩。

我最推荐的是最后一种:克隆。因为克隆的过程中 VBoxManage 会重新分配块,不只清理掉无用的空洞,还能把分区时留下的碎片整理一遍,原文件和新文件的体积差会很明显。克隆完再检查一遍新盘启动是否正常,然后删旧盘。

说到格式转换,日常运维里有两个常见场景:

  • 给虚拟机从 VMware 迁移到 VirtualBox:VBoxManage clonemedium "source.vmdk" "target.vdi" --format VDI;
  • 给虚拟磁盘从 VDI 转换成 VMDK 以便在 VMware 中使用:参数反过来即可。

格式转换和扩容可以同时进行吗?可以。先 clone 格式转换,再对转换后的文件 resize,或者反过来都行,最终容量一致即可。只是注意转换过程会占宿主机空间,临时文件的大小可能跟原磁盘一样大,别忘了留足硬盘空间。

再补充一个小技巧:如果虚拟机安装在 SSD 上,而且动态 VDI 文件已经膨胀到很大,很多空间其实已经被删除的文件占了,那么执行一次VBoxManage modifymedium --compact可以清理 VDI 文件内部的空闲扇区,文件体积会明显减小。但前提是客户机里需要先做一次"零填充"——Linux 下执行dd if=/dev/zero of=/tmp/zero bs=1M直到磁盘满,然后删除该文件;Windows 下可以用 sdelete 工具的-z参数完成。这一步做完再--compact,动态 VDI 的体积能缩回很可观的幅度。

最后说个实际体验。帮别人处理虚拟机磁盘扩容问题多了以后,我发现一个规律:十个案例里有六七个都是卡在"VirtualBox 层的 resize 做了、客户机层的分区文件系统调整没做"这道坎上;剩下两三个是快照没处理;真正遇到磁盘格式、VMDK 不兼容等硬问题的比例反而很低。这说明扩容这件事本身并不复杂,难点在于脑子里的模型要清晰:虚拟磁盘、分区、文件系统是三个不同层级的东西,逐层处理,每层都确认到位,就不会翻车。

动手之前多做一点检查,比事后抢救要省心太多。不管你是用 VirtualBox 跑开发环境、测试环境,还是生产服务,磁盘扩容都是一件高频但操作门槛偏高的维护动作。希望这篇里踩坑经验能帮你绕开那些不必要的问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询