☰
Ubuntu磁盘空间不足导致黑屏无法启动?排查与扩容完整指南
2026/10/17 5:03:00 网站建设 项目流程

刚接手一台Ubuntu服务器,同事说“开机黑屏,系统挂了”。我第一反应不是查显卡,而是先看了一眼磁盘——果然,df -h里根分区直接100%。这个词我太熟了:Ubuntu磁盘空间不足导致的黑屏无法启动,在物理机和虚拟机上都出现过。很多朋友遇到黑屏就先怀疑驱动、怀疑内核、甚至重装系统,但其实大半情况下,问题根本不复杂,就是根分区或者/boot被塞满了,系统在启动过程中起不来关键服务,最后屏幕就黑了。

这篇文章我打算把整条处理链路完整写一遍:先从启动链路讲清楚“磁盘满为什么会导致黑屏”,再给出一套在纯命令行里紧急腾挪空间的命令组合,然后重点演示磁盘容量扩展的两种主流方式(LVM在线扩容和非LVM分区扩容),最后把扩容过程中遇到的坑和排查思路整理成一个速查表。不管是自己用的Ubuntu工作站,还是公司里的服务器,这套流程基本都能直接套用。

1. 磁盘满了为什么会让Ubuntu直接黑屏

1.1 黑屏不是显卡的锅,先看启动链路

很多人的第一反应是“图形界面坏了,重装驱动”,但我见过的绝大多数“黑屏无法启动”,其实发生在显示管理器还没拉起来之前。

Ubuntu的启动链路大概是:BIOS/UEFI → GRUB → 内核 → systemd(PID 1)→ 挂载根文件系统 → 启动各个服务单元 → 图形登录管理器(GDM/LightDM等)。任何一环依赖的资源缺失,都会让后面的环节失败。磁盘满了影响的是systemd那一层:系统在启动时要创建很多临时目录、更新系统状态、加载用户会话,这些操作都需要写入/var、/tmp、用户家目录等路径。当根分区剩余空间是0字节的时候,systemd的一些关键服务就会因为“No space left on device”而启动失败,尤其是一些带After=约束的服务,一旦起不来,后续服务全部阻塞,最终就停在一个黑屏或者卡死状态。

我处理过一个客户现场,现象就是开机后显示器黑屏,键盘灯能亮,但没有任何登录界面。我远程进去看了一眼journalctl -p err -b,发现systemd-tmpfiles-setup.service、rsyslog.service都因为写入失败挂了。把根分区腾出几个G后,重启一切正常。

提示:黑屏和卡死的优先级永远先看磁盘和内存,再看驱动。开机时先试试能否进入纯命令行(下文会讲),如果能进命令行,90%是磁盘满或者服务异常,而非硬件故障。

1.2 先分清:是根分区爆满,还是/boot爆满

这是很多人会混淆的地方。磁盘空间不足引发启动失败,常见原因有两个:

  • 根分区/爆满:影响上面说的systemd服务、临时文件写入、用户会话,导致黑屏、卡循环登录。
  • /boot分区爆满:内核更新时无法写入新内核与initramfs,系统重启后可能直接卡在GRUB或者停在加载内核阶段,表现可能是“紫屏/黑屏/花屏”,也可能直接GRUB rescue。

所以排查第一步,不是急着扩容,而是先确认到底哪个分区满了。我用过这样一组命令:

df -h df -i lsblk -f

df -h看空间,df -i看inode——注意,有少数场景是inode满了但空间还够,表现同样是“No space left on device”,但本质上不一样。lsblk -f则能看到分区表结构和文件系统类型,为后续扩容规划做准备。

1.3 确认问题的三个入口:GRUB菜单、recovery mode、multi-user.target

系统已经黑屏了,怎么进到命令行?三个办法,按顺序尝试:

入口一:GRUB菜单修改内核启动参数

