文章目录
- 前言
- 环境准备
- 一、初始化检查
- 二、安全备份
- [三、进入 emergency 模式](#三、进入 emergency 模式)
- 四、再看一次盘,然后"动刀"
-
- [1. 再次确认当前分区表](#1. 再次确认当前分区表)
- [2. 删除 swap 分区 sda3](#2. 删除 swap 分区 sda3)
- [3. 删除根分区 sda2](#3. 删除根分区 sda2)
- 五、重建sda2
- 六、重启后对XFS做在线扩容
- [七、重建 sda3 作为 swap 分区](#七、重建 sda3 作为 swap 分区)
- [八、初始化 & 挂载 swap](#八、初始化 & 挂载 swap)
- 九、最终状态检查
- 十、数据验证
-
- [1. rpm -Va 校验系统文件](#1. rpm -Va 校验系统文件)
- [2. 读全盘所有文件,看有没有 I/O 错误](#2. 读全盘所有文件,看有没有 I/O 错误)
- 流程总结
前言
在使用 LVM 的场景下,逻辑卷的扩容通常比较轻松。但在某些受限环境中(例如无法连接公网、又处于涉密或内外网隔离环境)或特殊条件下系统采用传统分区模式进行部署。此时,如果根分区空间不足,扩容将变得相对复杂。因为普通分区根目录是直接建立在物理分区之上的,要扩容根分区的话就需要修改磁盘分区表,分区表是系统最底层最关键的数据结构之一,所以操作中一点小失误就会导致数据全部丢失,属于高危操作。但是能不能扩容呢?答案是能!
环境准备
.
模拟环境:Oracle Linux 7.9,MBR 分区表(dos),根分区 / 使用 XFS,非 LVM,磁盘空间20G.
存在分区:
- /dev/sda1:1G,XFS,挂载到 /boot
- /dev/sda2:8G,XFS,挂载到 /
- /dev/sda3:2G,swap

目标:在不丢数据的前提下,将 / 从 8G 扩到 16G,并重新规划 swap。
一、初始化检查
操作前请完整的记录以下数据,尤其是根目录的起始扇区
bash
##查看每个块设备的大小、挂载点
lsblk
##查看文件系统类型和UUID,之后恢复fstab要用
lsblk -f
##查看Start / End扇区
fdisk -l /dev/sda
##确认每个分区当前的UUID,和TYPE
blkid

注意看以下关键信息
text
/dev/sda1 * 2048 2099199 1048576 83 Linux 1G /boot xfs
/dev/sda2 2099200 18876415 8388608 83 Linux 8G / xfs
/dev/sda3 18876416 23070719 2097152 82 Linux swap 2G [SWAP]
- 旧的 / 分区 sda2 的起始扇区:2099200
- swap sda3 的大小:2G
之后我们扩容的时候,sda2 的起始扇区必须保持 2099200 不变,如果起始位置不对则会数据全部丢失,2099200不能多也不能少。
二、安全备份
先备份所有关键信息
bash
mkdir -p /root/backup
fdisk -l /dev/sda > /root/backup/sector.txt
blkid > /root/backup/uuid.txt
cp /etc/fstab /root/backup/fstab.bak
ls -l /root/backup/

这几份东西很重要:
- sector.txt:原始分区表,尤其是 Start / End,之后万一手滑了也能查回来。
- uuid.txt:分区与 UUID 对照表,fstab 里用的是 UUID,就靠这个恢复。
- fstab.bak:万一改坏了 /etc/fstab,还能直接覆盖回去。
三、进入 emergency 模式
在 GRUB 菜单按 e,找到那行以 linux16 开头的内核启动行,在最后面追加:
text
systemd.unit=emergency.target

按 Ctrl + X 启动,就会进入 emergency 模式,输入root密码登录

登录 root 之后,先把根分区重挂载成可读写:
bash
mount -o remount,rw /
四、再看一次盘,然后"动刀"
1. 再次确认当前分区表
bash
fdisk /dev/sda
p # print

2. 删除 swap 分区 sda3
bash
d #删除分区
3 #分区号
p #print
此时 p 输出只剩 sda1、sda2。
这里删除的是分区记录,不是"抹掉数据",磁盘上的数据还在,只是暂时没有分区指向它。
3. 删除根分区 sda2
bash
d
2
p

现在只剩:
text
/dev/sda1 * 2048 2099199 1048576 83 Linux
此时整个 / 分区的内容还在磁盘上,只是分区表不再有 sda2 这一行了,所以后面必须 用完全一样的起始扇区重建。
五、重建sda2
现在用 fdisk 重建 sda2:
bash
fdisk /dev/sda
n # 新建分区
p # 主分区
2 # 分区号 2
2099200 # 一定要填原来的起始扇区 !!!
+16G # 用 +16G 表示分配 16GiB 给这个分区
p # 打印确认
w # 写入分区表

打印出来是:
text
/dev/sda1 * 2048 2099199 1048576 83 Linux
/dev/sda2 2099200 35653631 16777216 83 Linux
此处的关键点:
- Start 仍然是 2099200 → 这就保证了旧数据的位置没变。
- End 扩到了 35653631 → sda2 大小从 8G 变成 16G。
写入后会出现:
text
WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table.
The new table will be used at the next reboot...
这很正常:内核已经在用旧的分区布局,必须重启才会用新的。
bash
reboot
六、重启后对XFS做在线扩容
系统正常启动后,先扩文件系统:
bash
xfs_growfs /

输出:
text
data blocks changed from 2097152 to 4194304
表示 XFS 把数据区从原来的大小扩展到了更大的区间。
然后连着三条确认一下:
bash
df -h ##看 / 的容量是否变成 16G
lsblk -f ##看文件系统和挂载点
fdisk -l /dev/sda

显示只有 sda1、sda2,说明我们成功处理完 root,但是暂时还没恢复 swap。
到这里,根分区扩容 8G → 16G 已经完成。
七、重建 sda3 作为 swap 分区
接下来重建swap
bash
fdisk /dev/sda
p # 确认现在只有 sda1/sda2
n # 新建
p # 主分区
3 # 分区号 3
35653632 # 默认即可,从 sda2 后面开始
+2G # 分 2G 给 swap
p

此时打印:
text
/dev/sda1 * 2048 2099199 1048576 83 Linux
/dev/sda2 2099200 35653631 16777216 83 Linux
/dev/sda3 35653632 39847935 2097152 83 Linux
注意 Id 还是 83 Linux,还没改成 swap 类型。
接着改类型:
bash
t
3 # 选择分区 3
82 # Linux swap / Solaris
p # 再看一眼,Id 已经变成 82
w # 写分区表
reboot

八、初始化 & 挂载 swap
系统起来之后,我们要确保 sda3 已被当作 swap 使用。
bash
##创建并激活swap
mkswap /dev/sda3
swapon /dev/sda3
##查看swap状态
swapon --show

再查一下 /dev/sda3 的 UUID:
bash
blkid /dev/sda3

再检查一下 /etc/fstab

/ 和 /boot 的 UUID 与之前一致(没动过这两个分区的起始扇区里面的文件系统,所以 UUID 不变)。
swap 这一行用的是旧的 UUID(5eda3d...),跟当前 blkid 查到的不一致。
将 fstab 里的 swap UUID 更新为 blkid 查到的新 UUID
bash
UUID=0cd20842-7155-4379-bd96-ff3017feebd3 swap swap defaults 0 0
改完执行:
bash
swapoff -a
swapon -a
swapon --show
九、最终状态检查
最后再跑一遍 fdisk -l:

再配合:
bash
df -h
lsblk -f
swapon --show
就能确认:
- 根分区从 8G → 16G
- swap 分区 2G
- / 和 /boot 的 UUID 未变化
- 系统可以正常启动
十、数据验证
1. rpm -Va 校验系统文件
bash
rpm -Va
只要没有大面积 missing、size mismatch、MD5 mismatch 之类致命错误,就说明rpm 管理的系统文件没有损坏。
2. 读全盘所有文件,看有没有 I/O 错误
bash
find / -xdev -type f -exec cat {} > /dev/null \;
这条命令的含义是:
- 遍历根文件系统里所有普通文件
- 尝试把它们全部读一遍
- 任何磁盘坏块、inode 断链、文件系统元数据损坏,都会在这里暴露为 I/O error
跑完后,如果没有返回则是数据无损坏

流程总结
- 看清当前分区状态
- 做备份(分区信息 + fstab + UUID)
- 进 emergency 模式
- 删除旧的 sda2/sda3
- 用同一个起始扇区重建 sda2
- 重启后对 XFS 做在线扩容
- 用剩余空间重建 sda3 + 改类型为 swap
- 初始化 & 挂载 swap,并修 fstab
- 最后做"数据没坏"的验证
由于操作风险高,每一步需要谨慎再谨慎,我第一次模拟测试的时候就因为起始扇区写错导致数据丢失无法开机了。