☰
虚拟机Linux磁盘扩容全攻略:从VMware到文件系统一步到位
2026/10/8 2:54:15 网站建设 项目流程

在虚拟机里跑Linux,我最怕看到的画面不是服务挂了,而是df -h刷出来一行红字,容量直接100%。前阵子VMware里一台Ubuntu服务器跑着跑着突然写不进日志,nginx报错、定时任务全卡住,一查就是根分区被占满了。当时第一反应是清理垃圾,但清完发现底层的虚拟磁盘本身已经不够用——这时候最彻底的解法就是给虚拟机做磁盘扩容。

很多朋友以为“虚拟机Linux磁盘扩容”就是把VMware的硬盘调大然后开机完事,实际上这只是一个起点。完整链路涉及三层:虚拟化层(把虚拟磁盘调大)→ 分区层(让分区表用上新空间)→ 文件系统层(让文件系统真正吃到容量),任意一层漏了都会出现“硬盘明明调大了但系统里还是老容量”的迷惑现象。这篇文章就按这个链路把每一步讲透,同时把容易翻车的细节和我实战中踩过的坑一并放出来,适合所有在用VMware、VirtualBox或KVM跑Linux的运维和开发朋友参考。

1. 先给磁盘做“体检”:搞清楚满在哪、当前是什么分区方案

扩容之前一定要先诊断,这不是走流程,而是为了避开后面的大坑。很多人在没弄明白分区表类型、文件系统类型、是不是LVM的情况下直接下手,结果扩容到一半发现方式和预期完全不一样,甚至把数据搞丢。

1.1 用df和du定位真实占用情况

第一步永远是df -Th,注意带上-T参数,可以顺带显示文件系统类型:

df -Th

输出里能看到所有挂载点、容量、已用、可用和文件系统类型。我先看到/dev/sda2挂载在/,ext4,容量占满。这里要区分两种情况:一种是磁盘本身还有剩余空间,只是某个目录特别大;另一种是分区容量确实到了上限,比如根分区只有20G但数据已经19.8G。

如果磁盘整体还有空间但某个分区满了,优先用du找到大目录:

sudo du -sh /var /home /tmp /var/log /opt /usr 2>/dev/null | sort -h

我在生产环境里最常见的大户是/var/log(journald日志不清)、/var/lib/docker(容器镜像和overlay2堆积)、/home下的构建缓存。实在挤不出空间再考虑扩容,因为扩容虽然是常规操作,但能少一次就少一次。

1.2 判断分区布局与文件系统类型

看结构用lsblk -f,这个命令会输出块设备树、挂载点、文件系统类型和UUID:

lsblk -f

这是判断“接下来走哪条路”的关键。常见情况有三种:

  • 非LVM、单一根分区:比如/dev/sda2直接挂载到/,扩容目标是把sda2分区扩大,再扩文件系统。
  • LVM逻辑卷结构:输出里能看到─ubuntu--vg-ubuntu--lv之类,实际挂载在/的设备可能是/dev/mapper/ubuntu--vg-ubuntu--lv,这时候分区层只要pvresize,然后把逻辑卷扩大,再扩文件系统。
  • 多分区表MBR/GPT:fdisk -l可以判断分区表类型。

再配合pvdisplay、vgdisplay、lvdisplay确认LVM的信息:

sudo pvdisplay sudo vgdisplay sudo lvdisplay

1.3 为什么这个预判能避免白折腾

因为Linux扩容在不同场景下命令完全不同:

  • ext4文件系统用resize2fs,xfs要用xfs_growfs,两者混用大概率报错。
  • 不是LVM的话,分区层要用growpart或fdisk手动扩分区;LVM则必须执行pvresize,顺序错了逻辑卷也看不到新空间。
  • 分区表是MBR还是GPT,会直接影响fdisk操作时的警告和步骤,GPT分区表在删除重建时容易出现备份表不同步的问题。

我见过一位朋友在非LVM的Ubuntu Desktop上直接敲lvextend,系统提示找不到逻辑卷,他还以为是命令没安装。其实只要lsblk -f看一眼是sda2直挂还是mapper设备,就全明白了。所以这一步别省,两分钟的事,后面能省两个小时。

2. 虚拟化层扩容:先把“虚拟硬盘”本身做大

确认好结构后,第二步是回到宿主机,把虚拟磁盘的总容量调大。这一步不涉及Linux内部操作,但在不同的虚拟化平台上细节略有差异。

2.1 VMware Workstation/Player的扩展操作