开机时按住Shift(BIOS启动的机器)或者狂按Esc(UEFI模式),进入GRUB界面。选中默认条目,按e进入编辑模式,找到以linux开头的那一行,在末尾加上:

systemd.unit=multi-user.target

然后按Ctrl+X启动。这个参数会强制systemd直接进入多用户纯命令行模式,跳过图形界面和管理器,只要内核能起来,基本就能拿到一个shell。

入口二:恢复模式(Recovery Mode)

GRUB菜单里一般有“Advanced options for Ubuntu”这一项,进去能看到带(recovery mode)的内核条目。选它进入后,会有一个恢复菜单,选择root选项就能拿到root shell。

注意:恢复模式下根文件系统通常是只读挂载的,要执行写入操作,先执行mount -o remount,rw /。我第一次用的时候忘了这步,journalctl --vacuum-size直接报只读文件系统错误,排查了半天才反应过来。

入口三:用安装U盘/ Live USB修复

如果GRUB都进不去,或者选了内核直接panic,那就用Ubuntu安装U盘启动,选择“Try Ubuntu”,进入Live环境后挂载原系统的根分区来清理或备份数据。后面扩容操作中,非LVM分区的部分也经常需要Live环境配合。

拿到shell之后,第一件事就是看一眼最盘占用和文件系统状态:

df -h systemctl default

如果磁盘确实满了,就按下一节的命令紧急腾空间。

2. 紧急自救:在命令行里先挤出几十GB活跃空间

2.1 用journald清理日志立竿见影

拿到命令行后的第一步,永远是先看系统的日志占了多少空间。systemd-journald这个组件会持续记录内核日志、服务日志、用户日志,配置不当的时候能把/var/log/journal吃到几十个GB。我之前在一台机器上见过/var/log/journal占满了整个根分区的80%。

优先执行这样两条:

journalctl --disk-usage journalctl --vacuum-size=200M

--vacuum-size=200M的意思是保留最近日志,让journal总占用控制在200MB以内。执行完立刻释放了大量空间。如果journald占得不多,再看其他:

du -xh --max-depth=1 / 2>/dev/null | sort -rh | head -20

这条命令用-x限制只看根分区内文件,--max-depth=1看一层目录,按大小倒序排。我最常用的场景就是看一下/var、/usr、/home、/tmp里到底谁最大。

2.2 apt与软件包缓存清理

Ubuntu的apt缓存和残留包是另一个隐藏磁盘杀手。执行:

apt clean apt autoremove -y

apt clean是清空/var/cache/apt/archives下所有下载的deb包,这些包装完就没用了,但经常会占几个G。apt autoremove会移除那些“自动安装、现在没被任何包依赖”的软件包,注意看输出,别把需要的包误删了(不过裸机层面,比较少见)。

还有个容易被忽略的:

