
1. 磁盘扩容前先认清你的虚拟磁盘格式VirtualBox 虚拟机的磁盘一旦提示磁盘空间不足很多人第一反应是去网上搜virtualbox 增加磁盘大小然后照着帖子用 VBoxManage 敲了两条命令结果重启系统发现没有任何变化。其实问题十有八九出在第一步——没有搞清楚自己的虚拟磁盘到底是个什么格式、有没有做快照、磁盘大小计算方式对不对。先说最基础的一个概念VirtualBox 的虚拟磁盘有好几种格式最常见的是 VDIVirtualBox 自家的默认格式、VMDKVMware 虚拟磁盘格式、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 左右如果你填 100000MBWindows 看到的会是 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 使用。我用得最多的是growpartresize2fs这套组合拳尤其是扩容云镜像、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 1growpart 的用法是磁盘路径 分区号中间有空格别把/dev/sda1整个传进去。它会自动读取磁盘大小把分区 1 的结束边界推到这个新磁盘的末尾。执行成功后如果你再次运行parted /dev/sda print free会发现空闲空间消失了分区已经顶到磁盘末尾。最后扩大文件系统sudo resize2fs /dev/sda1resize2fs 检测到分区变大了就会自动把文件系统扩展到整个分区。运行完再df -h /你会发现根目录容量已经更新。如果你的系统用了 LVM逻辑卷管理会稍微多两步。先sudo pvresize /dev/sda1让物理卷感知新空间然后sudo lvextend -l 100%FREE /dev/mapper/你的卷组-你的逻辑卷最后再对文件系统做扩展ext4 用resize2fsXFS 用xfs_growfs。LVM 的好处是以后想再扩容量不用像操作裸分区那样小心翼翼其实这也是我推荐服务器虚拟机从一开始就上 LVM 的原因。4.2 Linux 客户机如果是 XFS 文件系统说个真实场景。我之前扩容一台 CentOS 7.9根分区文件系统是 XFS结果执行resize2fs直接给我报错Couldnt 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。碰到这个报错处理方式有两条把快照全部删除这会丢失快照之后的状态变化但至少保住当前系统用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 迁移来的 VMDKVirtualBox 虽然可以读写它但涉及到扩容时有一个著名的限制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 完全一样。这类问题的排查顺序我按优先级列一下确认 VirtualBox 层 Capacity 已变化确认客户机系统已经看到大磁盘lsblk或者磁盘管理里磁盘的总容量确认分区表里是否有多余空闲空间parted print free确认文件系统是否已扩展到分区边界df -hT。只要这四步逐一排查90% 的问题都能定位到具体卡在哪一个环节。别跳步骤。6. 关于缩小磁盘与格式转换的补充经验很多人会在扩容之后问我既然能扩大能不能缩小这里我直接泼盆冷水——VirtualBox 官方不支持在线缩小虚拟磁盘。.如果你确实需要缩小常规做法是在客户机内部先缩小文件系统比如 ext4 用resize2fs /dev/sda1 20G然后用分区工具把分区边界缩小到 20G 左右最后用 VBoxManage 把磁盘缩小但仅支持 VDI 且只能缩小到分区实际位置之后误差较大更常见的方式是VBoxManage clonemedium --variant Fixed克隆一份固定大小 VDI 文件新文件只包含实际数据量等于间接压缩。我最推荐的是最后一种克隆。因为克隆的过程中 VBoxManage 会重新分配块不只清理掉无用的空洞还能把分区时留下的碎片整理一遍原文件和新文件的体积差会很明显。克隆完再检查一遍新盘启动是否正常然后删旧盘。说到格式转换日常运维里有两个常见场景给虚拟机从 VMware 迁移到 VirtualBoxVBoxManage 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 bs1M直到磁盘满然后删除该文件Windows 下可以用 sdelete 工具的-z参数完成。这一步做完再--compact动态 VDI 的体积能缩回很可观的幅度。最后说个实际体验。帮别人处理虚拟机磁盘扩容问题多了以后我发现一个规律十个案例里有六七个都是卡在VirtualBox 层的 resize 做了、客户机层的分区文件系统调整没做这道坎上剩下两三个是快照没处理真正遇到磁盘格式、VMDK 不兼容等硬问题的比例反而很低。这说明扩容这件事本身并不复杂难点在于脑子里的模型要清晰虚拟磁盘、分区、文件系统是三个不同层级的东西逐层处理每层都确认到位就不会翻车。动手之前多做一点检查比事后抢救要省心太多。不管你是用 VirtualBox 跑开发环境、测试环境还是生产服务磁盘扩容都是一件高频但操作门槛偏高的维护动作。希望这篇里踩坑经验能帮你绕开那些不必要的问题。