VMware系列我用得最多,操作路径如下:

  1. 关闭虚拟机(必须关机,VMware不支持在开机状态下扩展虚拟磁盘)。
  2. 右键虚拟机 → 设置 → 硬盘 → 实用工具 → 扩展。
  3. 输入目标磁盘大小,注意是“最终总大小”,不是“增加多少G”。比如原来是40G,想加20G,这里填60G。
  4. 等待VMware完成扩展,完成后点确定。

如果是纯命令行环境,可以用vmware-vdiskmanager:

vmware-vdiskmanager -x 60GB /path/to/vmdisk.vmdk

-x表示扩展磁盘,目标大小写清楚单位。这个命令扩展VMDK在虚拟机离线状态下执行。

2.2 VirtualBox与KVM/libvirt的对应操作

VirtualBox扩展比较简单,路径是:菜单栏“文件” → “虚拟介质管理器” → 选中虚拟磁盘 → “属性” → “大小”,拖动滑块或直接输入新容量,点应用。VirtualBox对VDI格式支持在线调整,但我仍习惯在关机状态下操作,稳一点。

KVM/libvirt环境用qemu-img:

qemu-img resize /var/lib/libvirt/images/ubuntu.qcow2 40G

qcow2格式同样要注意目标总大小。调整完虚拟机的XML不需要改,因为磁盘大小由镜像文件控制。部分图形化界面(virt-manager)也能在磁盘属性里直接调整。

2.3 扩容前务必做的两件事:快照与备份

说到这必须强调:在虚拟化层调大磁盘之前,先拍快照或备份分区表。VM虚拟磁盘的调整虽然极少失败,但一旦失败往往伴随分区表不可读,而对生产环境来说,最贵的不是磁盘空间,是恢复可用状态的时间。VMware里直接在开机前为虚拟机拍一个快照;VirtualBox可以在“生成备份”里做当前状态备份。哪怕是个人测试机,我也建议花这一步。

另一个容易被忽略的是宿主机的磁盘剩余空间。扩展虚拟磁盘时,VMware会在宿主机上为新增长度分配块,如果宿主机本身磁盘快满了,扩展可能完成得极其缓慢甚至失败。我自己遇到过宿主机只剩1.2G空间强行扩展20G,卡了半小时最后报错的情况。所以先看一眼宿主机的df -h,留足余量再动手。

3. 分区层处理:让Linux内核“看见”新增空间

虚拟化层做完,绝大多数人会直接开进系统看容量——然后疑惑“怎么还是老样子”。这很正常,因为虚拟磁盘变大了,但Linux的分区表里,分区的边界还停留在原来的位置,系统不会自动把新空间并进已有分区。这一步要处理的是分区表。

3.1 新空间为什么不会自动生效

用lsblk看一下就能发现规律:磁盘整体大小已经变成60G,但/dev/sda2分区还是40G,后面多出来的20G显示为未分配空间。内核虽然知道磁盘变大了,却不知道这个“新区域”应该属于哪个分区。所以需要把分区的物理边界往后推,才能让分区用满新空间。

方案有两种:一是用growpart自动调整分区边界,推荐优先;二是用fdisk手动删除分区再重建,操作得当也可靠,但风险略高。

3.2 growpart一步扩展分区边界(推荐)

在Ubuntu等系统上,先安装工具:

sudo apt update && sudo apt install -y cloud-guest-utils

然后执行:

sudo growpart /dev/sda 2

注意命令格式是growpart [磁盘] [分区号],中间没有/dev/前缀。执行后可以看到类似“CHANGED: partition=2 start=... old size=... size=...”的输出。

如果磁盘是GPT分区表,growpart可能会提示需要修正备份分区表,确认即可。执行完用lsblk检查分区大小是否已经变化。growpart的本质是自动计算新的结束扇区并改写到分区表,全过程不需要手工输入数字,能最大程度避免人为失误。

3.3 手动fdisk删除重建分区的老办法

有些老系统没装growpart,又不方便联网安装,这时可以用fdisk手动操作。过程不复杂,但有一个红线:重建分区时,起始扇区必须和原来一致。

sudo fdisk /dev/sda

交互过程如下:

  1. p查看当前分区表,记下目标分区的“起始扇区”和“结束扇区”。
  2. d删除分区(如果只有一个分区就是2,按实际输入分区号)。
  3. n新建分区,分区号保持原来一致。
  4. 起始扇区直接回车使用默认值——这时默认值通常就是刚才删除前的起始扇区,只要确认没变就行。
  5. 结束扇区直接回车使用默认值(最大可用空间),或输入新的大小。
  6. 如果提示是否移除签名(signature),选N,不删除分区上的文件系统标记。
  7. w保存退出。

