☰
LVM实战:CentOS7下将/home富余空间安全扩容给/var
2026/10/18 9:20:17 网站建设 项目流程

“home富得流油、var快要爆掉”,这大概是每个Linux运维都会撞上的经典场面。我手头一台CentOS7测试服务器,装系统时图省事给/home单独划了500G,/var只给了50G。结果跑了不到两个月,Nginx日志、yum缓存、数据库临时文件全往/var里塞,df一看直接血压升高:/var用了93%,/home才用了5%。这台机器当初用的是LVM逻辑卷管理,所以最优雅的解法不是重装系统,也不是临时加一块硬盘,而是直接在逻辑卷层面做“削峰填谷”——把home的容量压下来,把空间补给var。这篇文章就是我完整走了一遍这个操作之后整理出来的流程,会包含前置检查、命令细节、XFS和ext4两条路线的差异,以及我踩过的好几个坑。适合对LVM只知道大概、想把home空间安全调给var的开发者或运维参考。

1. 为什么home会富得流油,var却见底

先聊聊这个需求是怎么冒出来的。很多CentOS7服务器在安装阶段做自定义分区时,都会习惯性把/home单独划分一个大分区,理由是“以后用户数据会很多”。但现实往往是:/home里根本没住几个人,而/var却被日志、缓存、邮件、数据库临时文件这些东西迅速填满。尤其像Nginx的access_log、系统自带的yum缓存、某些中间件写进/var/lib或/var/tmp的数据,增长速度快得出乎意料。

如果这台机器在分区时没有用LVM,用的是一整块磁盘的普通分区,那么遇到这种“home大var小”的局面,确实只能加盘或者重做系统。但CentOS7默认安装就推荐LVM布局,安装器会把整块盘做成一个物理卷PV,归入卷组VG,再在VG上切出多个逻辑卷LV。逻辑卷的好处在于:同一块VG里的LV之间,容量可以互相调度。home用不完的空间,完全可以拆出来给var,不需要动到物理磁盘本身。

不过这里要先给大家泼一盆冷水:这个操作有一个前置条件,就是home和var必须属于同一个卷组,而且卷组里要存在可用的总容量。如果机器当时把/home和/var划成了两个独立的VG,或者根本没有用LVM,那这篇文章里的方案就不适用,只能换思路。

还有一个容易被忽略的点:为什么var会不够用?如果只是某一次日志暴涨,那清日志比动分区更明智。假如var长期维持在高水位,那才值得做真正的扩容。所以动手前,先搞清楚var里的空间到底是被谁吃掉的——是/var/log、/var/lib,还是/var/cache。这个判断直接影响后面“缩到多小、扩到多大”的目标数字。

2. 操作前必须看懂的磁盘家底:几条命令读出关键信息

2.1 先跑四条基础命令

正式开始调整之前,我会先把下面这组命令跑一遍,确认机器状态:

df -hT vgs lsblk blkid

df -hT是为了看挂载点、容量、使用率和文件系统类型。vgs看卷组,重点看VFree这一列,也就是卷组里还有多少空闲空间。如果VFree已经大到你计划给var增加的量,那根本不用动home,直接给var扩容就完事了。这一步经常被我忽略,实际上也是最省事的一种情况。

lsblk看块设备层级,确认磁盘底层是不是lvm。如果输出里没有LVM字样,说明当时装系统没选LVM,后续方案作废。blkid看每个逻辑卷真实的文件系统类型和UUID,这是判断接下来走哪条路的关键依据。

2.2 从输出里读出关键信息

一台典型机器的参考输出大概是这样的:

$ df -hT Filesystem Type Size Used Avail Use% Mounted on /dev/mapper/centos-root xfs 50G 20G 30G 40% / /dev/mapper/centos-home xfs 500G 10G 490G 2% /home /dev/mapper/centos-var xfs 50G 46G 4G 92% /var $ vgs VG #PV #LV #SN Attr VSize VFree centos 1 2 0 wz--n- 550.00g 0 $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 550G 0 disk └─sda2 8:2 0 550G 0 part ├─centos-root 253:0 0 50G 0 lvm / ├─centos-home 253:1 0 500G 0 lvm /home └─centos-var 253:2 0 50G 0 lvm /var

