做运维的朋友应该都遇到过这种场景:装系统时分区没规划好,或者以前规划的时候压根没细想,默认给了/home很大的空间,结果跑了几个月,发现/var分区被日志、缓存、数据库文件给塞满了,告警邮件一封接一封;而/home那边几百个G闲着,连零头都没用上。这时候最不想干的事就是重装系统或者把数据拷出来再重新分区。CentOS7下用LVM(逻辑卷管理)就能很方便地解决——把/home腾空,把空间匀给/var,整个过程能在线完成,数据也不用大动干戈。这篇博文就把我实际操作中的步骤、原理、还有踩过的坑都捋一遍,照着做基本能少走弯路。
1. LVM究竟是个什么底层机制
1.1 物理卷、卷组、逻辑卷三层关系
很多新手听到LV扩容觉得很高深,其实LVM的本质就是给磁盘加了一层“虚拟化”。它把物理磁盘划分成物理卷(PV),多个物理卷聚合成一个卷组(VG),卷组里的空间再按需切给逻辑卷(LV)。你平时看到的/dev/mapper/centos-root、/dev/mapper/centos-home这些都是逻辑卷。系统读写文件时,LVM负责把逻辑卷上的数据映射到物理卷上的具体位置。
这层抽象最大的好处就是——分区大小不再是死的。传统分区用fdisk切完之后,想要改大小只能删了重建;而LVM的逻辑卷可以在线扩大,甚至可以从一个卷里把空间挤出来,挪到另一个卷里。这正是“减少home增加到var”能实现的前提。
1.2 为啥能腾挪,关键在PE这个最小单位
逻辑卷的空间分配单位叫PE(Physical Extent),默认大小是4MB。你在创建VG、扩容LV的时候,LVM本质上就是在做PE的分配和回收。你缩减/home的LV,就是从home所属的PE中“释放”出一批空闲PE还给VG;你扩展/var的LV,就是把VG里的空闲PE再分配给var。整个过程就像从一个大仓库里先腾出一块区域,再划给另一个部门用,物理磁盘上数据所在的位置可能变,但这些事情LVM在底层处理,上层文件系统只需要配合调整自己的元数据。
这也是为什么缩容比扩容复杂:扩容只需要把新的PE块加进来,文件系统再扩展一下自己的空间信息就行;缩容则牵涉到把文件系统里的数据往前面搬、把后面的块释放掉,数据一多,操作起来就必须非常小心,顺序错了可能直接干掉整个文件系统。
1.3 为什么默认安装时home往往特别大
CentOS7装系统时,如果用自动分区,安装器经常把大部分剩余空间分给/home。你要是选择“手动配置分区”但不改大小,它也常按默认的比例来。等于说很多服务器的/home一开始就是个“隐形大块头”。但实际上,无论是跑Web服务、容器、数据库,还是充当监控、日志收集节点,真正吃磁盘的都是/var/log、/var/lib、/var/cache这些目录。于是“home白白闲着、var天天告急”的矛盾就这么来了。
2. 动手前的风险评估与分区现状摸底
2.1 真实场景案例:某台服务器的分区现状
我以之前处理过的一台某业务服务器为例。运行环境是CentOS7.9,磁盘是一块500G的云盘,LVM卷组名是centos。安装系统时用的是默认分区方案,结果如下:
- /dev/mapper/centos-root:50G,挂载 /
- /dev/mapper/centos-home:400G,挂载 /home
- /dev/mapper/centos-var:50G,挂载 /var
这台机器跑的是应用服务加日志采集,几百个用户数据都放在数据库里,实际存在/home下面的文件大概只有20G。而/var/log和/var/lib/mysql一路疯涨,眼看50G就撑不住了。df -h里/var的使用率到了92%,再这么下去,服务随时会崩。这时候最稳的解法就是:把/home的400G瘦身成40G,匀出360G给/var。
2.2 核心风险提示:这一步必须放在最前面
在我正式开始讲具体命令之前,必须先泼一盆冷水:所有涉及缩容的操作都存在数据损坏风险。缩容逻辑卷时,如果文件系统缩容失败,或者中间断电,数据就有可能丢。所以一定、一定、一定要先备份。哪怕你觉得“这台机器上没什么重要数据”,也至少要确认这一点。我之前就有一次帮别人处理服务器,对方说“home随便搞”,结果/home里藏着一个从来没人提过的归档备份目录,几十个G,还好提前备份了,不然后果完全不敢想。
备份方式可以根据数据量选:数据量小直接tar打包到其他分区;量大就考虑用rsync同步到另一台机器或者挂载的存储盘。备份这一步,做不做、做到什么程度,直接决定了后面操作的风险等级。
2.3 先看清现状:检查文件系统类型和挂载情况
实际操作前,先确认三件事:文件系统类型、当前挂载情况、逻辑卷的具体尺寸。CentOS7默认文件系统一般是xfs,但有些场景会手工做成ext4。xfs和ext4在扩容缩容上有本质区别,这一步没搞清楚,后面很容易直接踩爆坑。
先看挂载和文件系统类型:
df -hT输出类似这样:
Filesystem Type Size Used Avail Use% Mounted on /dev/mapper/centos-root xfs 50G 6.3G 44G 13% / /dev/mapper/centos-home xfs 400G 20G 381G 5% /home /dev/mapper/centos-var xfs 50G 46G 4.0G 92% /var再看LVM底层的卷组情况:
vgs lvs pvdisplayvgs看卷组总容量和剩余空间,lvs看每个逻辑卷的大小,pvdisplay看物理卷的具体情况。要是卷组里本来就有空闲空间,那根本不用动home,直接lvextend var就行。但大多数默认安装的场景下,VG的空间已经被home占完,所以必须先从home那边“挤空间”出来。
2.4 xfs和ext4的扩容缩容差异
这里必须重点提一下xfs和ext4的区别,因为很多人就是栽在这上面:
- xfs文件系统:可以在线扩容,但不支持缩减。也就是说,如果/home是xfs,你不能直接resize2fs把它缩小,再lvreduce。必须走备份、卸载、删除逻辑卷/重建逻辑卷、格式化、恢复数据的路子,或者用一些弯道操作。
- ext4文件系统:既支持在线扩容,也支持在卸载状态下缩容。缩容顺序必须是:先缩小文件系统,再缩小LV;扩容反过来,先扩LV,再扩文件系统。
CentOS7默认的/home和/var基本都是xfs,所以标题里“减少home”这个操作,对xfs来说实际上是“把home的数据备份走、删掉原LV、创建新小LV、格式化、挂载、还原数据”。如果数据量大,这个过程就会比较痛苦;这也是为什么我一直在强调先看文件系统类型。如果你的home恰好是ext4,那倒是可以直接走缩容流程,会快很多。
3. 核心实操步骤:缩减home、扩容var
3.1 第一步:备份home并卸载
在动/home之前,必须先把数据备份出来。我是用rsync将/home下所有数据同步到/backup目录的:
mkdir -p /backup rsync -avxP --delete /home/ /backup/rsync参数说明:-a表示归档模式保留权限和时间戳,-v显示过程,-x不跨文件系统,-P显示进度并支持断点续传,--delete删除目标端多余文件,确保两边完全一致。备份完成后,用diff或者再跑一次rsync检查一下一致性。
接下来卸载/home。如果服务器上没有任何服务依赖/home,直接:
umount /home这一步通常没问题。但有时候umount会提示target is busy,说明有进程正在使用/home目录下的文件。需要先找出来并处理掉。一般用:
fuser -mv /home lsof | grep /home找到占用进程后,能停的先停,或者用fuser -km /home强制杀掉。这一步在生产环境要特别小心,不要误杀关键进程。杀完之后再次umount,直到成功。
3.2 第二步:删除或缩减home逻辑卷
这里分两种情况。如果你的home是xfs,不支持缩减,最简单干脆的做法是直接删掉整个home LV,然后用回收的空间创建一个小一点的home LV:
lvremove /dev/centos/home等等,在lvremove之前,还得先把/etc/fstab里关于/home的挂载项处理好,不然后面重启会起不来。你可以在fstab里临时注释掉,或者等创建了新LV之后再把新UUID写回去。我习惯于先注释掉,后面重建完成再补上。修改fstab用:
vi /etc/fstab找到类似这一行:
/dev/mapper/centos-home /home xfs defaults 0 0在行首加#注释掉。
然后删除LV:
lvremove /dev/centos/home系统会询问是否确认,输入y。此时卷组里就多出来400G的空闲空间。接下来创建新LV:
lvcreate -L 40G -n home centos这条命令的意思是,在卷组centos里创建一个名字叫home、大小40G的逻辑卷。然后格式化:
mkfs.xfs /dev/centos/home再挂载:
mount /home确认没问题后,把fstab里的注释恢复,最好把挂载方式改成UUID方式,避免以后设备名错乱:
blkid /dev/centos/home把输出的UUID写到fstab里。
最后把备份数据还原:
rsync -avxP /backup/ /home/如果/home数据量小,这个流程几分钟就完成。但如果数据量大,备份、恢复两头都要花时间,这时候务必预留足够的窗口期。
3.3 第三步:把空间分给var
home释放出来的空间,现在回到了卷组centos里。可以先确认一下:
vgs看到Free那一列变了,就说明空间已经回到VG了。接下来把多出来的空间全部分配给var:
lvextend -l +100%FREE /dev/centos/var这里我用了-l +100%FREE,意思是把卷组里所有剩余空间都扩展到var逻辑卷。也可以用更精确的写法,比如:
lvextend -L +360G /dev/centos/var如果卷组剩余空间刚好是360G,这效果一样,但用百分比更省事,不需要手算。我个人在这个场景喜欢直接+100%FREE,毕竟home已经缩到够用,剩下的全给var就是目标。
3.4 第四步:扩容var文件系统
LV扩容完成,只代表块设备层有了更多空间,文件系统还要再“吃”进来才算真正可用。xfs用xfs_growfs,ext4用resize2fs,千万别搞混。对xfs执行:
xfs_growfs /var注意,xfs_growfs后面的参数是挂载点,不是设备路径。它支持在线扩容,不需要卸载。执行完输出里会显示新的块数量,说明文件系统已经扩大。
如果var是ext4,则执行:
resize2fs /dev/centos/varext4的resize2fs同样支持在线扩容。这里再次提醒,xfs千万别用resize2fs,会直接报错不认文件系统类型;ext4也千万别用xfs_growfs,同样报错。我见过有同事把这两个搞混,结果以为操作失败,折腾了半天排查,其实只是工具用错了。
3.5 第五步:验证结果并更新fstab
全部弄完后,该验证了:
df -hT lvdisplay确认var已经变成400G左右,home是40G左右,并且正常挂载。
同时还要确认fstab里的home挂载项没有任何问题。用:
mount -a这条命令用于重新加载fstab里的所有挂载项。如果没报错,说明fstab没问题。如果报错,马上看是不是设备名写错了或者UUID不对。修完之后可以shutdown -r now重启验证一次,确保重启后一切正常。虽然重启会短暂中断服务,但比起“一周后发现起不来”,这个代价要小得多。
4. 常见问题与排查技巧实录
4.1 umount提示target is busy,卸载不掉
这是最常遇到的第一个坑。卸载/home时提示:
umount: /home: target is busy原因基本只有一个:有进程打开着/home目录里的文件。排查手段:
fuser -mv /home会列出使用/home的进程PID和命令行。也可以用:
lsof | grep '/home'看到进程后,能正常停的就正常停;确实停不了的,用:
fuser -km /home强制终止。但这个命令要慎用,生产环境上杀错进程的影响可能比磁盘空间告警还严重。所以最好先人工看一遍lsof的结果,确认这些进程到底在干嘛,再决定动作。
有一种特殊情况:当前用户的工作目录就在/home下,比如你用某个账户登录后cd到了/home,那也会导致卸载失败。解决方法是切到/或其他目录再卸载。
4.2 lvremove报错,提示逻辑卷正被使用
即使umount成功了,lvremove仍然可能提示“/dev/centos/home: contains a filesystem in use”,或者类似“Logical volume centos/home in use”。这有可能是某个进程仍持有句柄,也可能是udev设备状态还没更新。处理办法:
lvchange -an /dev/centos/home dmsetup remove_all然后重新查看状态。如果还不奏效,用lsof再次检查是否有进程持有句柄。还不行的话,有一个终极大招就是重启机器,反正fstab里你已经注释掉了home,重启之后home不会挂载,LV设备也会释放,再lvremove就顺畅了。
4.3 扩容后df -h看不到新增空间
LV已经lvextend了,但df看到的大小没变化。这种情况几乎都是忘记了最后一步——文件系统扩容。xfs的需要xfs_growfs,ext4的需要resize2fs,这步绝对不能省。只要执行完对应命令,df就会体现出变化。
4.4 误用resize2fs去缩xfs,报错“Filesystem has unsupported features”
这个坑很隐蔽,有可能会遇到:某些教程在写“缩小home”操作时,直接甩一句resize2fs /dev/centos/home 200G,但你的home是xfs,执行时会提示:
resize2fs: Bad magic number in super-block while trying to open /dev/centos/home这里根本不是“坏”了,而是文件系统类型不支持。xfs没有缩小工具,不要在xfs文件系统上尝试缩小操作。唯一的正道是备份、删除、重建、恢复。如果遇到数据量特别大、没法轻松备份的机器,建议在业务低峰期操作,或者干脆评估另一套方案——保留home不动,另加一个新磁盘挂到/var上。
4.5 重启后进不了系统,卡在挂着home设备
这种情况多半是fstab没有处理好。要么注释不彻底,要么重启后又把旧的home挂载项启用了,但LV已经被删,于是开机就报错。挂在失败的时候会提示按Ctrl+D进入维护模式。进入维护模式后,把fstab里的home那一行注释掉或改成新UUID,再重启就好。这也是我为什么一直强调mount -a和重启验证这两个步骤,不要省略。
5. 另一种常见思路:保留home不动,直接加物理卷扩容
有时候home虽然占着空间,但业务上确实还需要继续往home里写数据,不太想动它。这时候可以换个思路:如果有条件加一块新磁盘,把它做成物理卷并加入到卷组centos里,然后直接把VG的空间扩大,再lvextend给var。这样完全不需要碰home,操作风险更低。
步骤是:
pvcreate /dev/sdb vgextend centos /dev/sdb lvextend -l +100%FREE /dev/centos/var xfs_growfs /var三分钟搞定,啥都不用迁,也不用卸载。这个方案适合那种磁盘空间整体不够、而不是分区比例失衡的场景。
另外还有一种思路是把/var下的某几个子目录直接挪到独立分区或另一块盘上,比如把/var/lib/docker、/var/log单独挂盘。逻辑上更干净,也能避免和系统分区抢空间,但这属于“未来的规划”,解决不了眼前“var快满了”的燃眉之急。作为运维,解决问题既要看当下的需求,也要考虑以后的增长模式:如果日志增长非常快,可能这次给了400G,半年后又满了;这时候就该考虑把/var/log放到独立磁盘、配上日志轮转,从根上解决问题。
6. 几个我特别想提醒的实操细节
6.1 操作窗口期要留足
缩减home再扩容var,如果走的是重建home这条路,中间有很长一段时间home是不可用的。业务上有任何依赖/home的服务,都要提前停机或切换。我一般在计划操作前会先做一次全量备份,再和业务方确认操作窗口,然后才动手。
6.2 格式化之前必须确认设备路径
lvremove之后重建home,mkfs.xfs /dev/centos/home这步非常危险。如果设备路径写错,比如说手滑把/dev/centos/var给格式化了,那数据直接全部消失。我在执行前会反复确认lvs的输出,核对设备名。有条件的话,甚至可以先给lvm的LV做一个快照,万一操作出错还能回滚。
6.3 云服务器的特殊注意事项
如果你的服务器是云主机,还有一层额外的东西要考虑:云平台上的磁盘可能本身就能在线扩容。比如云盘控制台先把磁盘从500G扩到800G,然后进系统用growpart、pvresize把新空间吸收进VG,最后lvextend给var。这种路径比“从home挤空间”更平滑,不需要动home,也不需要考虑数据搬移。同理,如果是物理机,可能就要考虑RAID卡、阵列等相关因素,不同环境差别很大。
我在某云环境上处理过一个类似问题,思路就是控制台扩云盘——系统里pvresize——lvextend——xfs_growfs,四步就完成了。这种方法也有局限性:云盘扩容需要花钱,而且有些老实例类型不支持在线扩容。具体操作前最好先去控制台看看支持不支持。
6.4 调整完别忘了监控
空间调整完不代表一劳永逸。日志类分区增长非常快,建议配置好日志轮转(比如logrotate),并且加一个简单的磁盘空间监控脚本或者接入监控系统,到80%就告警。否则下次再发现的时候,又是急到跳脚的场景。
以前我给某台机器配过一个简单的cron任务:
*/10 * * * * df -h | awk 'NR>1 && $5+0>=85 {print $0}' | mail -s "disk alarm" ops@example.com简单粗暴,但确实能在空间打满之前提前发现。建设一个完善的监控体系,这一块的价值其实比“会扩容命令”大多了——毕竟扩容解决的是已经发生的问题,监控解决的是“还没发生的问题”。
6.5 关于“减少home增加var”的最终操作顺序总结
最后再帮你理顺一遍整体顺序,避免来回折腾:
- 检查文件系统类型:df -hT确认home、var的是xfs还是ext4。
- 备份/home数据:rsync到/backup或其他安全位置。
- 停止使用/home的进程,卸载/home。
- 注释fstab里的home挂载项。
- 删除home逻辑卷:lvremove。
- 创建新home逻辑卷并格式化:lvcreate、mkfs.xfs。
- 挂载新home并恢复数据。
- 把释放的空间扩展给var:lvextend -l +100%FREE。
- 扩容var文件系统:xfs_growfs或resize2fs。
- 更新fstab,重启验证。
这套流程在CentOS7上跑过很多遍,稳不稳的基本要点都在上面说清楚了。核心就是一件事:搞清楚文件系统类型、备份做足、顺序别乱。把这三点做到,这个操作的风险基本可以降到很低。至于其他Linux发行版,只要你用的是LVM管理磁盘,这套思路也是通用的——改改卷组名、包管理器不太一样而已,大方向一模一样。