跑过Ubuntu 18.04虚拟机的人大概率遇到过那个让人头皮发麻的场景装系统时图省事只给了30GB磁盘开发环境、数据库、日志文件堆上来没几个月df -h一看/dev/sda1已经显示100%。系统开始各种抽风——文件保存失败、服务进程崩溃、桌面卡死严重的甚至重启后直接进不了图形界面。这篇文章就是围绕这个具体问题展开虚拟机里的Ubuntu 18.04磁盘空间不足该怎么解决。我先说结论整个问题本质上是两层虚拟机管理软件比如VMware Workstation里的虚拟磁盘大小和虚拟机内部操作系统所看到的分区、文件系统大小这两层只要有一层没动空间就永远上不去。下面我按自己实际处理过的完整流程把sda1空间不足的解决办法从头到尾拆一遍重点讲清楚每步为什么要这么做、命令怎么选、以及那些特别容易翻车的地方。1. 为什么你的sda1分区会空间不足1.1 先看清自己的分区布局遇到空间告急第一件事不是急着扩容而是先搞清楚分区现在长什么样。打开终端跑两条命令lsblk df -hTlsblk看的是块设备、分区和挂载点的整体结构。在大多数Ubuntu 18.04虚拟机里你看到的通常是这样的NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 30G 0 disk ├─sda1 8:1 0 29G 0 part / ├─sda2 8:2 0 1K 0 part └─sda5 8:5 0 1G 0 part [SWAP]这里sda1就是根分区挂载在/系统所有东西都往里面塞所以它最容易爆满。sda5一般是交换分区占不了多少空间。df -hT则是从文件系统层面告诉你每个挂载点用了多少、还剩多少以及文件系统类型Ubuntu 18.04默认根分区几乎都是ext4。这里有个很常见的误解看到/dev/sda1只有29G有些人以为直接改虚拟机设置把磁盘加到100G系统就能自动识别。实际上不是这样。虚拟磁盘扩大后这块磁盘整体容量确实变大了但分区表里sda1还是原来那么大文件系统也还是那么大系统根本感知不到新增的空间。所以你才需要做后面那套“扩容分区扩展文件系统”的组合操作。1.2 能通过清理解决的问题就先解决说你不用扩容其实也不对但扩容之前一定先把能清理的垃圾清掉。因为如果你不是真的缺空间而是日志、缓存、残留软件包把磁盘堆满了那直接扩容属于“治标不治本”。我见过不少虚拟机问题根本不是空间不够而是日志文件动辄几十个GB。Ubuntu 18.04上几个立竿见影的清理命令# 清理apt缓存 sudo apt clean sudo apt autoremove # 清理systemd日志保留最近3天 sudo journalctl --vacuum-time3d # 查看哪些目录最占空间 sudo du -sh /* 2/dev/null | sort -h说实话du那条命令对定位垃圾文件特别有用。我曾经在一台Ubuntu 18.04虚机上发现根目录被吃了30多GB查下来是/var/log/journal里的历史日志一条journalctl --vacuum直接释放掉。这种东西如果你不查扩容到200G都不够它造的。如果清理完之后df -h显示sda1的Use还是超过80%或者你有明确的数据增长需求那就老老实实走扩容流程。2. 扩容思路与工具选型2.1 为什么是虚拟磁盘扩容分区扩展的组合前面已经说到了空间不足是“两层”的问题虚拟磁盘大小是一层分区大小和文件系统大小是另一层。所以要分两步走。第一步在虚拟机管理软件层面扩大虚拟磁盘。比如VMware Workstation里调整硬盘大小这一步本质上是修改vmdk虚拟磁盘文件尾部的大小相当于你给一块真实硬盘换了块更大的盘体。第二步在Ubuntu系统里把分区表和文件系统扩张到新空间上。这一步通常是先用growpart工具调整分区大小再用resize2fs扩展文件系统让操作系统真正用上新空间。选这个方案而不是“再加一块新硬盘挂载到/某个目录”核心原因是加新硬盘方案要改应用配置、迁移数据、改fstab挂载点对系统侵入性大而且如果是根分区爆满导致系统起不来你连迁移操作都很难执行。扩展原分区是把新空间无缝接入现有目录树全程不影响已装软件也不用改任何业务配置。2.2 工具与前置条件盘点Ubuntu 18.04上做这件事需要一个关键工具growpart。它由cloud-guest-utils包提供官方云镜像一般自带但手动安装的虚拟机大概率没有。装一下很简单sudo apt update sudo apt install cloud-guest-utilsgrowpart是我比较推荐的扩展分区工具。它做的事情非常纯粹读分区表把指定分区的结束位置扩展到磁盘末尾或相邻分区的起始位置不会动分区里面的文件系统。相比手动用fdisk删掉分区再重建的方式growpart不需要你记住原分区的起始扇区也不容易手滑把分区表搞坏。文件系统扩展用的是resize2fs这是ext2/ext3/ext4文件系统自带的调整工具Ubuntu 18.04默认装系统时都有。如果你的根文件系统是xfs那要改用xfs_growfs不过这个场景在18.04上不多我这篇还是按ext4来讲后面会单独提一句xfs的差异。另外一个备选路线是用GParted Live的图形化界面来扩容这个我会在第5章单独讲。它适合对命令行不熟的人但操作逻辑和风险点不太一样。3. 实操前必须做好的准备3.1 备份与快照开始动分区表之前一定先做备份或快照。这句话我说过无数遍但每次总有人跳过然后扩容失败了来问我能不能恢复。在VMware Workstation里操作非常简单右键虚拟机标签页 → 快照 → 拍摄快照。给快照起个名字比如“before-disk-expand”顺便写一行备注这样如果后面操作失败可以直接恢复到当前这个健康状态。这里要特别提醒一句快照不是备份。快照依赖原始vmdk文件存在如果虚拟机整个目录被删了或者vmdk文件损坏快照也救不了你。所以如果虚拟机里的数据特别重要建议先把整个虚拟机目录复制一份到其他磁盘或者用虚拟机自带的导出OVF功能做一次完整备份。动分区表这件事风险再小也属于高危操作你永远不知道自己会不会踩到某个内核bug或者断电导致分区表写一半。3.2 确认引导方式和分区表类型动手之前还要确认两件事引导方式是UEFI还是传统Legacy BIOS分区表是MBR还是GPT。这两个信息决定了你后续能不能用growpart以及扩展哪个分区。查看引导方式ls /sys/firmware/efi如果这个目录存在说明是UEFI引导通常会有/dev/sda1或/dev/sda2作为EFI系统分区FAT32格式挂载在/boot/efi。这种情况扩容时要格外小心别把EFI分区搞乱了。查看分区表类型sudo fdisk -l /dev/sda看输出里的Disklabel type如果显示dos就是MBR如果显示gpt就是GPT。为什么要关注这个因为growpart扩展分区时如果分区表是GPT工具会自动调整分区表头如果是MBR也得处理好扩展分区的逻辑。大多数Ubuntu 18.04虚拟机默认是Legacy BIOS MBR少数新装的是UEFI GPT。不论哪种只要你的目标分区这里是sda1后面没有紧跟一个无法移动的相邻分区growpart都能处理。但如果sda1后面紧挨着sda2比如swap分区且sda2不能移动那growpart /dev/sda 1会直接失败这种情况我会在第6章细说。4. 实操流程从VMware扩容到系统分区调整4.1 在VMware里扩大虚拟磁盘容量这一步在虚拟机处于关机状态下操作。打开VMware Workstation选中目标虚拟机点击“编辑虚拟机设置”切到“硬件”标签然后选中“硬盘”。右侧会显示当前磁盘容量比如30GB。在“磁盘实用工具”里点“扩展”输入你想要的新大小。这里有个建议不要一次性扩得太大但也不要刚好够用。我一般会按现有使用量的1.5到2倍来给。比如现在用了28GB那就扩到60GB或80GB留出足够余量避免几个月后又来一次。输入容量后点击“扩展”VMware会提示“硬盘已成功扩展”之类的话。这个过程很快因为本质上只是在vmdk描述文件里改一个数字并不会真的一下子填充几十GB的数据到物理磁盘。写入扩容后先别急着开机顺手检查一下虚拟机目录下的vmdk文件是不是变成了两个一个基础盘加一个-s001.vmdk之类。因为扩容操作会创建新快照或者split类型的磁盘描述属于正常现象不用紧张。4.2 开机后第一件事确认新容量是否被“看见”开机会后用lsblk看一眼lsblk正常情况你会看到/dev/sda的总大小已经变成60G或80G但下面sda1还是原来的29G。这说明虚拟磁盘层面已经扩容成功分区层面还没动。这一步经常有人误判看完就以为扩容失败了直接去百度“VMware扩容无效”。其实不是无效是你没走到下一步。虚拟机只认到了磁盘整体变大但这个物理磁盘上的分区表、分区、文件系统都还停留在旧尺寸。4.3 用growpart扩展sda1分区接下来是核心操作。先确保装了cloud-guest-utils然后执行sudo growpart /dev/sda 1注意这里有个细节growpart后面跟的是设备和分区号是分开的两个参数。你写/dev/sda 1不是/dev/sda1中间是空格。这一点好多新手会搞错直接导致“无法找到分区”的报错。命令执行成功后输出大概长这样CHANGED: partition1 start2048 old: end60821503 end125829086意思是分区1的结束扇区从60821503扩展到了125829086磁盘末尾多出来的空间已经纳入sda1。如果命令报了NOCHANGE一般说明分区已经到末尾了或者后面有相邻分区挡住了。到这一步先不要慌先把情况记录下来去第6章排查。4.4 用resize2fs扩展文件系统分区扩展完之后文件系统还不知道有这么大空间。这时候再用resize2fs把ext4文件系统扩展到整个分区sudo resize2fs /dev/sda1这个命令会根据分区表里的新大小自动把文件系统扩大到分区末尾。在ext4上在线扩展是非常成熟的操作不需要卸载分区生产环境也可以直接执行。执行时间取决于文件系统大小一般几秒到几十秒。如果文件系统里根目录正被大量IO占用可能会提示需要先检查一致性用e2fsck -f /dev/sda1扫一遍再resize。我遇到的情况是很少需要这样做但如果你在用resize2fs时报了“Filesystem has errors”之类的错误就老老实实先检查再扩展。4.5 验证结果全部搞完运行df -hT / lsblkdf -hT应该显示根分区已经是60G或80GUse%明显降下来。lsblk里sda1的SIZE也跟着变大。到这一步虚拟机磁盘空间扩展就算成功了。整个流程核心就是三条命令growpart、resize2fs外加一次VMware界面操作。说穿了很简单但每步背后的原理必须懂不然出问题时无从下手。5. 备选方案用GParted Live图形化扩容5.1 准备工作与启动方式如果你的Linux功底一般看分区表像看天书或者遇到分区不连续导致growpart没法直接扩展的情况那GParted Live是个不错的图形化备选方案。GParted Live是一个独立的Linux发行版体积只有几百MB专门用来做分区管理。你不需要把它装到硬盘上直接下载ISO镜像挂到虚拟机的虚拟光驱里从光驱启动就行。下载地址官网都有找gparted-live-x.x.x-amd64.iso下载完在VMware里打开虚拟机设置把ISO挂到CD/DVD然后在虚拟机电源设置里把启动顺序改成“CD/DVD优先”或者开机时快速按F2进BIOS临时选一次启动设备。进入GParted Live后一路默认回车最终会来到桌面双击打开GParted图标就能看到整个磁盘的分区图形界面了。5.2 图形界面里调整分区在GParted界面里你会看到一条横条代表整个磁盘上面是各个分区。操作思路是这样的先选中要扩容的分区这里是sda1右键选择“Resize/Move”把分区末端拖到磁盘末端或者直接输入新的大小然后点“Resize”确认。调整完分区大小后还需要在同一个弹窗里把文件系统一起扩展。GParted会识别ext4文件系统并自动在resize分区后同步resize2fs所以理论上你只要拖动一次滑块分区和文件系统的大小就一起变了。确认后点击工具栏上的绿色对勾“Apply All Operations”GParted会把所有排队的操作真正写入磁盘。这一步需要时间中途千万别关机别强制重启否则分区表可能损坏。5.3 这套方案的优势和坑GParted最大的优势是直观你能一眼看到分区之间有没有空隙、哪个分区挡在了目标分区后面。特别是sda1后面紧跟swap分区导致growpart失败时GParted可以先把swap分区移动到磁盘末尾或者缩小它腾出空间再扩展sda1这个操作在纯命令行下非常麻烦图形界面里就是拖两下的事。但坑也很明显。第一移动分区本身是高风险操作一旦断电或者操作中途出错整个分区数据可能无影无踪所以这方案对备份的要求更高。第二图形界面容易让人麻痹大意勾错分区、把启动分区删了之类的事故我见过不止一次。使用GParted时眼睛一定盯住分区类型和挂载点尤其是/boot/efi这种分区删了系统就起不来了。我个人习惯是这样能用命令行搞定就优先命令行只有sda1和相邻分区之间的空间不连续或者需要移动swap才能扩展时才祭出GParted。它适合当“救火队员”不适合当日常首选。6. 常见问题与排查技巧实录6.1 growpart报错“no space left”怎么办这是扩容时最常撞见的坑执行sudo growpart /dev/sda 1结果提示类似failed: [Errno 28 No space left on device]或者直接告诉你cant be grown。这个报错十有八九是因为/dev/sda1后面紧跟着其他分区比如sda2或sda5导致分区1没有连续空间可以扩展。growpart也只能在分区之间没有障碍物时工作它不会帮你自动挪后面的分区。解决办法取决于你后续分区是什么。如果后面是swap交换分区最简单的处理方式是记下当前swap的UUIDblkid /dev/sda5能看到然后把它从分区表里删掉扩展sda1再新建一个swap分区放在磁盘末尾。具体命令流程# 1. 查看当前swap信息 cat /etc/fstab | grep swap blkid /dev/sda5 # 2. 停用swap sudo swapoff /dev/sda5 # 3. 用fdisk删除sda5并扩展sda1这一步需要手动操作分区表注意别删错 sudo fdisk /dev/sda # fdisk交互界面里p查看当前分区d删除分区5n新建分区1主要分区 # 默认起始扇区结束扇区选默认磁盘末尾w保存这里要敲黑板强调手动操作fdisk删分区再重建是有一定危险性的。删除分区只是删除分区表记录数据还在但如果你把起始扇区弄错了文件系统就废了。所以搞这套操作前快照必须做fdisk里每一步都要用p确认分区号。如果后面是EFI分区UEFI引导的机器很常见情况更复杂。EFI分区不能随便删建议改用GParted Live把EFI分区移动到磁盘末尾再把sda1扩到前面。操作顺序一定是在未挂载状态下做GParted会自动识别并处理。6.2 扩展之后swap的UUID变了删除重建swap分区后有个必然结果新swap分区的UUID和原来不一样了。如果你不更新/etc/fstab重启后系统会找不到swap导致开机报错或swap直接失效。解决办法是重建swap并更新fstab# 格式化新分区为swap sudo mkswap /dev/sda5 # 查看新UUID sudo blkid /dev/sda5 # 用新UUID替换fstab里的旧UUID或者直接改成/dev/sda5 sudo nano /etc/fstab改完之后执行swapon -a测试一下没有报错就算成功。这个坑特别容易踩因为很多人扩容时根本不记得自己动过swap重启后莫名其妙多了一个报错“swap not found”。我建议动分区表之前先把/etc/fstab完整备份一份出问题了好对照。6.3 分区表没刷新的“假失败”还有一种情况growpart和resize2fs都执行成功但运行lsblk或df -h看到的还是旧容量。这多半是内核还没重新读取分区表。Ubuntu 18.04在内核里对已经挂载的分区做resize通常能自动捕捉但保险起见执行一下sudo partprobe /dev/sda或者直接重启虚拟机。重启后如果一切正常那就没问题。如果重启后系统进不去不要慌回到第3章恢复快照换GParted方案再试一次。6.4 根分区是LVM怎么处理上面所有流程针对的是直接分区sda1就是根文件系统。还有一种情况Ubuntu 18.04服务器版安装时如果选了LVM根分区是在LVM逻辑卷里的这时候growpart扩的是物理卷所在分区后续还要扩逻辑卷和文件系统。流程大概是这样# 1. 扩展物理卷所在分区 sudo growpart /dev/sda 1 # 假设LVM PV在sda1 sudo pvresize /dev/sda1 # 2. 扩展逻辑卷 sudo lvextend -l 100%FREE /dev/ubuntu-vg/ubuntu-lv # 3. 扩展文件系统 sudo resize2fs /dev/ubuntu-vg/ubuntu-lv注意这里的逻辑卷路径要替换成你自己的用lvdisplay查。这个场景下只要PV、LV、FS三个环节都走了空间才能最终反应到根目录上。很多人卡在只做了第一步以为扩展了分区就完事结果df还是满的。6.5 常见问题速查表现象可能原因处理方式VMware磁盘扩完后lsblk无变化没重启虚拟机或磁盘扩展没被识别关闭虚拟机重新启动确认vmdk大小lsblk里sda变大了sda1没变分区表未扩展安装cloud-guest-utils并执行growpartgrowpart报no space left分区后面有相邻分区挡住删除或移动相邻分区或用GPartedresize2fs报媒体忙分区被挂载且有IO占用卸载或重启后再试ext4一般可在线扩展重启后swap报错删重建swap导致UUID变化更新/etc/fstab用新UUID扩展后df仍然显示旧容量文件系统未resize或内核分区表未刷新执行resize2fs再partprobe或重启系统起不来分区表操作出错或启动分区被误删从快照恢复或进GParted Live修复最后分享几个我自己的处理习惯遇到虚拟机磁盘空间不足我现在固定套路是先查日志和软件包缓存确定是否真的需要扩容。确实要扩时装好cloud-guest-utils先拍快照再关机扩容虚拟磁盘开机后growpart加resize2fs一次性搞定。整个过程熟练的话十分钟以内能完成但每一步我都会确认输出而不是批量粘贴命令然后等着出结果。有个小细节值得多说一句每次扩容时我都会把新容量在一次磁盘扩展里给足尽量不要搞成“30G变50G三个月后又来一次”这种状态。频繁扩分区虽然技术上可行但每多操作一次就多一次翻车概率。给未来留足余量才是这类运维操作里最有价值的经验。
