/boot 独立分区空间不足,是 Linux 服务器运维里最常见也最容易被忽略的老问题。系统跑着跑着,内核一升级,/boot 立马就满,yum update 甚至 apt upgrade 都可能直接报 No space left on device,搞不好服务器重启都进不了系统。我这些年处理过不少类似的故障,也见过很多同事一上来就准备重装系统,其实只要搞清楚 /boot 分区结构、内核清理逻辑和扩容工具的用法,这个问题完全可以在线化解。这篇就把完整的排查、救急和扩容流程都写出来,给被 /boot 折磨过的朋友,也给刚入门的运维新人一个可照抄的作业。
1. 为什么/boot总是空间不足?先搞清楚问题根源
1.1 一个几百MB分区的“慢性死亡”
传统 Linux 安装习惯会把 /boot 单独分出来,尤其是 CentOS/RHEL 系列,安装器默认就给 /boot 分配 500MB 到 1GB。这个容量在新装系统时看起来够用,但内核迭代几次之后就开始紧张。一个内核要装三样东西:vmlinuz(内核本体)、initramfs/initrd(初始内存盘)、System.map 和 config 文件,一套下来大概 40 到 80MB。发行版默认保留 2 到 3 个旧内核,再加上偶尔升级失败没清理的残留,300GB 的根分区没事,500MB 的 /boot 却先满了,这几乎是必然发生的事情。
还有一个容易忽略的点:/boot 不仅是内核文件的家,还承载着 grub 引导配置、grub 的残留模块、内存测试工具 memtest 等。有些机器上 /boot 里还混着旧版本内核卸载不干净留下的 .rpmnew 或 .dpkg-old 文件,这些东西单个看不大,累积起来也很可观。df -h 看的时候 /boot 使用率 100%,但 du -sh /boot/* 一查,往往能发现一堆早就该被清理却一直没被清理的配置文件。
1.2 为什么说它“难扩”
/ boot 独立分区难扩展,本质是分区布局问题。传统 MBR 或 GPT 磁盘上,/boot 通常位于磁盘靠前的位置,后面紧跟着根分区或其他分区。要给 /boot 扩容,必须满足三个条件之一:后面有空闲空间、后面分区能缩小、或者能在分区表里重新排列。问题是根分区正在被系统使用,没法在线缩小,这就让“原地扩容”变得很困难。
更麻烦的是,很多服务器当初安装时并没有预留连续的空闲空间,/boot 前后都被别的分区“夹住”。这种情况下,必须借助 Live 环境(比如 GParted Live、SystemRescueCD、Ubuntu 安装盘)启动系统,再对分区表进行操作。听起来有点复杂,但操作路径其实很固定:先备份,再缩小后面的分区,腾出空间,然后扩展 /boot,最后修复引导。整个过程只要按顺序来,成功率非常高。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 扩容前必做:先把“软性空间”挤出来
2.1 清理旧内核:最立竿见影的急救措施
如果你暂时没法重启服务器,也没有维护窗口,最现实的急救方案是清理旧内核。这一步往往能瞬间释放一两百MB空间,让系统先恢复元气。CentOS/RHEL 系的操作:
bash复制# 查看当前正在使用的内核
uname -r
# 列出系统已安装的内核
rpm -qa | grep ^kernel-
# 删除旧内核(把具体的旧版本号换成实际值)
yum remove kernel-3.10.0-1160.el7.x86_64 kernel-3.10.0-1127.el7.x86_64
删除之后需要重新生成 grub 配置:
bash复制grub2-mkconfig -o /boot/grub2/grub.cfg
Debian/Ubuntu 系则是这样:
bash复制# 查看当前内核
uname -r
# 列出所有已安装的内核镜像
dpkg --list | grep linux-image
# 删除旧内核(注意不要把当前内核删了)
apt purge linux-image-5.4.0-26-generic
Ubuntu 会自动帮你跑 update-grub,但如果你用 dd 方式安装的 grub,建议还是手动再确认一遍引导配置。清理动作一定要看准 uname -r 的结果,别把正在运行的内核干掉了。
2.2 手动清理 /boot 里的临时文件与残留
内核清理完,/boot 里可能还有一堆残留,这些文件不会自动消失,得手动处理。用 du -sh /boot/* | sort -hr 列出来,重点关注这些:
.rpmnew/.rpmsave:RPM 包升级时生成的配置文件备份,确认不需要可直接删除.dpkg-old/.dpkg-dist:Debian 系升级残留,同理- 旧的
config-*、System.map-*:如果对应的内核已经卸载,可以一并删除 initramfs-*.bak:某些升级脚本留下的 initramfs 备份,一般可删
很多情况下,我遇到过 /boot 使用率 100%,但实际内核文件只占了 60%,剩下全是这种历史垃圾。把这些清掉,哪怕不做真正的扩容,系统也能再撑一阵子。
2.3 从源头治理:配置内核保留数量
清理只是治标,治本还得限制系统保留的内核数量。CentOS/RHEL 8/9 或 Fedora 系,编辑 /etc/dnf/dnf.conf,写入:
ini复制installonly_limit=2
这样 dnf 只保留两个内核版本,旧内核会自动进入待清理状态。CentOS 7 对应的文件是 /etc/yum.conf,配置项同样是 installonly_limit=2。
Debian/Ubuntu 系没有这种全局限制配置,但可以靠 apt autoremove --purge 定期清理。更省心一点的思路是写个 cron 脚本,每月跑一次:
bash复制#!/bin/bash
# 保留当前内核 + 上一个版本,其余全部清理
current=$(uname -r)
apt autoremove --purge -y
把脚本放进 /etc/cron.daily/,赋予执行权限,以后基本不用再操心 /boot 爆满的问题。
3. 动手前先定位:你的/boot到底是什么类型
3.1 物理独立分区:最常见,也是重点
先确认 /boot 的类型,用 df -hT /boot 或者 blkid 看一眼。如果是 /dev/sda1、/dev/nvme0n1p1 这种,就是传统的物理独立分区。这种情况下扩容必须借助 Live 环境,因为根分区挂载状态下,分区表不允许被修改。
物理独立分区的扩容核心思路是:在不破坏数据的前提下,把 /boot 后面的空间“挪”一些给它。比如分区布局是:
text复制/dev/sda1 /boot ext4 500M
/dev/sda2 / ext4 100G
需要先缩小 /dev/sda2 的尾部,释放出空闲空间,再把空闲空间重新划分给 /dev/sda1。但 sda2 在 sda1 后面,直接缩小 sda2 尾部释放出的空间在它的末尾,不在 sda1 旁边,所以还需要把 sda2 整体向右移动。这也是整个操作里最耗时、最容易翻车的一步。
3.2 LVM分区:在线扩容最轻松
如果你的 /boot 在 LVM 逻辑卷上(df -hT /boot 显示 /dev/mapper/...),那扩容就简单很多。LVM 天然支持在线扩展,不需要重启,不需要 Live 环境。基本流程:
bash复制# 先看逻辑卷路径
df -hT /boot
# 例如 /dev/mapper/vgroot-lvboot
# 扩逻辑卷(增加500MB)
lvextend -L +500M /dev/mapper/vgroot-lvboot
# 扩展文件系统
resize2fs /dev/mapper/vgroot-lvboot # ext4 文件系统
# 如果是 xfs 则用 xfs_growfs /boot
但这里有个前提:卷组里得有足够的空闲空间。如果卷组满了,还得先把某个物理卷里的空闲空间挪出来,或者新增一块磁盘加入卷组,相对于物理分区的方案,LVM 灵活太多了。所以我在新装系统时,都会建议把 /boot 也放进 LVM,就是为了避免将来这种“物理分区被夹死”的尴尬。
3.3 btrfs子卷或独立/boot/efi场景
部分较新的发行版(如 Fedora Workstation、openSUSE)默认使用 btrfs 文件系统,/boot 可能是 btrfs 下的一个子卷,也可能单独分了一个 /boot/efi。不同情况处理方式差异很大:
- btrfs 子卷:如果根分区和 /boot 同在一个 btrfs 分区里,只是两个不同子卷,就不存在“给 /boot 单独扩容”的问题了,直接用
btrfs filesystem resize max /boot或者修改挂载参数即可 - /boot/efi 是 vfat:UEFI 引导的机器通常有一个独立 EFI 系统分区,几百MB。EFI 分区不建议随便扩容,因为固件对 ESP 的位置和大小比较挑剔。一般情况下,重建 /boot/efi 或者把多余的内核文件清理掉比扩容更安全
- /boot 是 xfs:xfs 不能缩小,只能扩大。如果你的 /boot 空间不足且它是 xfs,只能想办法扩展分区或者重建,无法像 ext4 那样先缩后扩
3.4 不同场景的扩容路线对比
| 场景 | 文件系统类型 | 扩容难度 | 推荐方案 |
|---|---|---|---|
| 物理独立分区(ext4) | ext4 | 中高 | GParted Live 改分区表,需重启维护窗口 |
| 物理独立分区(xfs) | xfs | 高 | 只能扩大不能缩小,通常需要重建分区 |
| LVM 逻辑卷(有free空间) | ext4/xfs | 低 | lvextend + resize2fs/xfs_growfs,在线完成 |
| LVM 逻辑卷(卷组满了) | ext4/xfs | 中 | 新增 PV 或腾挪空间后再扩 |
| btrfs 子卷 | btrfs | 低 | btrfs filesystem resize,在线完成 |
| /boot/efi 独立分区 | vfat | 不建议扩 | 清理文件或重建引导,避免动 ESP 分区表 |
从表格能看出来,扩容难度很大程度上取决于你当初的选择。老机器上物理分区是最常见的,也是接下来要重点讲的操作场景。
4. 实操全过程:用GParted Live给/boot分区扩容
4.1 备份与准备:宁可多花十分钟,别赌人品
扩容操作会直接改分区表,一旦中断或者操作失误,系统很可能起不来。所以第一步永远是备份。要备份的内容分两部分:
- 系统配置:
/etc/fstab、/etc/default/grub、/boot/grub2/grub.cfg(或/boot/grub/grub.cfg),复制到外置存储 - 整个 /boot 目录:文件不多,但极重要
bash复制# 打包备份 /boot 内容
tar czvf /root/boot-backup-$(date +%F).tar.gz /boot/
# 备份关键的引导配置文件
cp /etc/fstab /root/fstab.bak
cp /etc/default/grub /root/grub.bak
如果机器是虚拟机,建议先打个快照。云服务器的话,在控制台做一次磁盘快照,成本很低,却能在关键时刻救你一命。这一步看起来“浪费时间”,但我在生产环境做过无数次分区操作, 只要出过一次事,你就会明白备份不是可选步骤,而是必选项。
4.2 制作启动U盘并进入Live环境
要修改正在使用的根分区,必须从外部环境启动。最常用的工具是 GParted Live,你也可以用 Ubuntu 安装盘、SystemRescueCD、CentOS 安装盘,反正只要能进入一个带图形化分区工具的 Live 环境就行。
下载 GParted Live ISO 后,用 Rufus、Ventoy 或者 dd 写入 U 盘:
bash复制# Linux 下用 dd 写入 U 盘
sudo dd if=gparted-live-xxx.iso of=/dev/sdX bs=4M status=progress
注意 /dev/sdX 要写成你的 U 盘设备路径,千万别写错盘。写完之后,从 U 盘启动,选择默认的图形界面模式,很快就能进入桌面环境。
有一点必须强调:进入 Live 环境后,先看一下当前磁盘挂载情况。df -h 看一眼 /boot 是否已经被自动挂载,如果挂载了就先卸载,否则 GParted 会提示分区正忙,无法操作。
bash复制sudo umount /boot
4.3 GParted里的关键操作步骤
GParted 的图形界面很直观,但操作顺序很重要。假设当前布局是:
text复制/dev/sda1 /boot ext4 500M
/dev/sda2 / ext4 100G
目标是给 /dev/sda1 增加 500MB。完整流程如下:
第一步:缩小 /dev/sda2 的尾部空间
选中 /dev/sda2,右键选择 Resize/Move,把“New Size”减少 500MB 或者直接在“Free space following”里填 500MB。这里只是缩小尾部,不会影响 /dev/sda2 的起始位置,所以相对安全。
第二步:移动 /dev/sda2 的位置
这一步是整个流程里最耗时、风险也最高的。执行完第一步后,空闲空间出现在 /dev/sda2 的末尾,不在 /dev/sda1 旁边。要让 /boot 用上这块空间,必须把 /dev/sda2 整体向右“顶”一段,让空闲空间出现在 /dev/sda1 和 /dev/sda2 之间。
在 GParted 里选中 /dev/sda2,再次选择 Resize/Move,在“Free space preceding”填入 500MB,软件会自动把分区起始位置向后移动。移动分区和缩分区不同,它会把整个分区的数据块往后搬,耗时可能从几分钟到几十分钟,取决于磁盘速度和数据量。这块只能耐心等,千万别中途断电。
第三步:扩展 /dev/sda1
现在空闲空间已经挪到 /dev/sda1 和 /dev/sda2 之间,也就是 /boot 的“右边”紧邻着空闲区域。选中 /dev/sda1,选择 Resize/Move,把“New Size”直接拉满到 1GB,应用后 /boot 就完成了扩展。
第四步:点击 Apply 执行所有操作
GParted 会把上面的操作排成一个队列,点 Apply 后按顺序执行。执行过程中不要做任何其他操作,也不要强制关机。执行完成后,关掉 GParted,重启系统。
4.4 重启后的引导修复与验证
重启后不一定马上就能进系统,因为分区起始位置变了,grub 的配置文件里记录的 UUID 如果没变,一般能正常起来。但保险起见,我每次都手动重新生成一次引导配置。
bash复制# 进入系统后重新生成 grub 配置
grub2-mkconfig -o /boot/grub2/grub.cfg # CentOS/RHEL 系
# 或
update-grub # Debian/Ubuntu 系
然后检查 /boot 容量:
bash复制df -hT /boot
如果显示容量已经是 1G 左右,说明扩容成功。如果 /boot 挂载失败或者进不了系统,参照下一节排查。
5. 常见问题与排查技巧实录
5.1 重启后卡在grub>或grub rescue
这是分区操作最常见的“翻车现场”。卡在 grub rescue> 通常因为 grub 找不到 /boot 所在分区,分区表变了但 grub 还记着旧的根设备。手动介入的思路是先把模块加载起来:
text复制grub rescue> set prefix=(hd0,msdos1)/boot/grub2
grub rescue> set root=(hd0,msdos1)
grub rescue> insmod normal
grub rescue> normal
进入菜单后,如果能正常引导系统,进系统后再执行一遍 grub2-install /dev/sda 和 grub2-mkconfig -o /boot/grub2/grub.cfg。如果是 UEFI 引导,grub 路径有所不同,通常是 /boot/efi/EFI/centos/grub.cfg 这种,操作逻辑类似,但 grub2-install 要加上 --target=x86_64-efi。
5.2 扩容后报UUID找不到或挂载失败
分区表变化后,文件系统的 UUID 一般不会变(除非你重建了分区),但如果你在操作过程中不小心格式化或者移动了分区边界导致文件系统损坏,就可能出现 UUID=xxx does not exist 的报错。这种时候先在 Live 环境里挂载根分区,查看 /etc/fstab:
bash复制# 在 Live 环境里查看原系统的 fstab
cat /mnt/etc/fstab
# 对比当前分区的实际 UUID
blkid
如果 UUID 对不上,用 blkid 拿到的正确 UUID 修改 /etc/fstab,再重启。修改的时候务必小心,fstab 写错可能导致系统启动进入 emergency mode,但只要你能从 Live 环境里读盘改回来,问题就不大。
5.3 提示“No space left on device”但/boot明明有空间
这种情况我遇到过不止一次,并且每次都有人被绕进去。df -h 显示 /boot 有剩余空间,但新建文件就报设备没有空间。原因多半是 inode 耗尽了,不是空间耗尽。
bash复制df -i /boot
如果 Inodes 那一列显示使用率 100%,说明分区里的小文件太多,把所有 inode 都占完了。遇到这种情况,扩容分区其实也救不了 inode,因为 inode 数量在格式化时就已经固定。只能通过清理 /boot 下的小文件,或者干脆重建一个 inode 数更多的文件系统来解决。如果非扩容不可,建议在重建 /boot 时用下面的参数来增加 inode 密度:
bash复制mkfs.ext4 -i 4096 /dev/sda1
5.4 dracut/initramfs阶段就崩了
有些系统扩容后能过 grub,但启动到一半卡住,提示 dracut: FATAL: No or empty root device,这种通常是 initramfs 里的 initramfs 设备映射信息过期,认不出新的根分区布局。解决方法是进救援模式或者 Live 环境,然后用 chroot 进入原系统,重新生成 initramfs:
bash复制# 在 Live 环境里挂载根系统和 /boot
mount /dev/sda2 /mnt
mount /dev/sda1 /mnt/boot
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
chroot /mnt
# 重新生成 initramfs
dracut -f
# 或者 Ubuntu 上用:
update-initramfs -u
重新生成后退出 chroot,重启系统,基本能解决。
6. 一些我的经验和预防建议
扩容 /boot 这件事,技术上并不神秘,核心就是一个:改分区表之前一定要想清楚顺序,操作过程中每一步都要有备份支撑。但如果让我总结这几年踩坑的经验,我更想说的是怎么从根上避免这个问题。
新装系统时,如果安装器允许,尽量把 /boot 容量分大一点。别迷信默认值,CentOS 默认 1GB 在部分场景都偏紧,我通常直接分 2GB,完全不心疼这点磁盘空间。能用 LVM 就用 LVM,把 /boot 放 LVM 里,以后扩容再也不用折腾 GParted 这种 External 工具,一条 lvextend 命令搞定,省下的时间都是真金白银。
系统跑起来之后,把内核清理配置好,installonly_limit=2 这种参数务必加上,Ubuntu 用户写个自动清理脚本。其次,日常巡检多看两眼 /boot 的使用率,别等监控报警了才开始收拾,临时抱佛脚虽然能解决,但风险明显更高。
说实话,每次处理完一个 /boot 爆满的服务器,我都会觉得这种问题要是早十分钟动手,根本不用搞得这么惊险。希望这篇能把很多人的“第一次”变得顺利一点,遇到同样的问题,打开文章照着做,比对着 grub 提示符发愁要强得多。