注意vgs输出的VFree是0,说明整个VG的550G已经全分完了。这时要让var变大,唯一的路就是调整home。而lsblk显示home和var都是lvm,且属于同一个VG centos,意思是物理基础没问题。

2.3 文件系统类型决定路线

CentOS7安装时默认使用的文件系统是XFS,所以绝大多数人的home和var会是XFS。XFS有个非常硬的限制:只能扩大,不能缩小。后面要把home的容量吐出来,就得先备份、删除旧LV、重建新LV,再恢复数据。如果当初你在安装时把home手动指定成了ext4,那恭喜你,可以走“在线瘦身”路线,用resize2fs先缩文件系统,再让lvreduce把LV缩小。第4章和第5章分别讲这两条路。

2.4 规划目标数字与备份方案

动手之前,把目标数字写下来。比如我当时的规划是:

  • home当前实际使用10G,目标缩到30G,留20G余量给未来用户数据;
  • var当前已用46G,目标扩到120G,对应未来两到三个月日志和缓存增长;
  • 剩余空间留在VG里作为“机动池”,谁满了给谁加。

备份位置同样要提前想好。最忌讳的是把备份放到home自身或var自身,因为后面这些LV本身会被改动。我一般临时挂一块数据盘到/backup,或者rsync到另外一台服务器。即便你只是把home从500G缩到30G,重建LV也相当于推倒重来,不备份就是赌命。

3. 关键岔路:XFS与ext4对“缩小”的容忍度完全不同

3.1 XFS为什么不能缩小

XFS在设计上是专门冲着大文件、高并发、大容量去的,它的元数据结构和空间管理逻辑都是为“增长”设计的,官方从始至终没有提供缩小文件系统的能力。如果你在XFS的LV上直接执行lvreduce,LVM会警告文件系统不支持shrink,继续操作等于销毁文件系统。有人不信邪,加个-y硬跑,后果就是/home整个目录树直接消失。这个坑我见过不止一次,属于这个操作里最经典的翻车原因。

3.2 ext4的缩容机制

ext4是支持缩容的,但缩容动作必须在文件系统未挂载状态下做。先umount,再用resize2fs把文件系统缩到目标大小,最后才能lvreduce缩小LV。LVM其实提供了-r参数,能自动调用resize2fs,但在生产环境我第一次操作时还是选择手动分开执行,每一步看输出,出了问题也知道是哪一步。

3.3 两条路线对比

文件系统支持在线扩大支持缩小缩小方式推荐路线
XFS支持,用xfs_growfs不支持只能备份、删LV、重建LV、恢复第4章
ext4支持,用resize2fs支持,但需先卸载先resize2fs缩文件系统,再lvreduce缩LV第5章

这里多提一句:如果home和var都是XFS,“减少home增加var”这个需求实际拆解动作是“拆掉旧home、重建一个新home、把拆出来的空间补给var”。表面看起来动静大,但只要home里实际数据不多,整个维护窗口也就十来分钟。最怕的是home里堆了几百G又没法快速备份,那种情况就得评估是不是有其他路径,比如直接给var加一块新盘、或者把部分应用数据目录软链到home去。但本文还是围绕最常见“home数据不多”的场景讲。

4. XFS场景下的完整操作:备份、拆home、重建home、扩容var

4.1 准备维护窗口和备份

选一个业务低峰期,先停掉会往/home写数据的任务。比如这台机器上有几个用户的定时任务,我都提前打了招呼让他们退出。然后建立备份目录并开始同步:

mkdir -p /backup rsync -a --delete /home/ /backup/home_bak/

同步完成之后对比两个目录的大小:

du -sh /home du -sh /backup/home_bak

两个数字一致就说明备份完整。如果/home里有正在被写入的日志文件,rsync前最好先停掉相关进程;实在停不了就做两次rsync,第二次只同步增量,也能保证一致性。

