1. 什么时候需要给目录扩容场景判断与两种处理路径1.1 三种典型的空间不足场景先说一个很多人踩过的场景登录服务器一看告警邮件根目录使用率已经到100%业务日志写不进去临时文件创建失败数据库事务卡死。这时候大多数人第一反应是上去删文件然而真到了生产环境你会发现每一份文件背后都可能挂着业务依赖根本不敢乱动。我比较推荐的做法是提前规划好磁盘容量方案把新磁盘直接挂载到根目录或者指定目录从根上解决空间瓶颈。我见过比较典型的三种空间不足场景你可以对照一下自己属于哪一种根分区/被系统日志、Docker镜像、临时文件塞满。这类最头疼因为根分区不只是业务数据还承载了操作系统本身。系统日志写到一半断电、扩容失败都可能导致启动异常。数据盘挂载点满了但根分区还很空。比如网上常见的把数据都丢在 /data结果 /data 所在分区爆了而根分区剩了一堆空间没法挪过去。家目录/home爆了。常见于多用户服务器每个用户往家目录堆下载、堆构建缓存挤爆磁盘。不同场景对应的扩容手段完全不同第一步不是急着执行命令而是先判断当前系统的文件系统布局。1.2 扩容前必须搞清楚的几件事无论你要挂载根目录还是指定目录动手前必须确认文件系统类型用df -T查看。Linux 下最常见的根文件系统是 ext4 和 xfs两者扩容指令不一样千万别搞混。ext4 用resize2fsxfs 用xfs_growfs。我见过不止一次有人在 xfs 上执行 resize2fs直接报错不说还把文件系统搞出问题。是否 LVM执行lsblk看磁盘结构。如果根分区下面挂着vg_xxx-lv_root之类的设备说明是 LVM 逻辑卷这种结构可以直接在线扩容不用卸载不用重启是生产环境最推荐的方案。如果根分区直接是/dev/sda2这种物理分区那扩容路径就完全不同了。当前挂载情况用mount或findmnt查看是否有已经挂载但没利用上的磁盘。很多服务器云控制台里加了一块数据盘但忘记格式化挂载白白放着。磁盘剩余扇区情况用parted /dev/sda print free或者fdisk -l /dev/sda看现有磁盘后面是否还有空闲扇区。这个信息决定了你能否在原有磁盘上直接扩大分区还是必须加新盘。为什么要先确认这些因为扩容方案的底层逻辑取决于根目录是不是 LVM和分区后面还有没有空闲空间。确认完之后你基本就能选出下面的处理路径。1.3 两条路径的选择新盘直挂指定目录 vs LVM在线扩容目录扩容本质上只有两种思路思路一把新磁盘直接挂载到指定目录上。比如/var/lib/docker满了我加一块新盘格式化后直接挂载到/var/lib/docker那 Docker 的数据就全部写到新盘上原有空间立刻释放。这种方式适用于非 LVM 环境操作简单不用动原有分区表。注意如果目标目录里已经有数据直接挂载新盘会让旧数据被遮住——原目录里的文件还在但通过挂载点访问不到了。所以这种情况必须先做数据迁移不能直接挂。思路二通过 LVM 把根目录所在逻辑卷在线扩大。这种方式更适合根分区不够用的情况。你的根目录通常是 LVM 逻辑卷比如/dev/mapper/centos-root新盘加进来之后我只需要做三步把新盘变成物理卷PV→ 加入卷组VG→ 把卷组剩余空间分配给根目录所在逻辑卷LV然后扩容文件系统。整个过程不需要卸载根目录不需要重启服务器业务完全不受影响。这两种思路各有利弊下面分开讲清楚因为涉及的命令和风险点完全不同。2. 直挂新盘到指定目录mount 与 fstab 的正确打开方式2.1 物理盘初始化与分区fdisk 常用套路假设你已经把一块新磁盘插进服务器先要看系统认不认。执行lsblk正常情况下会出现类似sdb的盘大小 1TB 左右没有任何分区。此时可以开始分区fdisk /dev/sdbfdisk 是交互式命令按n新建分区按p选择主分区分区号默认 1起始扇区默认即可结束扇区如果想整块盘都用一个分区直接回车。最后按w写入分区表。写完之后执行partprobe或partx -a /dev/sdb让内核重新读取分区表。个人经验是在 CentOS 7 上partprobe更稳有些老系统partx不识别新分区报 partition table invalid 之类的错。如果磁盘大于 2TBfdisk 不支持 GPT 分区表需要用 partedparted /dev/sdb mklabel gpt parted /dev/sdb mkpart primary 0% 100%2.2 文件系统创建与挂载mkfs.ext4 mount分区建好之后格式化mkfs.ext4 /dev/sdb1如果你的数据盘要用 xfs那就是mkfs.xfs /dev/sdb1关于选择哪种文件系统我的看法是CentOS 7 默认根分区是 xfs如果这块盘将来要挂载给业务放文件数据量巨大且大文件多xfs 性能有优势如果希望后续空间不够时可以缩容ext4 更好管理。生产环境我不建议频繁调整文件系统类型选定了就用下去。接着挂载到目标目录。假设目标目录是/datamkdir -p /data mount /dev/sdb1 /data此时df -h应该能看到/data已经挂上容量也正确。但这个挂载是临时的重启就没了。要让重启后自动挂载必须写 fstab。2.3 fstab 配置与 UUID 取值查看分区 UUIDblkid /dev/sdb1输出类似/dev/sdb1: UUIDf7c6e0b4-xxxx-xxxx-xxxx-xxxxxxxxxxxx TYPEext4然后在/etc/fstab里追加一行UUIDf7c6e0b4-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data ext4 defaults,nofail 0 0写完之后一定要验证不然 fstab 写错会导致开机进不了系统。验证命令mount -a如果没有任何输出说明配置没问题。再执行df -h确认挂载成功。这个mount -a习惯是我强烈推荐的几乎所有 fstab 相关事故都是因为写完没验证直接重启导致的。2.4 为什么用 UUID 而不是 /dev/sdb1新人经常犯的一个错误是在 fstab 里写/dev/sdb1 /data ...。这在单盘服务器上问题不大但一旦系统重启后磁盘识别顺序变化比如多块盘的情况下/dev/sdb可能变成/dev/sdc系统会找不到设备直接卡在紧急模式。UUID 是文件系统创建时生成的全盘唯一标识符跟设备名无关所以用 UUID 更可靠。我在多块数据盘的主机上实测过拔掉一块盘再开机如果用设备名启机之后直接进入救援模式用 UUID 则完全不受影响顶多就是挂不上的目录自动跳过。3. LVM 扩容根目录从物理卷到逻辑卷的完整链路3.1 先确认你的根目录是不是 LVM很多人一听说LVM 扩容根目录就觉得复杂其实 Linux 发行版默认安装时大多已经采用 LVM 结构了。确认方法很简单lsblk /dev/mapper df -h /执行之后如果看到根目录挂在类似centos-root、ubuntu--vg-root或vg_root-lv_root上恭喜你你的根目录就是 LVM 逻辑卷可以用标准流程在线扩容。如果看到的是/dev/sda2这种说明不是 LVM只能走别的路子后面讲。再看卷组信息vgs这条命令列出卷组名和剩余空间。假如卷组叫centos逻辑卷叫root现在卷组剩余空间为 0说明需要先加新盘。3.2 物理卷与卷组扩充新盘插上后先建物理卷pvcreate /dev/sdb注意这里直接用整个/dev/sdb不用分区。LVM 允许直接把整块盘做成 PV。如果有多块盘可以一次性创建多个 PV。再查一下当前 PV 状态pvs确认/dev/sdb已经成为 PV 之后把它加入根目录所在的卷组。比如卷组叫centosvgextend centos /dev/sdb加完之后再执行vgs你会看到卷组剩余空间从 0 变成了新盘的大小。这一步做完根目录扩容的物质基础就有了。3.3 lvextend 与 resize2fs / xfs_growfs 的配合卷组有空间之后把空间分配给根目录逻辑卷。逻辑卷名通常不是简单一个root要先用lvs看看准确名称。假设名称是/dev/centos/root要把卷组剩余的所有空间全部分配给它lvextend -l 100%FREE /dev/centos/root如果只想加 20Glvextend -L 20G /dev/centos/root这里-l加的是 PE 数量百分比-L加的是容量大小两者别混了。我习惯用-l 100%FREE一次把剩余空间全给根目录省得还要反复算。到这里逻辑卷已经变大了但文件系统还保持原来大小。这一步是新人最容易忽略的lvextend 只是改了 LVM 元数据文件系统完全不知道空间变了。接下来按文件系统类型区分ext4 执行resize2fs /dev/centos/rootxfs 执行xfs_growfs /注意两者区别很大resize2fs 后面跟设备文件xfs_growfs 后面跟挂载点。写成 xfs 的还要求挂载点必须是 xfs否则报错。执行完成后df -h /你就会发现根目录大小变了全程没有卸载没有重启业务没停。3.4 在线扩容的前提条件与风险点LVM 在线扩容整个流程看起来很神奇但有几个前提必须满足文件系统必须是 ext4 或 xfs且/etc/fstab里挂载参数没有特殊限制。文件系统不能有损坏。最好在扩容前执行一下xfs_repair -n或e2fsck -n做只读检测。虽然扩容失败概率不高但一旦赶上文件系统损坏在线扩容会放大问题。磁盘、控制器不能有硬件故障。扩容过程中数据重新映射硬件不稳定会导致逻辑卷数据错乱。我自己的一个教训是曾经在虚拟机里对 xfs 根目录执行resize2fs结果指令直接报 Filesystem at /dev/mapper/xxx has unsupported feature 之类原因是这虚拟机根分区本来就不是 xfs 而是 ext4 我记错了。所以扩容前df -T /一定看仔细别只凭印象。4. 非 LVM 分区根目录扩容的替代思路4.1 最安全但不是扩容bind mount 目录迁走大文件如果你的根目录不是 LVM物理分区后面也没有空闲空间想直接扩大根目录本身会很麻烦。这时我推荐一个非常实用、风险很低的替代方案用 bind mount 把根目录下的大目录迁移到新数据盘上。思路是这样的找一个数据量大的子目录比如/var/lib/docker把新数据盘挂载到一个临时目录比如/mnt/newdisk然后同步数据最后用 bind mount 的方式把新盘挂回原目录。用 systemd 的方式实现更稳。在/etc/systemd/system/下新建一个 mount 单元比如/etc/systemd/system/var-lib-docker.mount[Unit] Afternetwork-online.target Wantsnetwork-online.target [Mount] What/dev/sdb1 Where/var/lib/docker Typeext4 Optionsdefaults,nofail [Install] WantedBymulti-user.target激活systemctl daemon-reload systemctl enable --now var-lib-docker.mount这种方式的好处是如果磁盘没挂上系统也不会卡死因为nofail参数决定了失败时忽略错误继续启动。相比直接改 fstab 更安全。4.2 把数据盘挂到根目录下的大目录如果你不想用 bind mount 这种重定向手段还有更直接的做法假设根目录马上要满了根目录下的/opt占用量极大。你完全可以把新盘格式化后直接挂载到/opt上。操作流程是先把/opt下的现有数据复制到新盘比如挂载到/mnt/newdisk后执行rsync -avxH --progress /opt/ /mnt/newdisk/复制完成后解挂旧目录把新盘挂载到/opt修改 fstab写入 UUID 与/opt的映射这里的关键是复制时一定要保留权限、属主、硬链接rsync参数-a里已经包含这些-H保留硬链接做数据迁移墙裂建议带带上。复制完成后还要对比源目录与目标目录的 inode 数量find /opt -type f | wc -l find /mnt/newdisk -type f | wc -l两边一致才说明数据没少。如果数量不一样不要解挂旧目录。4.3 虚拟机场景的磁盘扩容流程很多人的 Linux 是装在虚拟机里的。虚拟机扩容有一个好处虚拟磁盘文件可以动态扩大不用像物理机那样加硬盘。VMware 和 KVM 都支持在线扩展虚拟磁盘大小但扩展完虚拟磁盘后Linux 内部看不到新空间还需要执行分区表刷新。在虚拟机里给根目录扩容标准操作是在虚拟机管理界面把磁盘大小从 100G 改成 200G。登录系统执行lsblk查看。如果磁盘分区是/dev/sda2而磁盘/dev/sda已经有 200G说明尾部有空闲。用growpart扩展分区比如 CentOS 7 上growpart /dev/sda 2这条命令把/dev/sda2分区扩展到磁盘尾部剩余空间。然后根据文件系统类型扩展文件系统resize2fs /dev/sda2或者xfs_growfs /用 growpart 之前最好先备份分区表sfdisk -d /dev/sda backup.sfdisk万一失误可以恢复。4.4 冒险做法GParted 调整分区谨慎使用还有一种方式是用 GParted 等图形化工具调整分区大小。一般做法是刻录一个 GParted Live USB启动后拖拽调整根分区大小。这种方案在个人电脑、测试机上操作尚可生产环境我极不推荐。原因很简单调整分区表过程中一旦断电或者误操作整个磁盘的文件系统可能直接损坏数据恢复成本极高。如果你坚持要用最好先做全盘快照或者离线备份。我见过有人拿 GParted 调分区后sda2 文件系统完全损坏最后只能从备份恢复。相比之下加一块新盘挂载到目标目录风险要低一个数量级。5. 数据迁移顺序与 fstab 配置的避坑细节5.1 迁移数据时常见的顺序错误把旧目录数据迁到新盘很多人犯的第一个错误就是复制还没完成就解挂旧目录。这是大忌。完整且安全的顺序应该是新盘先挂载到临时目录/mnt/newdiskrsync 同步数据到/mnt/newdisk比对文件数量与体积确认一致停业务或停对该目录的写入用lsof看还有没有进程占用目录再次 rsync同步两次同步之间的增量数据解挂旧目录把新盘挂载到原目录确认 fstab 已经更新避免重启后挂载点丢失很多人省略第 4、5 步直接复制完就切挂载点结果丢掉了复制期间新产生的数据。生产环境一定要有这个增量二次同步的意识。关于 rsync 的用法我贴一个自己常用的参数组合rsync -avxHAX --numeric-ids --progress /var/lib/docker/ /mnt/newdisk/-x表示不跨文件系统防止把/proc、/sys这类伪文件系统也带进去-H保留硬链接-A保留 ACL-X保留扩展属性。这套参数是我做整目录迁移时的标配。5.2 fstab 参数讲解defaults、nofail、_netdevfstab 配置看起来就一行但参数里的门道不少。每个字段的含义如下字段说明设备UUID 或设备路径推荐 UUID挂载点比如 /data 或 /var/lib/docker文件系统类型ext4、xfs、nfs 等挂载参数defaults、nofail、noatime 等dump是否备份通常填 0fsck开机时检查顺序根分区填 1其他填 2各类挂载参数里我重点推荐两个实用选项nofail挂载失败时不阻断启动过程。远程挂载比如 NFS尤其重要网络不通时如果 fstab 里没写 nofail系统会反复重试并卡在启动流程上。noatime不更新文件访问时间。对高并发读场景性能提升明显因为减少了每次读文件时的元数据写入。如果是日志型目录这个参数能减少大量磁盘 I/O。挂载 NFS 时还要考虑_netdev它告诉系统等网络就绪后再挂载避免网络服务没起来就去挂网络文件系统导致启动失败。5.3 常见错误fstab 写错导致无法开机fstab 写错进不了系统这个坑可以说每个人都会踩一次。症状很典型开机后卡在A start job is running for /dev/sdb1之类的界面最终进紧急模式。如果你遇到这种情况不要慌。在紧急模式下执行mount -o remount,rw /把根分区重新挂载成可写然后编辑/etc/fstab把错误的那一行注释掉或修正。最后执行exit重新进入系统。避免事故发生的最好办法永远不要只改 fstab 不验证。写完 fstab 后一定要执行mount -a并用findmnt -a检查所有挂载点状态是否正常。还有一个技巧如果是对一块已经挂载的盘修改 fstab可以先执行umount /挂载点再mount -a测试 fstab 配置是否能正确挂载。5.4 大目录迁移后软链接的处理数据迁移过程中还有一类隐藏坑目录里可能有大量软链接symlinkrsync 默认会保留符号链接本身不会复制链接指向的目标内容。这本来是好事但如果原目录下有的应用创建的是相对路径软链接迁移后很容易因为路径变化变成死链接。所以迁移完成后建议检查一下死链find /mnt/newdisk -type l -xtype l如果输出为空说明没有失效链接。如果有逐个处理或者写脚本重新生成链接。这个细节很多人不看结果业务启动后报各种 No such file or directory排查半天才发现是软链接失效。6. 扩容后的验证与日常运维检查6.1 容量核对与关键目录占用确认扩容完成不代表万事大吉。我习惯做几步验证df -h确认目标目录容量变化符合预期。这里注意如果系统里同时存在多个挂载点df 显示的是每个文件系统的总数和已用要看挂载点那一行别只看根目录。du -sh /目标目录确认数据量没有异常。如果新挂载的目录显示数据量异常小可能是复制不完整。lsblk确认设备、分区、挂载点三者对应关系清晰。如果是 LVM 扩容执行pvs、vgs、lvs把三层状态都看一遍确保 PV、VG、LV 大小一致。还可以用df -i检查 inode 使用率。数据量大的场景比如存放大量小文件有时候空间没满但 inode 先用完了这种情况扩容逻辑卷后同时要记得检查 inode 数是否够用。ext4 默认 inode 数量是固定的如果 inode 不够就算空间再大也写不进新文件。6.2 性能测试基础方法扩容后顺手测一下新盘性能确保硬件状态正常。我常用的命令是dd if/dev/zero of/data/testfile bs1M count1024 convfdatasync这条命令写入 1G 数据convfdatasync确保写到物理磁盘而不是停留在页面缓存中否则测出来的是内存速度没意义。测完之后删除测试文件rm -f /data/testfile如果是生产环境的磁盘阵列或者云盘还可以用fio做更细致的随机读写测试但日常验证用 dd 就够了。注意测试前确认目标目录剩余空间足够别拿测试文件把刚扩容的空间又塞满。6.3 未来空间规划给运维留个检查习惯扩容这事儿本质上做的是一次亡羊补牢。真正靠谱的运维习惯是提前预警、提前规划。我现在的做法是每月用df -h和du -x -h --max-depth1 / 2/dev/null | sort -rh查看各目录占用排名及早发现异常增长。日志类目录启用 logrotate 并设置合理保留周期避免无限增长。Docker 镜像定期清理docker system prune、docker image prune清理悬空镜像和停止的容器。给关键目录根目录、数据盘配置监控告警阈值设在 80% 和 90%别等 100% 才收到告警邮件。空间规划上我的个人经验是根分区尽量规划成 LVM哪怕当初安装时只用了一个磁盘也要保留 VG 的扩展能力。哪怕当下不需要以后加盘扩容也比直接调分区表安全得多。云服务器上尤其如此——大多数云平台都支持在线扩展云盘配合 LVM基本能做到免停机扩容。最后再分享一个小技巧如果你用的发行版是 Ubuntu根分区扩容时还经常用到lvresize --resizefs的组合命令它会把逻辑卷和文件系统一次性扩展。CentOS 这边没有--resizefs选项所以要先lvextend再resize2fs或xfs_growfs。不同发行版命令集有差异但核心概念完全一样——认准 PV、VG、LV 三层结构再按文件系统类型选对扩展命令根目录或指定目录的扩容就是一件可以标准化复用的常规运维操作。