no bootable device。今天这篇来聊一下为什么会发生这种事,以及用 Live USB 一步步把引导修回来。
在开始修之前,必须先理解"引导"是怎么工作的。不然修了还是不明白,下次坏了还是茫然。
现在的电脑几乎都是 UEFI 了,但有必要了解一下历史对比:
💡 提示1: 怎么判断电脑是 UEFI 还是 BIOS? Windows 里按 Win+R 输入
msinfo32,看"BIOS 模式"那行,显示 UEFI 就是 UEFI,显示 Legacy或传统 就是 BIOS。 Linux 里看/sys/firmware/efi目录是否存在:ls /sys/firmware/efi能列出内容说明是 UEFI,反之就是BIOS。💡 提示2: 现在的电脑几乎都是UEFI+GPT了,本文也以此为主。
上电
↓
UEFI 固件初始化硬件
↓
读取 EFI 分区(ESP)中的启动项列表(nvram/bootorder)
↓
按顺序尝试启动项
↓
找到 GRUB → 加载 grub.cfg → 显示启动菜单
↓
用户选择 Linux 或 Windows
↓
进入对应系统
关键点:UEFI 的启动项列表存在主板的 NVRAM 里,EFI 分区里存的是各个系统的引导加载程序文件(.efi 文件)。
EFI 分区(ESP)通常是 100MB~500MB 的 FAT32 分区,挂载在 /boot/efi。里面结构大概是:
/boot/efi/EFI/
├── Microsoft/
│ └── Boot/
│ └── bootmgfw.efi ← Windows 引导器
├── ubuntu/
│ ├── grubx64.efi ← GRUB 主文件
│ ├── shimx64.efi ← Secure Boot 垫片
│ └── grub.cfg ← GRUB 配置(简单版,指向真正的 grub.cfg,它只包含几行加载根分区配置文件的内容)
├── Boot/
│ └── bootx64.efi ← 默认启动项(UEFI fallback)
└── ...(其他系统)
Windows的快速启动功能(Fast Startup)在关机时并不会真正关机,它会把内核会话写入休眠文件。这可能导致双系统之间切换时,GRUB无法正确检测到Windows分区。如果GRUB能出现,但选Windows后蓝屏/重启,试试在Windows里关闭‘快速启动’。
知道了结构,再来看"被干掉"的各种场景:
这是最常见的原因。
Windows 安装程序在安装时会:
EFI/Boot/bootx64.efi 替换为 Windows 引导器结果:GRUB 的文件还在 EFI 分区,但 NVRAM 里的启动顺序被 Windows 改了,电脑开机直接跳过 GRUB 进 Windows。但GRUB文件还在,所以改BIOS启动顺序就能回来。
Windows 大版本升级走的是重装流程,和上面一样——会重置启动顺序。
EFI/Boot/bootx64.efi 是 UEFI 的"默认启动项",很多 Linux 发行版为了在 Windows 已有的情况下还能引导,会把 GRUB 也复制到这个路径。但 Windows 更新有时会把这个文件替换成 Windows 引导器,把 GRUB 顶掉。
NVRAM 存储的启动项列表有时依赖 CMOS 电池维持,如果 CMOS 掉电或 BIOS 被重置,主板可能会回退到默认启动项(EFI/Boot/bootx64.efi),如果这个文件被 Windows 占了,就进不了 GRUB。
误操作,或者"清理垃圾"时把 EFI 分区的 ubuntu/ 目录删了。
调整分区大小、移动分区、更换硬盘后,GRUB 配置文件里记录的 UUID 或设备号可能对不上新的分区布局。
在动手修之前,先判断一下问题属于哪种:
no bootable device / boot device not found | |
grub> ),没有菜单 | |
Shell>) | .efi 文件 |
如果确认 GRUB 文件还在(因为之前装双系统是成功的),只是开机直接进 Windows,最简单的修法是在 BIOS/UEFI 设置里改启动顺序。
开机时按快捷键(各品牌不同):
如果经操作过一次,下次遇到问题可以直接照着这个表操作。
进 BIOS 后找"Boot"或"引导"选项卡,可以移动 ubuntu(或 GRUB)、 Windows Boot Manager 前后顺序,保存退出。
💡 提示: 如果在启动顺序里根本找不到 ubuntu 或 GRUB 的选项,说明 NVRAM 里的启动项被彻底清掉了,需要用下面的方法从 Live USB 修复。
Live USB 就是装 Linux 时用的那个 U 盘,也可以重新用 balenaEtcher 制作一个 Ubuntu 的 Live 镜像。用 Live USB 启动,不进安装,而是进"试用 Ubuntu",然后 chroot 到安装好的系统里重装 GRUB。整个过程大约15-20分钟,请耐心操作,不要中途断电。
# 列出所有分区
lsblk -f
# 或者更详细的信息
sudo fdisk -l
lsblk -f 输出示例:
NAME FSTYPE LABEL UUID MOUNTPOINTS
sda
├─sda1 vfat XXXX-XXXX /boot/efi ← EFI 分区
├─sda2 ext4 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ← Linux 根分区
└─sda3 ntfs Windows ← Windows 分区
nvme0n1
├─nvme0n1p1 vfat XXXX-XXXX ← EFI 分区(NVMe硬盘)
└─nvme0n1p2 ext4 xxxxxxxx-... ← Linux 根分区
需要记下:
/,通常是 ext4 格式):比如 /dev/sda2 或 /dev/nvme0n1p2/dev/sda1 或 /dev/nvme0n1p1# 把 Linux 根分区挂到 /mnt(把 /dev/sda2 换成根分区)
sudo mount /dev/sda2 /mnt
如果有单独的 /boot 分区(安装时分了的话),也要挂上:
# 查看是否有 /boot 分区
lsblk -f | grep boot
# 如果有,挂上(把 /dev/sda3 换成 boot 分区)
sudo mount /dev/sda3 /mnt/boot
# 把 EFI 分区挂到 /mnt/boot/efi(把 /dev/sda1 换成 EFI 分区)
sudo mount /dev/sda1 /mnt/boot/efi
# 这几个目录是 chroot 环境正常工作所必须的
sudo mount --bind /dev /mnt/dev
sudo mount --bind /dev/pts /mnt/dev/pts
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
sudo mount --bind /run /mnt/run
# 如果需要用 efibootmgr 修改启动顺序,再挂一个:
sudo mount --bind /sys/firmware/efi/efivars /mnt/sys/firmware/efi/efivars
# 切换根目录到安装的 Linux
sudochroot /mnt
💡 提示: chroot 之后,终端提示符会变化成‘root@ubuntu:/#’之类,现在"相当于"在安装的 Linux 系统里操作,而不是 Live USB 的临时系统。
UEFI 系统(绝大多数现代电脑):
# 重新安装 GRUB 到 EFI 分区
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu
# 重新生成 GRUB 配置文件(扫描所有系统,生成启动菜单)
update-grub
BIOS/MBR 系统(老电脑):
# 把 /dev/sda 换成硬盘名(不加分区号)
grub-install /dev/sda
update-grub
⚠️ 注意:
grub-install的目标是硬盘(如/dev/sda),不是分区(不要写/dev/sda1)。UEFI 系统用--target=x86_64-efi参数。
# 退出 chroot
exit
# 卸载挂载点(可选,重启会自动卸载)
sudo umount -R /mnt
# 拔出 U 盘,重启
sudo reboot
重启后应该能看到 GRUB 启动菜单,里面有 Ubuntu 和 Windows 两个选项。
有时候 update-grub 跑完,重启后 GRUB 菜单里只有 Linux,没有 Windows 选项。
# 在 chroot 环境里检查 os-prober 是否安装
dpkg -l | grep os-prober
# 如果没有,安装它
apt install os-prober
# 确认 os-prober 没被禁用
cat /etc/default/grub | grep GRUB_DISABLE_OS_PROBER
# 如果输出 GRUB_DISABLE_OS_PROBER=true,需要改成 false 或者注释掉
nano /etc/default/grub
# 找到那行,改成:
# GRUB_DISABLE_OS_PROBER=false
# 手动运行 os-prober 测试
os-prober
# 应该能输出 Windows 的 EFI 路径
# 重新生成 GRUB 配置
update-grub
💡 提示: Ubuntu 21.10 以后,
/etc/default/grub默认加了GRUB_DISABLE_OS_PROBER=true,这是 Ubuntu 默认的(安全考虑),但会导致双系统用户的 Windows 选项消失。改成 false 就好了。
grub-install: error: cannot find EFI directoryEFI 分区没挂上,或者挂错了路径:
# 退出 chroot,重新检查 EFI 分区挂载
exit
ls /mnt/boot/efi # 应该能看到 EFI 目录
# 如果是空的,重新挂载 EFI 分区
sudo mount /dev/sda1 /mnt/boot/efi
# 再重新 chroot 进去操作
grub-install: error: failed to get canonical path of /cow这个报错通常意味着EFI分区没有正确挂载到 /boot/efi,先检查挂载再重试:
sudo mount --bind /run /mnt/run
# 重新 chroot 后再试
cannot find a device for /boot/efiEFI 分区没挂或识别失败:
# 查看 EFI 分区是否正确挂载
mount | grep efi
# 确认输出类似:/dev/sda1 on /mnt/boot/efi type vfat
NVRAM 里的启动顺序没变,需要手动改:
# 在 chroot 环境里查看当前启动顺序
efibootmgr
# 输出示例:
# BootCurrent: 0001
# BootOrder: 0001,0000
# Boot0000 Windows Boot Manager
# Boot0001 ubuntu
# 把 ubuntu(Boot0001)设为第一启动项
efibootmgr -o 0001,0000
# 或者:
efibootmgr --bootorder 0001,0000
lsblk -f | ||
sudo mount /dev/sdXN /mnt | ||
sudo mount /dev/sdXN /mnt/boot/efi | ||
sudo mount --bind /dev /mnt/dev | ||
sudo chroot /mnt | ||
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu | ||
update-grub | ||
exitsudo reboot |
如果经操作过一次,下次遇到问题可以直接照着这个表操作。
grub-install → update-grub | |
os-prober,把 GRUB_DISABLE_OS_PROBER 的值改成 false |
📌 下一篇预告: 《Linux/Windows 双系统引导修复(下)——boot-repair 与手动修复进阶》,介绍 boot-repair 一键工具、更复杂的分区情况处理,以及修完之后怎么防止 Windows 更新再次干掉 GRUB。