“磁盘满了应用告警日志刷屏数据库写入失败……”这大概是运维人最不想半夜看到的画面。我处理过不少“Linux磁盘扩容”的工单从裸金属到虚拟机、从传统分区到LVM前前后后踩过很多坑。这篇文章不绕弯子先把扩容背后的三层结构讲清楚再把最常见的两种扩容路径一步步写明白最后附上我自己的排查经验和操作习惯。无论你是刚接触服务器没多久还是已经扛过几次故障照着这套思路走至少不会把能在线完成的扩容做成需要停机的大工程。1. 扩容之前先把场景和原理盘清楚1.1 你遇到的到底是哪一种“磁盘不够用”很多人一上来就问“磁盘满了怎么扩容”但“磁盘不够用”至少分三种情况第一种是整块磁盘已经用满比如系统盘本身只有40G根分区满了连日志都写不进去。第二种是磁盘还有剩余空间但当初分区时只分了一小块剩下的空间一直闲着没分配。第三种是空间已经分配给某个分区但那个分区挂载的目录不对或者文件系统没跟着扩导致df看起来没变化。这三种情况的操作路径完全不同。第一种需要看你用的是LVM还是传统分区第二种好办直接在原有分区上扩展前提是这块磁盘是虚拟磁盘或云盘且分区在磁盘靠后的位置第三种最坑因为命令都执行成功了但df始终显示旧容量往往就是文件系统扩容那一步漏了。所以我拿到一台机器第一件事不是敲fdisk而是先看整体布局。1.2 扩容的关键分区、卷、文件系统三层结构Linux磁盘管理可以简单分成三层物理磁盘、分区或逻辑卷、文件系统。物理磁盘对应/dev/sda这种设备分区是/dev/sda1、/dev/sda2LVM场景下还有物理卷PV、卷组VG、逻辑卷LV文件系统则是ext4、xfs这类格式挂在某个目录上供业务读写。可以把这三层理解成书柜物理磁盘是整个书柜分区是书柜里的隔板文件系统是隔板上放档案盒的区域。你想让某个档案盒区域变大不能只把隔板往外挪还得告诉档案盒系统“现在你可以多占用一点空间”。放在Linux里就是磁盘扩容 - 分区/逻辑卷扩容 - 文件系统扩容三步缺一不可。这也是很多人“扩容失败”的根源云控制台把磁盘从100G扩到了200Glsblk也看到sda变大了但分区没动分区动完了PV没动PV动完了LV没动LV动完了忘记跑xfs_growfs。每一层都有对应的命令少一步df永远不变。1.3 不同环境的扩容差异物理机、虚拟机、云主机物理机扩容通常要加物理硬盘或者通过RAID卡在线扩容RAID组系统层面可能还需要重新扫描SCSI设备。虚拟机则方便很多在虚拟机管理平台里可以直接给虚拟磁盘扩容甚至支持在线热扩容。云主机就更简单了在云控制台里对云盘做“扩容”但我必须强调一句控制台扩容完成后操作系统里看到的往往只是磁盘设备变大了分区和文件系统还停留在旧状态必须手动继续处理。另外物理机扩容时如果涉及RAID操作顺序和普通虚拟机还不一样必须先让RAID层面识别到新容量再进系统处理。虚拟机和云主机的流程基本一致只是“让系统识别新磁盘容量”这一步不同虚拟机可能要扫描总线云主机可能直接lsblk就能看到新容量少数场景需要重启。2. 动手前的必备检查和数据备份2.1 用这几条命令摸清现状在敲任何可能影响分区表的命令之前先把现状摸清楚。我常用的组合是df -hT lsblk blkid pvs vgs lvs fdisk -ldf -hT能告诉你哪些文件系统满了、文件系统类型是什么、挂载点在哪。lsblk能看到磁盘、分区、LVM各层的关系是判断“磁盘变大了但分区没变”的最直观工具。blkid用来记录分区UUID和文件系统类型后面检查挂载关系会用到。pvs/vgs/lvs只对LVM环境有意义能直接看出物理卷、卷组、逻辑卷目前的大小和剩余空间。fdisk -l我习惯放在最后因为它在某些环境下输出比较长但能看到磁盘总容量、分区起始扇区和结束扇区。如果磁盘总容量已经变大了但最后一个分区的结束扇区还停在旧位置那基本可以断定分区还没扩展。2.2 数据备份怎么做到不踩坑扩容虽然不像格式化那样破坏性大但任何涉及分区表和文件系统元数据的操作都有风险。我自己见过有人在生产环境执行resize2fs时中途断电虽然概率低可真遇到了就是事故。对于云主机和虚拟机最省事的是打快照。快照不是备份但它能让你在操作失败后快速回滚到扩容前的状态这比任何命令都重要。某些云平台支持在线快照不影响业务如果不能在线打快照那就安排一个维护窗口停机后快照。对于物理机没有快照的话至少要把/etc/fstab、/etc/grub2.cfg这类关键配置文件备份出来同时用tar或rsync把重要数据复制到其他磁盘。数据库场景还要额外注意不能直接对数据目录做文件拷贝必须用数据库自己的导出工具否则拷出来的数据可能是坏的。2.3 扩容前的风险清单我给自己总结过一份扩容前风险清单每次操作前都会过一遍确认业务可接受的停机时间。能在线扩容的尽量在线做但分区表调整仍存在风险。确认磁盘上是否还有未分配空间。如果没有先解决物理容量问题。确认根分区和/boot分区的关系。如果/boot是独立分区且满了扩容根分区并不能解决启动问题。确认文件系统类型。ext4用resize2fsxfs用xfs_growfs命令用反了会直接报错。确认有没有正在使用该分区的进程。尤其是数据库和容器扩容前最好停止写入。确认快照或备份已经完成并验证过可恢复。3. LVM场景下的磁盘扩容完整实操3.1 虚拟机或云主机从云控制台扩磁盘到系统识别LVM环境下的扩容路径是控制台/虚拟化平台扩容磁盘 - 系统识别新容量 - 扩展物理分区 - pvresize扩展PV - lvextend扩展LV - 文件系统扩容。先看“系统识别新容量”。假设原来是一块100G的云盘/dev/sda控制台扩容到了200G。大多数情况下用lsblk就能直接看到sda变成了200Glsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 200G 0 disk ├─sda1 8:1 0 1G 0 part /boot └─sda2 8:2 0 99G 0 part └─centos-root 253:0 0 99G 0 lvm /这时候sda是200G但分区sda2还是99GPV、LV也停留在原来的大小。如果lsblk没变化对于虚拟机可以尝试重新扫描SCSI设备常见做法是echo 1 /sys/class/scsi_device/设备编号/device/rescan具体编号可以从/sys/class/scsi_device/下面找但不同虚拟化平台差异很大。更稳妥的方法是先在管理平台确认磁盘已经是新容量然后重启系统几乎所有场景下都能识别。能在线就别乱折腾重启一次的成本通常比在错误命令上反复试错低得多。3.2 扩展物理卷、卷组、逻辑卷确认系统看到了更大的磁盘后先扩展分区。比如上面例子里的sda2可以使用growpartgrowpart /dev/sda 2这个命令的作用是让最后一个分区占满磁盘剩余空间。执行后可以用lsblk验证sda2应该从99G变成199G。这里有个前提sda2必须是磁盘上的最后一个分区或者至少它后面没有其他分区。这也是为什么我们总是建议装系统时把LVM分区放到磁盘最后的原因。分区扩完后物理卷PV的大小还没有变需要用pvresize让它识别分区的新容量pvresize /dev/sda2然后看pvsFree这一列应该出现了新空间pvs接下来把剩余空间全部加到根逻辑卷。先看逻辑卷和卷组名字再执行lvextendlvs vgs lvextend -l 100%FREE /dev/centos/root这里-l 100%FREE表示把卷组里所有空闲空间全部分配给这个逻辑卷。如果你只是想加一定容量也可以用-L 50G这种写法。LVM的好处就在这逻辑卷的调整比物理分区灵活得多而且在线做基本没问题。3.3 文件系统扩容ext4与xfs的区别和命令逻辑卷扩容完成后df很可能还是旧值。原因很简单文件系统并不知道自己可以变大必须主动扩展。如果是ext4用resize2fsresize2fs /dev/centos/root如果是xfs用xfs_growfs而且参数是挂载点xfs_growfs /这两个命令都能在线执行。xfs_growfs还有一个特性它的执行结果默认不打印“扩展后大小”而是提示data blocks changed所以看到“changed”就不用慌。有一个关键区别一定要记住ext4既支持扩大也支持缩小但xfs只支持扩大不支持缩小。如果你一开始用xfs做了根分区后来想压缩空间重新规划只能备份、删除、重建、恢复整个过程复杂得多。3.4 实操记录从100G扩到200G的完整命令流给一段完整示例假设是某台生产虚拟机原磁盘100G根文件系统是xfs挂载在/逻辑卷路径是/dev/centos/root。在虚拟化平台把磁盘从100G调整到200G后进入系统执行# 1. 确认系统识别到磁盘新容量 lsblk /dev/sda # 2. 扩展sda2分区到磁盘尾部 growpart /dev/sda 2 # 3. 扩展物理卷 pvresize /dev/sda2 # 4. 扩展逻辑卷 lvextend -l 100%FREE /dev/centos/root # 5. 扩展xfs文件系统 xfs_growfs / # 6. 验证 df -hT /我实际操作时会在第2步和第3步之间再用lsblk确认一次分区大小避免分区没扩成功就继续跑pvresize。第5步执行时如果当前目录正好在/下面某些环境会提示target is busy但通常不影响执行换个目录或者直接指定挂载点即可。整套流程跑完df -hT里根分区应该已经变成200G。如果还停在100G不要怀疑人生大概率是第2、3、4、5步里漏了某一步按顺序重新检查。4. 非LVM场景怎么扩容直接扩展分区4.1 用parted/growpart调整分区表不是所有系统都用LVM。很多老系统、云镜像或者直接用ext4根分区的机器根本没有PV/VG/LV这套逻辑。这时候扩容路径更简单但也更危险物理磁盘扩容 - 扩展分区 - 扩展文件系统。最理想的情况是根分区是磁盘的最后一个分区并且磁盘上还有未分配空间。此时可以使用growpart直接扩展分区growpart /dev/sda 1growpart比fdisk手动改分区表安全得多因为它只扩展分区结束扇区不会改动起始扇区和分区类型。如果你的Linux发行版没有growpart可以用partedparted /dev/sda resizepart 1 100%这会交互式地让你确认部分版本还会提醒是否更新分区表。实际操作时我要确认一下parted resizepart只对GPT分区表和部分场景好用MBR分区表有时会提示不能在线调整需要重启才能生效。如果你发现根分区不是最后一个分区比如sda1是/bootsda2是根分区而磁盘后面没有空闲空间那就比较麻烦了。这种情况最好提前规划在安装系统时就留出足够的根分区或者直接改用LVM。4.2 让内核重新读取分区表扩展分区后Linux内核不一定立刻使用新分区表需要重新读取。最常用的是partprobe /dev/sdapartprobe在大多数场景下能无痛刷新分区表。但有一种情况会失败某个分区正被挂载使用内核认为分区表忙拒绝重读。此时会报“Device or resource busy”。如果实在不行只能安排重启或者在维护窗口里卸载文件系统再重读。注意fdisk里的w选项在写入分区表后也会触发内核重读但同样可能遇到占用问题。不要因为看到“Syncing disks.”就认为万事大吉务必用lsblk或cat /proc/partitions确认内核已经看到新分区大小。4.3 调整文件系统大小分区扩展完毕后文件系统还停留在旧大小。和LVM场景一样ext4用resize2fsxfs用xfs_growfs# ext4参数是设备路径 resize2fs /dev/sda1 # xfs参数是挂载点 xfs_growfs /对于非LVM的ext4分区resize2fs执行前最好先跑一遍e2fsck检查文件系统。虽然在线检查一般只是只读但能提前发现隐患。xfs则没有对应的在线安全强制检查更多依赖内核日志。如果分区不在末尾或者磁盘空间已经被其他分区占用直接调整文件系统也没有意义因为文件系统大小不能超过所在分区大小。遇到这种情况我的建议是放弃“原地扩容”改成“加一块新盘把数据迁移过去”而不是强行去动中间的分区。5. 常见问题与排查技巧实录5.1 为什么df -h看到的没变化这是扩容后被问得最多的问题几乎每次都有。排查顺序应该是先确认磁盘设备本身有没有变大lsblk /dev/sda如果sda还是旧大小说明物理层没扩或者系统没识别该查云控制台或虚拟机设置必要时重启。如果sda变大了但分区没变是该扩分区用growpart或fdisk。如果分区变大了但PV没变是没跑pvresize。如果PV变了但LV没变是没跑lvextend。如果LV变了但df没变是没跑文件系统扩容命令。我见过有人在“LV已经扩完”之后没跑xfs_growfs就跑来问为什么df没变化其实只要执行xfs_growfs /就结束了。还有一个容易忽略的点某些文件系统扩容后df显示的是旧inode数量或者块大小但实际已经可用。可以用df -i看看inode有没有变化用stat -f /看文件系统状态别只盯着df的Size列。5.2 “磁盘空间已用尽”但实际还有inode可用这里有个常见误区磁盘满了不只是容量满了也可能是inode耗尽了。扩容后容量变大但inode可能还是原来的数量对于大量小文件场景比如邮件队列、消息队列、容器日志目录很容易出现“df容量没用完但应用报磁盘满”。命令是df -i /如果IUse%是100%说明inode耗尽了。ext4和xfs在扩容时通常会按比例增加inode但如果你用的文件系统创建参数比较特殊或者目录里小文件多到异常容量扩完还是要关注inode。遇到inode耗尽优先清理无效小文件比如旧的session、临时文件、过期的日志。实在清理不动再考虑备份重建文件系统因为增加inode数量通常需要重建文件系统不能在在线扩容时直接指定。5.3 分区表无法重新读取执行partprobe或者fdisk w后报“Busy”常见原因是有进程在使用该分区或者某个逻辑卷正在使用对应的物理卷。处理思路是先卸载文件系统停止相关服务再刷新分区表。如果根分区无法卸载那基本上只能重启。这也是为什么我强烈建议扩容动作放在维护窗口留好重启时间。不要尝试用一些看起来很巧的命令强制在线重读代价可能远超重启。在云环境里有些平台对在线扩容支持得比较好分区表刷新通常不会失败。但物理机加磁盘后SCSI扫描和内核重读反而容易出问题这时候重启反而最干净。5.4 xfs文件系统能否缩减不能。xfs_growfs只有扩大功能没有缩小功能。很多人在磁盘规划初期用了xfs后来想压缩根分区给其他卷腾空间会发现根本没有现成命令。如果你必须为xfs缩容唯一稳妥的办法是备份数据、卸载文件系统、删除原逻辑卷或分区、创建较小的新逻辑卷/分区、格式化xfs、恢复数据。整个过程要停机而且备份和恢复的时间成本很高。所以在创建文件系统时就要想清楚不确定分区大小的场景优先用ext4或LVM后期调整更灵活。5.5 扩容到一半卡住或报错怎么办resize2fs在扩容过程中如果报错通常和文件系统不一致有关。先停止所有写入然后执行e2fsck检查修复再重新resize2fs。如果是xfsxfs_growfs报错多半是逻辑卷还有剩余空间没分配或者命令参数写错了检查一下LV大小和文件系统当前大小。让我提醒一句不要一边扩容一边往这个分区里写大量数据。虽然在线扩容本身允许业务继续运行但在数据剧烈写入的场景下做文件系统变更风险会成倍增加。数据库这类场景建议先停止写入或者至少切到只读模式扩完再恢复。5.6 开机自动挂载与UUID注意事项扩容后一些系统会自动更新/etc/fstab但更多情况是需要手动确认。分区表变化后分区UUID在大多数情况下不会变但少数分区管理工具调整后可能改变文件系统UUID。如果/etc/fstab里写的是UUID开机后发现挂载不上就要用blkid重新读取设备UUID然后更新fstab。我的习惯是扩容前先记录一份blkid输出扩容后逐项对比。真的出问题也能快速恢复。对于LVM场景逻辑卷路径如/dev/centos/root一般是稳定的但使用UUID挂载/xfs文件系统的机器扩容后最好验证一次mount -a能不能正常挂载所有文件系统。6. 一些我踩过坑之后总结出来的习惯6.1 扩容前先拍快照这句我几乎对每个来问的人都重复一遍无论多么熟练无论看起来多简单扩容前先拍快照。我遇到过growpart一切正常、pvresize也成功但在执行xfs_growfs时虚拟机突然死机的情况。没有快照那就得靠备份恢复时间完全不可控。有快照回滚就是几分钟的事。快照不是永久保留的东西扩容验证通过后确认数据完整、服务正常就可以删除快照了。一直留着快照会占用存储空间而且会影响性能。6.2 命令顺序不要乱扩容的命令顺序非常像多米诺骨牌磁盘设备变大 - 分区变大 - PV变大 - LV变大 - 文件系统变大。任何一步提前或跳步都会导致后续命令报错。比如LV还没扩直接跑xfs_growfs它会告诉你“没有空间可以扩展”分区没扩直接pvresize它会认为PV大小不变。所以我习惯把每个步骤用lsblk或df验证一遍再往下走。多敲几次lsblk不丢人漏敲一个命令才是真的麻烦。6.3 运维变更记录最后分享一个习惯每次扩容操作我会把操作前状态、操作命令、操作后状态都记录下来包括df快照、lsblk输出、pvs和lvs的输出。原因很简单半年后这个磁盘可能又满了你或者接手的人需要知道上一次扩容到底扩到了哪一步有没有留下没做完的事情。变更记录不一定要写得多正式哪怕是一个文本文件只要包含了关键命令和前后对比就能省下大量排查时间。我个人见过太多“磁盘还是满的但大家都说已经扩过了”的诡异场景最后查下来要么是文件系统没扩要么是扩到了别的逻辑卷。有记录一眼就能定位问题。Linux磁盘扩容这件事说难不难说简单也简单但真正让操作变得可靠的不是某一条命令而是对三层结构的理解和对风险的敬畏。希望你下次处理扩容时能在动手前先笑一笑然后冷静地走完每一步。