先交代背景。这台 Rocky Linux 8.10 跑着几个测试服务,容器数了数有 7 个,站点、测速、几个内部应用都在上面。当初装系统时候觉得区分一下,数据单独一份,系统单独一份,LVM 自动分成了三块:root 70G、swap 7.84G、home 159G。但是后面想了想,一个测试环境,整块磁盘只有256G,而且没有特别重要的资料。这样只分了两个区,每次调试软件和容器还要去指定存储位置,反而更加麻烦,于是干脆一口气全给“/”目录上了。
问题就在最后那个 159G 上。它建好之后基本没动过——里面只有一个从没登录过的账号,加上 .bashrc、.bash_profile 几个默认文件,du -sh 出来 12K。真正干活的根分区反倒常年 31%,镜像、日志、构建缓存全挤在 70G 里。
先别急着动手,把现状看清楚:
lsblk # 物理盘、分区、LVM 的关系
vgs # 卷组还剩多少空闲
lvs # 三个逻辑卷各自的容量
这一步没什么技术含量,但很多人跳过,后面就容易把卷名写错一个字母。

本来打算迁 Docker,算了一下不划算
第一反应是把 Docker 的数据目录挪到 /home 去。命令都想好了:停 Docker、rsync 复制 11G 的 /var/lib/docker、改 daemon.json 加 data-root、处理 SELinux 上下文,最后启动验证。但是方案写到一半我停下来了,这事儿的代价不只是这半小时:以后每次重建这台机器、每加一台新机器,都得记得"这台的数据目录在 /home 下面"这个特殊配置。而它换来的,只是让空间从"根分区"挪到"同一块物理盘上的另一个逻辑卷"。
单盘机器上,LV 隔离买不到任何冗余——盘一坏,两个逻辑卷一起没。它唯一的价值是重装系统时保住数据——对一台测试机来说,这个价值也没多大。于是改主意:把 home 整个删掉,空间还给 root。这样 Docker 一个参数都不用改,/var/lib/docker 原地就能用上 229G。
代价是不可逆。XFS 从设计上就不提供缩小功能,没有 xfs_shrink 这种东西——ext4 好歹还能用 resize2fs 缩一下(得先卸载、跑 fsck,还得担心 inode 分布,不是百分百稳),XFS 连这条路都没有。lvremove 敲下去,就真的回不了头。所以动手前的检查比动手本身更重要。
动手前先看清楚三件事
第一件,谁在占着 /home。
fuser -vm /home
如果这条命令列出 PID,说明有进程的工作目录或者打开的文件在里面,这时候 umount 一定失败。我这台的输出只有一行 kernel mount /home,那是挂载本身占着,不是用户进程,这种就算干净。

顺手也确认了那个账号确实没用:last -n 3 xiaozou 没有任何登录记录,ps -u xiaozou 也没进程。
第二件,fstab 里有没有 /home 的挂载条目。
有的。/dev/mapper/rl-home /home xfs defaults 0 0。这条不注释掉,重启时系统找不到这个 LV,会直接掉进 emergency mode。
第三件,也是最多人忽略的:grub 的启动参数里有没有写死这个 LV。
cat /proc/cmdline
grep GRUB_CMDLINE_LINUX /etc/default/grub
很多发行版装系统时会把 rd.lvm.lv=rl/root rd.lvm.lv=rl/home 这类参数塞进内核命令行,让 initramfs 提前激活这些逻辑卷。LV 删了但参数还在,重启就会卡在 initramfs 阶段等一个永远等不到的设备。
我这台只有 rl/root 和 rl/swap,没有 home,省了一步。如果你的机器有,得先改 /etc/default/grub,跑 grub2-mkconfig 重新生成配置,再用 dracut -f 重建 initramfs,然后才能重启。
确认完就开始备份。
vgcfgbackup -f /root/vg-rl-20261022.bak rl
tar czf /root/home-backup-20261022.tar.gz -C / home
cp -a /etc/fstab /etc/fstab.bak-20261022
vgcfgbackup 存的是 LVM 的元数据,不是数据本身,真出事它救不回文件,但至少能让你看清原来的布局。home 那份 tar 就是全部内容,12K,压缩完几乎不占地方。

卸载、删卷、扩容
这三步是连贯的,中间没有回头路。
umount /home
lvremove /dev/rl/home
lvextend -l +100%FREE /dev/rl/root
xfs_growfs /
umount 成功之后 findmnt /home 应该什么都查不到。

lvremove 会要你输一次 y 确认,删完 lvs 里就只剩 root 和 swap 了。

lvextend -l +100%FREE 是把卷组里所有空闲空间都给 root。这时候 lsblk 和 lvs 显示的是新容量,但 df -h 还是旧数字——因为文件系统还没跟着长。