rm -rf /var/lib/apt/lists/*

这是apt的索引和元数据缓存,占几个G很正常,清掉后下次apt update会重新拉,完全不影响系统。

2.3 清理旧内核与Docker残留

内核更新是/boot爆满的主要原因,但也会把根分区的/usr/lib/modules占满。先看当前运行的内核版本:

uname -a dpkg --list | grep linux-image

保留当前内核版本和最近一两个版本,其余通过apt purge删除,例如:

apt purge linux-image-5.x.x-x-generic -y

删除后记得执行update-grub,让GRUB菜单同步清理。

如果机器装了Docker,别忘了:

docker system prune -a

这条会清理悬空镜像、停止的容器、未使用的网络和构建缓存,释放空间非常可观。但也提示一下,-a会把所有没有被正在运行容器引用的镜像都清掉,如果后续需要重新拉取镜像,要考虑网络和时间成本。不需要急着恢复生产就用这条,如果是生产环境建议只执行docker system prune -f先清悬空资源。

实操心得:紧急清理阶段的目标不是“优化体验”,而是“让系统能启动”。所以先看journal,再看apt缓存,再看旧内核,这三板斧下去基本能腾出5~15GB空间,足够支撑重启和后续扩容操作了。

3. 真正根治:磁盘容量扩展的完整实操

腾出空间只是缓兵之计,根源是磁盘容量规划不合理。要彻底解决,必须把容量扩大。我按三种常见磁盘布局分别给出操作路径。

3.1 动手前必须搞清楚的三种布局

先说清楚,扩容方式和分区布局强相关。先跑:

lsblk -f sudo pvs sudo vgs sudo lvs
  • 普通分区(非LVM):根分区是/dev/sda1、/dev/nvme0n1p2这种直接分区,没有卷管理层。扩容时要么用growpart+resize2fs,要么借助Live U盘和GParted图形化处理。
  • LVM逻辑卷:Ubuntu默认安装(使用整个磁盘时)经常采用LVM布局,根分区实际落在逻辑卷上,比如/dev/mapper/ubuntu--vg-ubuntu--lv。LVM的好处是可以在卷组里有多余的物理空间时,一条命令在线扩展,不重启。
  • 虚拟机磁盘:物理磁盘本身的容量是虚拟机软件(如VMware、VirtualBox、KVM)分配的,系统里看到的分区只是虚拟磁盘上的一部分。先在宿主机侧把虚拟磁盘大小扩大,再在系统内部扩展分区/文件系统。

我把三种情况对比如下:

布局类型判断方法核心扩容手段是否必须停机
普通分区lsblk里根分区直接从sda等物理盘分出growpart+resize2fs;或GParted优先建议维护窗口
LVMlvs能看到逻辑卷lvextend+resize2fs可在线,通常不中断服务
虚拟机lsblk时磁盘总容量小于宿主分配容量宿主侧扩虚拟磁盘,再系统内扩分区视情况

注意:实际操作前永远先备份重要数据。扩容分区有风险,如果断电或者中途出错,最坏情况会导致数据不可读,所以我个人习惯是在操作前至少tar备份关键目录,或者做一次快照(虚拟机里特别方便)。

3.2 LVM在线扩展:lvextend + resize2fs

LVM场景的扩容是我最喜欢的,因为可以在系统运行状态下完成,不需要进Live环境,也不用停机维护窗口。

假设我现在的布局是:

ubuntu-vg ├─ ubuntu-lv 挂载于 /

第一步:查看卷组剩余空间。

sudo pvs sudo vgs sudo lvs

vgs输出的VFree字段就是卷组里还没分配的可用物理空间。如果VFree是0,说明物理磁盘或者PV(物理卷)本身没预留空间,这时需要先扩展PV:

  • 如果是虚拟机磁盘太小,先在宿主机扩容虚拟磁盘(见3.4),然后系统内执行echo 1 > /sys/class/scsi_device/0:0:0:0/device/rescan重新扫描SCSI设备(路径里设备编号以实际为准,我常用ls /sys/class/scsi_device/查看)。
  • 如果是物理机新增了一块硬盘,比如新增/dev/sdb,则这样操作:
sudo pvcreate /dev/sdb sudo vgextend ubuntu-vg /dev/sdb

如果卷组本来就有空闲空间,直接跳到第二步:

第二步:扩展逻辑卷。

sudo lvextend -L +20G /dev/ubuntu-vg/ubuntu-lv

这条命令把逻辑卷扩大20GB。也可以直接指定目标大小,比如-L 100G表示扩展到100GB。注意-L +20G是“增加20G”,-L 120G是“扩容到120G”,两者含义完全不同,我见过有人用错导致逻辑卷大小和自己预期不一致。

第三步:扩展文件系统。

不同文件系统类型扩展命令不同,先判断:

lsblk -f /dev/ubuntu-vg/ubuntu-lv
  • 如果是ext4:
sudo resize2fs /dev/ubuntu-vg/ubuntu-lv
  • 如果是xfs(比如某些Rocky/Alma,但Ubuntu一般默认ext4):
sudo xfs_growfs /

只要卷组里有空闲空间,这三步完成后df -h立刻就能看到根分区变大了,全程无需重启。

注意:现在新版的lvextend在默认情况下已经会自动扩展文件系统(相当于替你执行了resize2fs)。我习惯用lvextend -r -L +20G,其中-r参数表示resize文件系统,一步到位。但为了兼容旧版本系统,我还是建议拆开执行,逻辑更清晰,出错也好定位。

3.3 非LVM场景:分区表扩展与resize2fs

非LVM场景稍微麻烦一点,因为分区表需要修改。方法取决于根分区在磁盘上的位置。

情况A:根分区前面有未分配空间,或者磁盘本身容量变大了(把根分区扩展到磁盘末尾之后)

这种最理想,用growpart扩展分区表条目,再用resize2fs扩展文件系统。假设根分区是/dev/sda2:

sudo growpart /dev/sda 2 sudo resize2fs /dev/sda2

growpart实际上是在不影响数据的前提下,修改分区表让该分区的结束位置向后移动,把磁盘末尾的空闲空间“吸收”进来。执行前同样建议确认磁盘容量已经扩大(物理机换大硬盘,或虚拟机扩容虚拟磁盘)。

情况B:根分区后面跟着其它分区,无法向后扩展

这种情况根分区被挡在中间,没法直接向后扩。我的方案是用GParted Live或者Ubuntu Live USB启动,图形化把前面的数据分区缩小、腾出空间、再把根分区扩大。步骤大致为:

  1. 用启动盘进入Live环境。
  2. 如果根分区所在磁盘有交换分区且刚好挡在中间,先swapoff并删除/缩小交换分区,优先把空闲空间给根分区腾出来(必要时之后再重建swapfile)。
  3. 在GParted里缩小根分区后面的那个分区,腾出空闲空间。
  4. 把根分区向后面扩展到目标大小。
  5. 应用操作后退出Live环境,正常启动系统。

这个过程我一般不建议在运行中的系统上直接操作挂载中的根分区,GParted会拒绝修改已挂载分区,Live环境里根分区未挂载,安全性高一些。

3.4 虚拟机场景:先在宿主侧扩容,再让系统识别

很多“Ubuntu黑屏无法启动”其实是虚拟机里的系统,比如VMware、VirtualBox、Proxmox/KVM环境。这类环境扩容链路多了一个宿主侧操作,很多人卡就卡在“宿主里已经把磁盘调大了,但系统里看不到”。

以VMware为例,先关机或在线执行磁盘扩展,把虚拟磁盘从50GB扩到100GB(不同虚拟化平台的操作入口不同,但思路一致)。随后进入Ubuntu命令行:

lsblk

这时你会发现磁盘(比如/dev/sda)总容量变成了100GB,但分区(/dev/sda2)还是原来的大小。此时只需要做两件事:

  1. 让系统重新读取磁盘的新容量(虚拟机里通常重启后自然生效,但有些平台支持在线扫描):
echo 1 > /sys/class/scsi_device/0:0:0:0/device/rescan

不同虚拟化平台识别新容量的方式略有差异,最简单可靠的方式其实是重启系统,然后再执行lsblk确认容量。

  1. 如果是LVM,先扩展PV:
sudo pvresize /dev/sda2

然后再回到3.2的第二步执行lvextend+resize2fs。

如果是非LVM分区,执行3.3的growpart+resize2fs即可。

实操心得:虚拟机扩容的时候,强烈建议在宿主侧先做快照。虽然扩展分区本身一般不损坏数据,但虚拟机磁盘扩容后一旦分区表操作中途断电,没有快照就只能靠备份恢复,太被动了。

4. 扩容过程和扩容后最容易踩的坑

4.1 黑屏问题的其他诱因:swap、内存溢出、驱动冲突排查

先说明一下,磁盘扩容解决的是“磁盘满”这一大类问题。但黑屏无法启动这里其实不止一个诱因,我自己排障时遇到过好几种情况,如果磁盘腾出来之后重启依然黑屏,需要继续排查以下三点:

swap太小或者没配置:内存不够时,系统会尝试用交换分区,如果交换分区在扩容过程中被删了或者太小,图形界面启动时内存耗尽,也会表现为黑屏。可以先检查:

free -h swapon --show

如果swap为0且内存吃紧,建议创建swapfile:

sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile

然后在/etc/fstab里加一行/swapfile none swap sw 0 0。

显示管理器或者图形驱动问题:如果磁盘空间充足、内存充足、swap正常,但黑屏依旧,那就可能是GPU驱动和当前内核版本不配套。在命令行下可以这样重启显示管理器:

sudo systemctl restart gdm3

或者查日志:

journalctl -b -g "(Failed|ERROR|Traceback)" | tail -50

如果是NVIDIA驱动的问题,日志里一般会有模块加载失败的报错,这时才需要去处理驱动。

4.2 扩容后引导失败的排查思路

扩容后最可怕的不是容量不够,而是重启后系统直接进不了GRUB。以下我根据实际经验整理了排查优先级:

分区表被改动导致UUID变化

如果你用fdisk/parted手动删除重建分区,而不是用growpart,那么分区的UUID可能发生变化,而/etc/fstab里记录的还是旧UUID,系统挂载根分区时就会失败。这就是为什么我强烈推荐growpart和lvextend——它们不改UUID。

如果不小心改了UUID,启动时会停在一个类似(initramfs)的提示符。此时可以在initramfs里用blkid查看新UUID,然后在/etc/fstab里修改,或者用update-initramfs -u重新生成initramfs。这些操作在Live环境中做会更顺手。

GRUB引导安装位置不对

扩容时如果动过磁盘首部区域(比如从磁盘头部腾空间),可能导致GRUB引导代码丢失,表现为开机直接黑屏或者提示“找不到引导程序”。处理方式是进Live环境后挂载根分区,执行:

sudo mount /dev/sda2 /mnt sudo mount /dev/sda1 /mnt/boot # 如果有独立boot分区 sudo grub-install /dev/sda sudo update-grub

然后重启。我遇到过一次这种情况,就是图省事直接删了分区重建,结果引导丢,还好用Live U盘救回来了。

误删了内核或者initramfs

清理旧内核时apt purge可能会“手滑”把当前内核也删了。遇到这种情况,进Live环境挂载根分区后:

sudo chroot /mnt apt install linux-image-generic update-grub exit

然后重启。

4.3 常见问题速查表

我把排障过程中碰到的典型问题整理成一个速查表,方便现场快速对照:

现象可能原因排查/修复命令
开机黑屏,Ctrl+Alt+F2无响应磁盘满,systemd服务卡死df -h,清除journal和apt缓存
进GRUB选择内核后黑屏/boot分区满或内核损坏dpkg --list | grep linux-image,清理旧内核
开机提示(initramfs)fstab中UUID失效或根分区挂载失败blkid查看UUID,修改/etc/fstab
扩容后分区未变大卷组没有剩余空间,或者没执行resize2fsvgs看VFree,resize2fs确认执行
扩容后显示容量变大但写入仍报满inode耗尽df -i确认,删除大量小文件
GRUB提示no such device引导丢失Live环境执行grub-install和update-grub

最后再补充一个我个人的习惯:扩容完成之后,别急着直接投入高负载使用,先重启一次验证完全正常,再让业务跑起来。Linux扩容这件事,绝大多数情况下都不难,但每一步都涉及分区表、文件系统这些核心结构,谨慎一点永远不会吃亏。希望这篇记录能帮到你,你机器的空间规划,也值得在这次处理完之后好好重新盘一盘。

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

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

立即咨询