上个月一台VMware里的Ubuntu 22.04告警磁盘满了,df -h一看/分区用了92%,虚拟机创建时只给了30G,扩容势在必行。我原以为无非是虚拟机设置里把磁盘拉大、进系统resize一下,结果真正动手才发现,光是把虚拟磁盘从30G加到50G只算第一步——系统能不能识别、分区表怎么处理、文件系统怎么无损扩展,每一步都有坑。这篇就把我在Ubuntu 22.04上做磁盘大小调整的完整过程、方案选型逻辑和踩坑记录梳理出来,给同样被困在“磁盘不够用”里的朋友一个可直接照做的参考。
这篇文章适合几类人:虚拟机里跑着Ubuntu 22.04、磁盘空间吃紧需要扩容的老手;双系统环境下想把Windows分区匀一部分给Ubuntu的新手;还有那些只是想搞清楚“为什么我在VMware里加了磁盘但Ubuntu里看不到”的好奇者。全程不会让你改任何系统文件、不需要重装系统,通过LVM、分区表、文件系统在线扩容这几板斧,把磁盘空间实打实地交还给系统。
1. 扩容前先搞清楚的3件事
1.1 确认你的分区方案:LVM还是普通分区
动手之前,最关键的一步不是做U盘、不是关机,而是先搞明白Ubuntu 22.04安装时的分区方案。这直接决定了后续扩容要用哪套思路。
我见过太多人在论坛里问“为什么我growpart之后resize2fs报错”,结果一看,他用的是LVM逻辑卷,文件系统在逻辑卷上,分区表扩了根本不生效。反过来说,如果你是普通分区方案,却在网上搜了一堆lvextend命令,那也是白忙活。所以第一条建议就是:先看清楚自己的分区类型再动手。
怎么确认?命令很简单:
lsblk -f这条命令会列出所有块设备及其文件系统类型、挂载点。重点关注以下几列:
- NAME:设备名称,比如sda、nvme0n1、sdb
- FSTYPE:文件系统类型,ext4、xfs、swap是常见输出,如果是LVM,你会在这里看到LVM的成员标记
- MOUNTPOINTS:挂载点,/、/home、/boot/efi等
判断方法很简单:如果你的根分区(/)挂载在类似vgubuntu-root这种名称的设备上,或者FSTYPE显示的是LVM2_member,那你的系统就是LVM方案。如果根分区直接挂载在sda2、nvme0n1p2这类物理分区名上,那就是普通分区方案。
还有一个辅助命令可以多层确认:
sudo pvs sudo vgs sudo lvs这三条命令分别查看物理卷、卷组和逻辑卷。如果提示No volume groups或command not found,基本可以断定不是LVM。
ubuntu 22.04默认安装时,如果选择“使用整个磁盘并配置LVM”,就是LVM方案;如果选择“清除整个磁盘并安装Ubuntu”,则是普通分区。我手头这台虚拟机和一台物理机上,两种方案各占一半,扩容逻辑完全不同。
1.2 看你到底缺不缺空间:别急着扩容
很多人一看到磁盘使用率80%就觉得要扩容,其实不一定。扩容虚拟磁盘是个不可逆性较强的操作(虽然可以删快照回退,但步骤繁琐),最好先做一次健康体检,确认是不是真的“没空间了”。
我常用的体检组合:
df -h这是最直观的,看的是文件系统级别的使用率。如果显示/dev/mapper/ubuntu--vg-ubuntu--lv或/dev/sda2挂载在/且使用率超过80%,确实需要关注。
但df显示的是文件系统层面的使用量,它不会告诉你磁盘上有没有大块被删除但没释放的空间。所以接着看:
sudo du -sh /* 2>/dev/null | sort -rh | head -20这条命令把根目录下各一级目录按占用从大到小排列,让你一眼看到谁是空间杀手。我实际排查下来,最常见的几类:
- /var/log下积累的日志文件,动辄几个GB
- docker的overlay2目录,镜像和容器日志能占到几十GB
- apt缓存
/var/cache/apt/archives,长期不清理也有好几个GB - 用户的home目录下的下载文件、虚拟机镜像、conda环境
如果只是日志或缓存占用,那么清理比扩容更划算。比如sudo apt clean清理apt缓存、sudo journalctl --vacuum-size=100M压缩journal日志,通常能释放10-20%的空间。试过的人都知道,清理完再跑一次df,有时候根本不用扩容。
只有当清理完毕、文件系统使用率依然很高,或者业务数据确实在持续增长时,才值得进入下一步。
1.3 备份是底线:快照比任何技巧都重要
这一步我必须放在最前面说,因为真的有人跳过备份直接扩,然后分区表损坏、数据全丢。虚拟机的好处是快照功能成熟,物理机则应该做数据盘或分区级别的镜像备份。
VMware虚拟机扩容前,最稳妥的操作是关机制作快照,或者备份vmdk/vmx文件:
# 如果虚拟机已关机,直接复制虚拟磁盘文件到外部存储 cp -a /vmfs/volumes/datastore1/ubuntu2204/ubuntu2204.vmdk /vmfs/volumes/datastore1/backup/如果你用的是VirtualBox,直接导出OVF或者复制vdi文件也可以。物理机上的Ubuntu 22.04,至少要用rsync把关键数据同步到外部磁盘:
sudo rsync -avxP --exclude='/proc/*' --exclude='/sys/*' --exclude='/dev/*' --exclude='/run/*' --exclude='/tmp/*' / /mnt/backup/备份的意义不是“大概率会用上”,而是“万一出问题你不至于从零开始”。我的原则是:不管操作多简单,只要涉及分区表修改,先备份。
2. 虚拟磁盘扩容实操:从VMware/VirtualBox到系统识别
2.1 虚拟机层把磁盘容量加上去
VMware Workstation和VirtualBox的操作路径虽然不同,思路完全一致:先关闭虚拟机,然后编辑虚拟硬件配置,把磁盘大小从30G改成50G或更大。
VMware Workstation路径:虚拟机菜单 -> 设置 -> 硬盘 -> 实用程序 -> 扩展,输入新的大小。注意,这里必须是磁盘的“总容量”,单位是GB,不支持在线扩展,必须先关机。
VirtualBox路径:选中虚拟机 -> 设置 -> 存储 -> 选中SATA控制器下的磁盘 -> 属性 -> 拖动“大小”滑块或直接输入新容量。同样需要先关机。
还有一个细节:如果你的虚拟磁盘是拆分成多个2GB小文件(split模式),VMware扩展时可能需要一些时间;如果是单个大文件,扩展会快很多。VirtualBox对vdi格式扩容,同样需要关机。
扩展完成后,启动Ubuntu 22.04,此时你看不到任何变化——df -h还是原来的容量。这是正常的,因为虚拟磁盘虽然“变大了”,但磁盘末端的空闲空间还没有被分区和文件系统认领。下一节就是真正关键的部分。
2.2 让内核识别“新磁盘容量”
在Ubuntu 22.04里,有些场景下SCSI设备的热插拔机制会自动感知到磁盘容量变化,但更多时候需要手动让内核重新读取分区表。平时最常用的做法:
sudo partprobe /dev/sda如果partprobe之后lsblk还是显示旧容量,重启一次几乎总能解决问题。较新的ubuntu 22.04内核(5.15及以上版本)对virtio-scsi的支持较好,VMware的pvscsi驱动也没问题,但保险起见关个机再开比什么都强。
确认内核已经识别到新容量的办法:
sudo lsblk如果sda显示的总容量已经是50G,而其中分区sda2还是30G,那就说明内核没问题、分区表还是旧的,接下来只需要扩展分区和文件系统即可。
2.3 分区表扩展:growpart一步到位
以前很多人用fdisk的d+n重建分区,风险高、步骤繁琐。现在Ubuntu 22.04内置了cloud-growpart工具(通常作为cloud-guest-utils的一部分),一行命令就能把分区扩展到磁盘最大容量:
# 以sda2为例,把第2个分区扩展到占满整块磁盘 sudo growpart /dev/sda 2注意,growpart的第一个参数是设备名,第二个参数是分区号,中间用空格分开,不是冒号也不是斜杠。实例执行后,会输出类似:
CHANGED: partition=2 start=... old: end=... new: end=...如果系统提示没有这个命令,先安装:
sudo apt install cloud-guest-utils为什么推荐growpart而不是fdisk?因为growpart会检查分区表的起点是否不变、只向后端扩展,并且自动处理边界对齐,不会出现fdisk手动操作时容易产生的精度误差。growpart对GPT和MBR分区表都支持,如果分区表是GPT,它还会自动更新备份GPT表,省去了手动sgdisk备份恢复的麻烦。
执行完growpart后,再次查看分区信息:
sudo lsblk此时sda2的容量应该已经是50G了,但文件系统还是30G,所以还差最后一步。
3. 文件系统在线扩容:LVM与普通分区实战
3.1 LVM方案:两步扩展逻辑卷和文件系统
如果你在第一阶段确认了系统用的是LVM,那么分区扩容完成后,还需要让LVM“认领”这部分空间,再把空间分配给逻辑卷,最后文件系统才完成扩容。
先看物理卷是否识别到了新分区大小:
sudo pvs输出中PV Size那列,如果还是旧值,需要手动执行:
sudo pvresize /dev/sda2这条命令的作用是把物理卷扩展到分区的新大小。它可能输出Physical volume "/dev/sda2" changed,再跑一次pvs,就应该看到PV Size已经变成50G左右了。
接下来,查看卷组中还有多少空闲空间:
sudo vgsVFree列显示的就是卷组还有多少空间没分配给逻辑卷。如果VFree还是0,说明pvresize没生效;如果空间已经出来,就可以把空间全部加到根分区的逻辑卷上。我这里根逻辑卷叫ubuntu-vg/ubuntu-lv,命令如下:
sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv-l +100%FREE表示把卷组所有空闲空间都分配给这个逻辑卷。也可以用-L +20G指定增加20G,但既然虚拟磁盘已经扩容了,一次性全给更省事。
最后,文件系统在线扩展。ext4用resize2fs:
sudo resize2fs /dev/ubuntu-vg/ubuntu-lv如果文件系统是xfs,用xfs_growfs:
sudo xfs_growfs /Ubuntu 22.04默认ext4较多,但有些定制镜像用xfs,别搞混。
全部执行完,df -h就能看到/分区容量已经变成50G了。
3.2 普通分区方案:resize2fs一路到底
非LVM环境下,分区扩展后文件系统直接在这个物理分区上,所以少了一层LVM的操作。直接用resize2fs扩展ext4文件系统即可:
sudo resize2fs /dev/sda2xfs则是对应:
sudo xfs_growfs /执行resize2fs时,如果文件系统并无错误,通常会输出:
resize2fs 1.46.5 (30-Dec-2021) Filesystem at /dev/sda2 is mounted on /; on-line resizing required old_desc_blocks = ... new_desc_blocks = ... ... The filesystem on /dev/sda2 is now 13107200 (4k) blocks long.这就说明扩容成功了。df -h确认一下,/分区的容量已经更新。
这里要提醒一点:resize2fs执行前最好先做一次文件系统检查。ubuntu 22.04默认启用了systemd的fsck定时检查,但那是重启时干活,手动扩容前跑一次总是心里有底:
sudo e2fsck -f /dev/sda2注意,-f是强制检查,即使文件系统看起来是clean的也会真实扫描一遍。e2fsck执行过程如果出现大量“Inode *** has EXTENTS_FL flag set on file”这类信息,大多是正常输出,只要不是UNEXPECTED INCONSISTENCY就不用慌。如果e2fsck真的报了文件系统错误,先别急着resize,得先修复,否则可能越扩越糟。
3.3 在线扩容 vs 离线扩容:什么时候必须重启
我上面写的所有步骤都是“在线”完成的——分区在挂载状态下直接扩容,不需要启动Live USB、不需要卸载根分区。这是Ubuntu 22.04下最省事的方式,也是我推荐的首选方案。
但有几个场景必须转为离线操作:
- 根分区文件系统损坏,resize2fs拒绝在线扩展
- 扩展的是swap分区,swapoff后再swapon即可,不需要重启
- 修改了/boot分区所在的扩展分区结构,尤其是MBR+扩展分区的老式布局,growpart可能无法在线操作
在线扩容最大的前提是growpart能顺利完成任务。如果分区正好是磁盘最后一个分区,growpart几乎不会失败;如果后面还有其他分区(比如恢复了系统自带恢复分区),growpart可能放弃扩展,因为把中间分区向后挪需要移动数据,这种高级操作不在growpart的能力范围内,需要借助GParted Live CD的图形化拖拽。所以,如果lsblk看到目标分区后面还有分区,别硬上,老老实实做离线调整。
4. 双系统与物理机场景:Ubuntu 22.04怎么调整分区
4.1 双系统下给Ubuntu“匀”空间的完整流程
双系统(Windows+Ubuntu 22.04)的情况比虚拟机复杂一个维度:你需要先压缩Windows分区,再把腾出来的空间转给Ubuntu分区。这一过程如果操作顺序不对,轻则分区表混乱,重则Windows无法启动。
最稳的流程是这样的:
先在Windows里用自带“磁盘管理”收缩卷,或者用DiskGenius等工具把C盘(或数据盘)尾部空间腾出来。收缩出来的空闲空间不要急着创建分区,保持“未分配”状态即可。注意,Windows的快速启动(Fast Startup)可能会锁住NTFS分区,导致压缩或移动数据时出现损坏风险,最好先在Windows的电源选项里关掉快速启动,再进入磁盘管理操作。
接下来重启进入Ubuntu 22.04,如果你不想动命令行,GParted是图形化调整分区的不二选择。安装方式:
sudo apt install gparted打开GParted后,你会看到磁盘分区的图形化分布。比如常见布局是:最前面是Windows的EFI分区和MSR分区,中间是Windows的C盘,后面是Ubuntu的/分区和swap分区。此时你要做的事情很明确:
- 把Ubuntu的swap分区先删掉(或者缩小),它一般是末尾那个linux-swap分区
- 把Ubuntu的/分区向右拖拽,扩展到磁盘末端
- 重新创建swap分区,大小按内存的1-2倍即可
GParted操作分区时,会要求所有涉及的分区都未挂载。对/分区和swap分区,你需要用Live USB启动Ubuntu后再运行GParted,否则在运行中的系统里没法卸载根分区。这也是双系统和虚拟机扩容最大的差异:虚拟机扩容通常不用离线盘,双系统则基本绕不开Live USB。
操作完成后,重启进入系统,再用resize2fs扩展文件系统(如果GParted没自动完成的话)。实际上GParted在图形界面里可以顺带勾选文件系统调整,执行完后df -h直接生效。
4.2 物理机上的纯Ubuntu系统扩展
如果这台物理机只装了Ubuntu 22.04,没有Windows,那就比双系统简单得多。你只需要一块Live USB或者直接进系统操作(如果是扩展非根分区的话)。
但物理机扩展根分区时面临一个100%会遇到的限制:根分区的后一个分区(拓展分区)必须先处理。如果你安装时选择了默认的“使用整个磁盘”方案,根分区通常就是最后一个分区,growpart可以直接操作;如果你手动分区,根分区后面还有一个swap分区,扩容就麻烦一些。
一个实用技巧:在安装系统时,把swap放在LVM卷组内而不是单独物理分区,这样以后扩容LVM时swap会自动跟着逻辑卷扩展,不需要挪位置。如果已经装好了,swap在根分区后面挡路,最简单的办法是删除swap分区、扩展根分区、再创建一个新的swap文件而不是swap分区。swap文件的性能损耗在绝大多数桌面和服务器场景下可忽略:
# 创建4G swapfile sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab这个方案绕开了分区位置限制,是物理机上最省事的路径。
5. 常见问题排查实录:扩容翻车现场与修复方案
5.1 加完磁盘后系统识别不到:多半是内核没刷新
现象:VMware里把磁盘从30G改成50G,启动Ubuntu 22.04后lsblk还是30G。
排查顺序:
首先确认关机时是否真的点了“扩展”。有些人改的是CD/DVD光驱大小或者误改了其他设备,盯着虚拟机设置里的硬盘看大小是否变成了50G。
其次确认虚拟磁盘类型,如果是SATA控制器下的磁盘,Linux内核对SATA设备的热插拔支持很成熟,一般能自动识别;但如果是较老的IDE接口(某些低版本的VMware默认IDE),重启是唯一解。
最后用sudo partprobe /dev/sda再刷一次,如果还不行,重启。我遇到过几次,基本都是partprobe没刷新成功、重启立刻就好。
5.2 growpart报错“unexpected input”
growpart使用中常见的一个报错是:
unexpected input原因大多是第二个参数写错了位置或格式。正确用法:
sudo growpart /dev/sda 2如果把分区间隔符写成了冒号(比如/dev/sda:2)或者分区号没写,就会报这个错。还有种情况是用growpart /dev/nvme0n1 1时,设备名和分区号中间空格没问题,但设备名不能包含p+数字。growpart能自动处理nvme0n1p1这种命名,但你传参时还是要传设备名/dev/nvme0n1、分区号1。
5.3 resize2fs报错“Filesystem has unsupported feature(s)”
这块是Ubuntu 22.04时代特有的坑。某些云镜像或定制镜像会开启ext4的metadata_csum_seed、orphan_file等新特性,而resize2fs版本太老会不支持。Ubuntu 22.04自带的e2fsprogs是1.46.5,应该够新,但如果你是从旧版本升级上来的系统,或者用的内核自带工具,可能碰到:
resize2fs: Filesystem has unsupported feature(s) (e.g. metadata_csum_seed) while trying to open解决办法是升级e2fsprogs:
sudo apt update sudo apt install --only-upgrade e2fsprogs如果还不行,可以尝试先关闭该特性再resize,但通常不推荐关特性,不如升级工具版本。
5.4 xfs扩容用了resize2fs导致提示
网上教程鱼龙混杂,如果你不小心对xfs文件系统用了resize2fs,会得到类似:
resize2fs: Bad magic number in super-block这不是灾难,只是用错了工具。xfs应该用xfs_growfs:
sudo xfs_growfs /xfs_growfs的挂载点参数通常填/,它读取的是挂载点对应的文件系统,会自动探测设备。如果出现is not a mounted XFS filesystem,确认下设备路径是否正确。
5.5 扩容后df还是旧容量
这是最常见也最容易被忽略的问题。growpart完成了分区扩展、LVM也扩展了逻辑卷、resize2fs输出也显示成功,但df -h就是没变。
大部分情况下,原因是你扩容的根分区,但df -h和/dev/mapper/ubuntu--vg-ubuntu--lv的对应关系搞混了。查看当前生效的文件系统大小,用df -h /而不是看整个df输出中的某一列。如果df -h /还是旧值,就用sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv再执行一次,输出如果提示“Nothing to do!”,说明文件系统已经是最新大小,只是你之前df看的是错误设备导致误判。
还有种情况是growpart扩展了分区,但物理卷没刷新,LVM不知道底层变大。此时pvresize能解决问题:
sudo pvresize /dev/sda25.6 扩容后系统启动异常:别慌,先进恢复模式
如果扩容过程中动了引导相关分区(如/boot或EFI分区),或者resize时意外断电,重启可能出现GRUB命令行或黑屏。这时候记住一点:不要立即重装或格式化。启动到GRUB菜单时,选择“Advanced options for Ubuntu”,进入恢复模式(recovery mode),选择“root”打开root shell,先检查系统是否能正常挂载:
mount -o remount,rw /再修复文件系统:
e2fsck -f /dev/sda2如果启动过程卡在某一步,常见原因是/etc/fstab里写了旧的UUID。扩容一般不会改动UUID(只有当分区被删除重建时才会变),但如果你用了GParted动过分区位置,UUID有可能变化。这时进入恢复模式跑一下:
blkid对比/etc/fstab里的UUID,改了就行。
6. 一条龙实操速查表:从30G到50G全流程
为了方便你照着操作,我把一套完整的虚拟机场景扩容流程整理成速查表。这个流程我已经在VMware Workstation + Ubuntu 22.04 LTS + LVM方案上验证过多次,照着做基本不会翻车。
| 步骤 | 操作内容 | 命令/操作路径 | 关键提示 |
|---|---|---|---|
| 1 | 关机 + 快照备份 | VMware“虚拟机 -> 快照 -> 拍摄快照” | 不备份不动手,这是铁律 |
| 2 | 扩展虚拟磁盘 | VM设置 -> 硬盘 -> 扩展 | 改成50G |
| 3 | 启动系统,刷新分区表 | sudo partprobe /dev/sda | 识别不到就重启 |
| 4 | 扩展分区 | sudo growpart /dev/sda 2 | 确认分区号,别搞错 |
| 5 | PVE/VG/LV检查 | sudo pvs && sudo vgs && sudo lvs | 确认LVM是否感知新容量 |
| 6 | 刷新物理卷 | sudo pvresize /dev/sda2 | PV Size变为新容量 |
| 7 | 扩展逻辑卷 | sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv | 卷组空闲全部分配 |
| 8 | 扩展文件系统 | sudo resize2fs /dev/ubuntu-vg/ubuntu-lv | 实时生效,无需重启 |
| 9 | 验证 | df -h / | 容量已更新 |
如果系统是普通分区(非LVM),第5-7步可以忽略,第8步直接对物理分区执行sudo resize2fs /dev/sda2就好。
这套流程的核心理念是:先让虚拟机磁盘变大,再告诉分区表“磁盘变大了”,接着让LVM“认领”新空间,最后让文件系统扩展“吃掉”新空间。每一层都在上一层的成果上继续,顺序不能乱。
7. 几个值得养成的扩容习惯
经历了多次扩容和几次翻车后,我总结出几个和工具无关的经验,分享给你:
第一,扩容前养成先看lsblk -f、df -h、pvs三连的习惯。五分钟的确认时间,能省下一晚上的恢复时间。我就见过有人对着普通分区的系统执行lvextend,报错半天才反应过来不是LVM。
第二,能用growpart就用growpart,别去手搓fdisk。growpart虽然名字看着陌生,但它是cloud-init生态里最成熟的分区扩展工具,边界对齐、GPT备份表更新全都帮你处理。手动fdisk重建分区表,一个数字敲错就可能把整个分区表毁了。
第三,swap尽量放在LVM内或使用swapfile。这样以后扩容根分区时不会面临“后面有swap分区挡住”的尴尬。Ubuntu 22.04安装时默认把swap放在LVM卷组里,反而是手动分区时容易踩坑。
第四,扩容后记得清理不再需要的旧快照。VMware里快照会在后台持续增长,尤其在你扩容后、数据持续写入时,旧快照可能异常膨胀,最终占满物理主机磁盘。扩容完成并确认系统稳定后,及时删除快照。
最后,如果你只是临时跑一些Linux工具,或者对系统根分区有洁癖,也可以从一开始就避开“分区扩容”这个命题——比如把数据放在独立的数据盘上,或者把大目录单独挂载到新磁盘。但如果你已经走到扩容这一步,这篇文章里的方法和避坑经验,足够让你安全度过这个“磁盘不够用”的坎。