最后一条 xfs_growfs / 才是让 XFS 认领新增空间的那一步。它是在线操作,不用卸载、不用重启,df -h 里的 70G 直接变成 230G。


如果换成 ext4,这里就不是 xfs_growfs 而是 resize2fs /dev/mapper/rl-root。命令不一样,原理一样:先扩逻辑卷,再扩文件系统,两步不能省。
把 /home 重建回来
分区没了,/home 这个路径还得在。不少程序会去读它,SSH 登录也依赖它。
mkdir -p /home
restorecon -v /home
tar xzf /root/home-backup-20261022.tar.gz -C / --numeric-owner
restorecon -Rv /home
--numeric-owner 是为了保住原来的 uid/gid,不然解压出来的目录会归到当前用户身上。
restorecon 这一步不能省。这台开着 SELinux(Enforcing),/home 要 home_root_t 标签,用户家目录要 user_home_dir_t。上面写了两条,实际操作时最后那条带 -R 的已经把整棵树修好了——截图里能看到 .bashrc 这些文件的标签从 default_t 被改成 user_home_dir_t。
漏了会怎样?用户登录各种 Permission denied,但报错信息完全不提 SELinux,很容易往权限、密码、sshd 配置上查,白绕一大圈。
ls -Zd /home /home/xiaozou
正确的输出长这样:
system_u:object_r:home_root_t:s0 /home
unconfined_u:object_r:user_home_dir_t:s0 /home/xiaozou
然后是 fstab。把那行注释掉,别删——留着注释比删干净更好,以后翻回来看得见这里原来是什么。
sed -i 's|^/dev/mapper/rl-home|#/dev/mapper/rl-home|' /etc/fstab
mount -a
mount -a 没报错,说明 fstab 语法和引用都对得上。

过程中可能卡住的几个地方
umount /home 报 target is busy 是最常见的。除了 fuser -vm /home,还可以用 lsof +D /home 看具体是哪个进程开着里面的文件。十有八九是有人 cd 进去过,或者某个服务的日志写在家目录下。把人清出来再卸。
lvremove 如果提示 "Logical volume rl/home is used by another device",一般是它还在挂载表里,或者被当成 swap 用了。findmnt /home 和 swapon --show 过一遍就能定位。
麻烦一点的是 xfs_growfs 报 "not a mounted XFS filesystem"。这个报错基本只有两种原因:路径写成了设备名(要写挂载点 /),或者刚开始那条 umount 其实没成功。跟 LVM 本身没关系。
还有一种情况是全部做完、重启掉进 emergency mode。翻回去看 fstab:rl-home 那行还在,或者已经注释了但 /home 目录被一起删掉了。前者改 fstab,后者一条 mkdir /home 加 restorecon 就能救回来。
验证,别只看 df
df -h / 显示 230G,事情只完成了一半。还得确认业务没受影响。
docker ps -a
ss -lntp | grep -E ':(8080|8443|8088|9999) '
7 个容器全是 Up,四个端口都在监听。因为 Docker 的数据目录没动过,容器启动时读的还是原来那些路径,迁移风险为零——这也算选这条路的一个隐性收益。

收尾时顺手在 Grafana 上看了一眼。这条曲线之前在 31% 附近躺了大半年,现在掉到 9.9%,node_filesystem_size_bytes 也跟着变成 229GiB。盯监控比只敲一条 df 更有说服力。
做完之后的分区布局
| 项目 | 调整前 | 调整后 |
|---|---|---|
/ 容量 | 70G | 229G(可用 207G) |
/ 使用率 | 31% | 9.9% |
| 逻辑卷 | root 70G + home 159.05G + swap 7.84G | root 229.05G + swap 7.84G |
/home | 独立挂载 rl-home | 根分区下的普通目录 |
| 停机时间 | — | 约 30 秒(只跑了几条 LVM 命令,没有数据搬迁) |
什么情况下别这么干
这套操作适合"分区切错了、想把空间还回去"的场景。但有两种情况建议保留独立的 /home:
- 一是数据比系统重要、且盘不止一块。系统盘重装、数据盘挂着不动,这时候 LV 隔离是真的有用。
- 二是这台机器将来要频繁重装系统做实验。数据跟系统分开,重装时少一层心理负担。
反过来,如果像我这样:单块盘、数据量很小、机器就是个测试环境,那把空间合并成一个池子更省心。少一个分区,就少一处"这个目录到底该放哪"的犹豫。
最后提醒一句:lvremove 之前的所有检查,都是为了让这一步不用后悔。真删完了,能救你的只有那份提前打好的 tar。
如果你觉得这篇文章不错,有用的话可以点击下面的“赞赏”支持作者,你的支持是我更新的动力(饿饿吃饭)。


Comments NOTHING