保存后用partprobe /dev/sda刷新分区表,或直接重启。这里一定要强调:fdisk法最危险的步骤就是重启后分区UUID变了。MBR分区表删除再重建时,分区系统ID和UUID可能变化,如果/etc/fstab里用UUID挂载,很可能开机直接进emergency mode。所以不是万不得已,我优先用growpart,因为它只改结束边界,不重算UUID。

3.4 LVM场景的专属分区处理路径

如果lsblk -f看到的是LVM结构,比如Ubuntu Server默认的ubuntu--vg-ubuntu--lv,那分区层只需做一件事:把物理卷扩展到新分区边界上。

sudo pvresize /dev/sda2

这里假设/dev/sda2是LVM物理卷所在分区。执行后pvdisplay或pvs能看到Physical Volume的PE数和大小已经变化。如果分区本身还没扩展(比如growpart没跑),那pvresize扩的也只是分区内已有空间,所以LVM场景下正确的顺序是:

  1. growpart /dev/sda 2扩展分区边界
  2. pvresize /dev/sda2让物理卷感知新空间
  3. lvextend -l +100%FREE /dev/mapper/xxx把空闲空间全部分配给逻辑卷
  4. 扩容文件系统(下一步)

这里有个小细节:lvextend可以只加一部分而不是全加,比如lvextend -L +10G /dev/mapper/xxx。生产环境里我喜欢预留一部分空间在卷组里,方便以后某个卷紧急扩。不过测试环境直接+100%FREE最省事。

3.5 分区表操作遇到的警告与应对

扩分区时最常见的一个提示是GPT分区表的警告:GPT PMBR size mismatch或Not all of the space available to /dev/sda appears to be used...。遇到这种提示别慌,通常意味着分区表和实际磁盘大小不一致。最稳妥的做法是用gdisk或parted修复。

用gdisk修复很简单:

sudo gdisk /dev/sda

进入交互界面后,输入w写回分区表,它会自动修正备份GPT表,然后退出。这里注意,gdisk的w操作会直接保存,前提是你确认当前分区表内容没毛病。

4. 文件系统层收尾:ext4和xfs必须分开处理

分区边界扩展完了,逻辑卷也大了,但文件系统本身还不知道,最后一步是让文件系统用满新空间。这一步的坑最多,因为ext4和xfs的操作命令完全不同。

4.1 ext4系:一条resize2fs在线搞定

Ubuntu Desktop和很多Debian系默认用ext4。对于ext4,直接在线执行:

sudo resize2fs /dev/sda2

如果分区结构是LVM,设备路径就是/dev/mapper/xxx:

sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv

resize2fs默认会扩展到设备的最大可用空间,输出会显示文件系统从多少block扩到了多少block。ext4的好处是支持在线扩容,挂载状态下执行没问题,这也是我用它做根分区时的首选。

4.2 xfs系:只能用xfs_growfs,且不支持缩容

红帽系(RHEL/CentOS/Rocky)默认用xfs,很多朋友会下意识敲resize2fs,然后收到“resize2fs: Bad magic number in super-block”之类的报错,这时候应该用xfs专用命令:

sudo xfs_growfs /

注意xfs_growfs的参数是挂载点,不是设备路径。也可以指定设备:

sudo xfs_growfs -d /dev/mapper/centos-root

-d表示扩大到最大值,xfs在线扩容没问题,但xfs不支持缩容,这个特性在规划磁盘大小时要想好,一次性给够空间,避免后面要缩回来。

下面这个表每次遇到都值得贴出来参考:

文件系统扩容命令是否支持在线是否支持缩容
ext4resize2fs /dev/xxx支持支持(离线)
xfsxfs_growfs /挂载点支持不支持
btrfsbtrfs filesystem resize max /支持支持
swapswapoff后重新mkswap否可重做

4.3 LVM与文件系统的完整组合流程演示

以一台Ubuntu Server(LVM + ext4)为例,完整命令串如下,方便直接套用:

# 1. 扩展分区边界 sudo growpart /dev/sda 2 # 2. 让物理卷感知新的分区大小 sudo pvresize /dev/sda2 # 3. 逻辑卷使用卷组中所有剩余空间 sudo lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv # 4. 扩展文件系统到最大 sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv # 5. 验证 df -Th

如果是RHEL系xfs,把第4步换成:

sudo xfs_growfs /

注意逻辑卷设备路径可能带--,比如ubuntu--vg-ubuntu--lv,这是因为卷组和逻辑卷名里含有-时会转义成双连字符,以lsblk显示为准。