4.2 卸载home并处理占用进程

fuser -mv /home umount /home

fuser -mv会列出来哪个进程正在使用/home目录。如果umount返回target is busy,千万别用umount -l直接强制卸载应付了事——那只是表面卸载,进程还卡在原地。正确做法是定位进程,能优雅停就优雅停,实在不行才用fuser -km /home。这台机器上有个screen会话没退出,导致我卡了几分钟,后来把会话结束才正常卸载。

4.3 删除旧home逻辑卷

lvremove /dev/centos/home

执行后LVM会询问确认,输入y。紧接着用vgs再看一眼,VFree应该从0变回约500G。删除前,我用lvdisplay把原来的LV大小、VG名、Profile都截图存了一份。这一步很多人不敢动,其实只要备份在手,删除本身不可怕,真正的风险是后面忘了重建home就重启系统。

4.4 重建一个合适大小的home并挂载

lvcreate -L 30G -n home centos mkfs.xfs /dev/centos/home mkdir -p /home mount /dev/centos/home /home

mkfs.xfs会创建一个全新的空文件系统。挂载时有个坑:如果/etc/fstab里写的是/dev/mapper/centos-home这种路径,直接能挂上;如果写的是UUID,会挂载失败,因为新LV的UUID跟旧的不一样。所以这里建议先手动mount,挂完再回头改fstab。改fstab的细节我在第6章专门讲。

4.5 恢复home数据

rsync -a --delete /backup/home_bak/ /home/

rsync的-a参数很重要,它会把文件权限、属主、属组、时间戳一并恢复。如果不用-a,等你把数据同步回去,用户会发现目录权限全乱了,那种问题比磁盘空间更麻烦。

4.6 给var扩容并放大XFS文件系统

接下来是重头戏,把拆出来的空间补给var:

lvextend -L 120G /dev/centos/var xfs_growfs /var

lvextend -L 120G是把var逻辑卷直接设为120G。如果之前var已经是50G,等价写法是lvextend -L +70G /dev/centos/var,效果一样,看个人习惯。重点在于,逻辑卷LVM层扩大了还不够,XFS文件系统层不会自动跟着变大,必须执行xfs_growfs。通常直接给挂载点即可,比如xfs_growfs /var,也可以写设备路径。

4.7 验证扩容结果

df -hT /home /var mount | grep -E 'home|var'

此时应该看到home 30G、var 120G,并且挂载状态正常。做完之后VG里通常还剩下一些未分配空间,我的建议是先留着不要全部分完,以后哪个分区紧张了直接lvextend,非常方便。

5. 如果你的home是ext4,可以直接走“在线瘦身”

5.1 为什么缩容顺序是铁律

ext4缩容有两个动作:先缩小文件系统,再缩小LV。顺序千万不能反。你可以把文件系统想象成衣柜里的隔板,LV想象成整面墙。必须先让隔板往左挪(resize2fs),再让整面墙往左挪(lvreduce)。万一先挪墙再挪隔板,右边的衣服全被墙挤烂,数据直接没。所以顺序就是:umount -> resize2fs缩小 -> lvreduce缩小 -> mount。

5.2 完整命令序列

假设home是ext4,当前500G,目标缩到30G:

# 1. 备份,同一套备份逻辑 # 2. 卸载 umount /home # 3. 先缩小文件系统到30G resize2fs /dev/centos/home 30G # 4. 再缩小LV到30G lvreduce -L 30G /dev/centos/home # 5. 重新挂载 mount /dev/centos/home /home

resize2fs执行完会打印出新的文件系统大小,确认跟目标数字一致,再往下走。如果输出里有nothing to do字样,多半是目标容量比当前文件系统还大,检查一下是不是单位或者数值写错了。

然后给var扩容:

# 如果var也是ext4 lvextend -L 120G /dev/centos/var resize2fs /dev/centos/var # 如果var是XFS,则用: # xfs_growfs /var

这里特别容易混。很多机器根和/var是XFS,只有手工划出来的home是ext4,所以扩容var时要先想清楚var本身是什么文件系统,再去选对应命令。

5.3 ext4路径的边界条件

ext4缩容还有个现实约束:目标容量不能小于home里的实际数据占用量。比如home已经用了40G,你想缩到30G,resize2fs会直接拒绝。这时要做的不是硬缩,而是先删数据、迁移数据,或者干脆回到XFS那种“备份重建”路线。你自己选哪种,完全看home里数据量大小和能接受的停机时间。

6. 收尾最容易翻车的几个细节:fstab、挂载验证与回滚预案

6.1 fstab里到底要不要改UUID

XFS路线重建home之后,这一步几乎必做。先查新UUID:

blkid /dev/centos/home

然后打开/etc/fstab,把原来home那一行里的UUID替换成新的。改之前顺手备份一下:

cp /etc/fstab /etc/fstab.bak

改完不急着重启,先执行:

mount -a df -hT /home

mount -a会把fstab里所有未挂载的项自动挂一遍,有错当场报出来,总比重启后卡在Emergency模式再进救援修fstab强一百倍。我认识的好几个人都在这里翻过车:home LV删了重建,fstab没改,重启后系统起不来。

6.2 var扩容后的挂载验证

var从头到尾没有卸载,fstab也没动,理论上不用改。但我会习惯性检查一下:

  • mount | grep /var 能看到正常挂载;
  • 往/var/tmp下写一个文件再删掉,确认写权限正常;
  • 重启后df输出依然保持新容量。

有一点务必记住:xfs_growfs改的是文件系统在线状态,不需要改fstab,重启后也不会丢。有人以为扩容完必须在fstab里写点什么,纯属多虑。

6.3 回滚预案怎么看

只要备份还在,回滚的核心就一句话:把home重建回去,把var扩大这事没法让XFS缩回去。所以做决策时要留后路,我的做法是home的最终尺寸宁可先紧凑一点,VG里保留一部分未分配空间。真到了home不够用,就直接用剩余空间lvextend给home,一分钟搞定。最怕的是把VG空间全部分完,以后想动任何一个LV,又得做一次备份重建循环。

6.4 我踩过的几个坑

第一个坑就是lvremove前没仔细看fstab。当时以为删掉home、重建home、更新fstab就行,结果忘了改UUID,重启后系统进紧急模式,最后拿Live系统把fstab注释掉才救回来。从那以后,我养成一个习惯:调整LV前先把/etc/fstab备份一份,改完立即用mount -a验证。

第二个坑是umount /home一直报busy。排查后是有人在screen会话里挂着,当前目录正好停在/home。以后每次操作前,我都会先w看一下有没有用户挂机,再fuser -mv确认占用进程。

第三个坑是命令选错。给var扩容时随手敲了resize2fs /dev/centos/var,结果报错提示文件系统不是ext4,我才反应过来这台机器var是XFS,应该用xfs_growfs。命令敲错了不会马上毁数据,但会把自己吓个半死,所以现在我会先df -hT看清楚类型再选命令。

第四个坑涉及容量精度。lvreduce -L 30G之后,实际df看到的大小偶尔会是29.99G或者30.01G,这是LVM按PE取整的结果,属于正常现象。不要为此反复调整,浪费精力。真正要注意的是在目标值后面多留1G左右余量,给文件系统元数据留点空间,别抠到小数点。

6.5 我现在的操作习惯

最后说一个我自己的习惯:整套操作开始前,把lvs、vgs、df -hT、blkid的输出全部存到/root/lvm_plan_before.txt,操作完成后再存一份after文件。这不算什么高深技巧,纯粹是为了复盘。磁盘扩容这个场景,翻车往往不是命令本身复杂,而是当时手上信息不全,或者做完忘了当初给var定的目标容量。有了前后对照,下次再碰到类似的home/var空间失衡问题,十分钟就能定位并处理完。这台机器后来var很快涨到了100G,我直接拿VG剩余空间lvextend又加了20G,全程没有动home一下,那种顺手的感觉,才是LVM布局真正该有的体验。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询