4.4 顺带处理swap分区扩容

很多虚拟机初始只有2G的swap,跑编译或大数据任务时经常被打满。swap扩容和根分区扩容是两条路径,但可以一起做。思路是:先建一个新的swap分区(或用swap文件),启用后移除旧分区。简单的方法是swap文件,无需动分区表:

sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile

持久化写入/etc/fstab:

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

如果想复用原来的swap分区,流程是swapoff /dev/sda3→fdisk删除旧swap分区重建出更大分区(或growpart)→mkswap /dev/sda3→swapon /dev/sda3,同时记得更新/etc/fstab里的UUID。swap分区扩容中间有一次交换空间清零,对内存吃紧的机器要挑业务低峰操作。

5. 扩容后的验证与翻车实录

扩容完成并不意味着结束,必要的验证和几个高频翻车点我专门放在这节讲。毕竟我这些经验都是真金白银换来的。

5.1 怎么确认扩容真正成功

判断成功的标准有三个,全部满足才算完成:

lsblk -f # 分区大小正确 df -Th # 挂载点容量显示新大小 mount | grep ' / ' # 挂载参数正常,UUID没有漂移

如果df里显示的还是旧容量,最大可能是文件系统层没执行到位;如果lsblk里分区大小没变,说明分区层没执行成功。按这个顺序倒查,能快速定位问题在哪一层。

5.2 “resize2fs: Device or resource busy”是什么意思

我见过不少朋友扩容LVM时卡在这里。其实报错的意思是设备忙,文件系统无法安全调整。ext4在挂载状态下通常能在线扩容,但某些情况(比如挂载选项带nouser_xattr等特殊参数)或对根文件系统时,仍可能提示busy。处理办法:

  1. 先确认是不是命令用错了设备,比如拿/dev/sda2在LVM环境扩,设备其实应该是mapper路径。
  2. 如果是普通分区且能卸载,可以启动到live环境离线resize,但虚拟机场景重启又快,没必要非得在线。
  3. 如果确实要在线,检查挂载参数,必要时先mount -o remount,rw /dev/xxx /再试。

实际上对根分区最省事的方式是:确保分区层已经扩好,直接用resize2fs在线扩,绝大多数ext4都没问题。这个报更多出现在xfs文件系统被错误执行resize2fs,报错类型不一样但同样让人头大。

5.3 GPT备份表不一致导致的认盘异常

有次我用fdisk手动扩展GPT分区,保存时报了一堆警告,重启后系统差点起不来,原因就是备份GPT表还保留旧结构。应急修法是用gdisk修复:

sudo gdisk /dev/sda

进入后不用改任何设置,直接输入w,它会自动重建备份GPT表。如果系统卡在grub界面,还能用e2fsck修复文件系统。

这也就是为什么我前面强调growpart优先——它对GPT的处理更规范,手动fdisk虽然能成,但每多一次手工操作,就多一分风险。

5.4 扩容完成后fstab失效的经典问题

MBR分区表删除重建之后,分区的UUID可能变了,/etc/fstab还按旧UUID找设备,开机直接失败。遇到这种情况,先用live系统或紧急模式把根分区只读挂载起来,查看blkid拿到新UUID,然后更新/etc/fstab。

更好的办法是从一开始就避免:如果fstab里用的是UUID而不是设备路径/dev/sda2,手动fdisk重建分区前一定要把原UUID记下来,重建后用mkswap -U或直接保留原分区类型重新指定UUID。ext4可以这样保留:

sudo tune2fs -U <原UUID> /dev/sda2

但我真实建议还是优先growpart,它不会改变分区UUID,省掉这整个风险。

5.5 一些实操中的小习惯与体会

我个人的习惯是:给虚拟机扩容前,先用lsblk -f > disk_layout.txt把分区结构存一份档,真的出问题时能对照找回原始布局。扩容顺序一定是“先快照、再虚拟化层、再分区层、再文件系统层”,每一步用对应的命令验证一次,不要一股脑全部跑完。很多朋友一次跑完所有命令,中间某一步失败后反而不知道去哪排查。

最后再分享一个小技巧:如果虚拟机里跑的是Docker,扩容后记得看下/var/lib/docker占用,docker的overlay2层经常占用超出预期。有时候“磁盘满了”不是容量不够,而是镜像和日志堆积——先清理再扩容,能让扩容这件事的效果维持更久。扩容不是万能药,量出为入、定期清理,才是虚拟机Linux长期稳定运行的核心。

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

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

立即咨询