
1. 为什么会这样先搞清楚Windows和Linux的引导关系1.1 一个真实的重装现场先说说我自己遭遇过的情况。有一台实验室的备用电脑我用U盘装好了Ubuntu和Windows双系统平时默认进Ubuntu写代码Windows偶尔用来跑一些Windows-only的工业软件。本来用得挺顺直到有一天Windows系统出了点问题我想都没想就用系统U盘重装了一遍Windows。重装过程一切正常结果装完重启屏幕上直接弹出一行字大意是找不到操作系统连Windows也进不去。折腾了半天才发现问题根本不是Windows装坏了而是Ubuntu的引导程序GRUB被Windows重装过程覆盖掉了。后来跟几个同事聊发现这个坑几乎每个人在玩双系统时都踩过一遍。只要你先装了Linux后装或重装Windows大概率会让Linux从启动菜单里消失。这跟Windows好不好用、Ubuntu版本新不新都没关系是两者引导机制的设计差异导致的。所以这篇文章就是把我当时完整的排查过程和几种修复方案整理出来。不光是告诉你照着敲几条命令就行还会把每个步骤背后的原理讲清楚——知道为什么这么做遇到Boot-Repair失效、盘符错乱这些特殊情况你才有办法自己判断。1.2 Legacy BIOS模式下Windows如何吃掉MBR要理解引导丢失得先知道电脑开机时发生了什么。传统的Legacy BIOS引导模式也就是很多人说的BIOS启动、MBR启动主板会去读硬盘第一扇区——也就是主引导记录MBR。MBR一共512字节前446字节是引导代码后面是分区表。引导代码做什么呢它负责把操作系统的引导程序找出来然后把控制权交给它。Linux用的GRUB引导程序在Legacy模式下就是把自己的引导代码写进MBR这446字节里。GRUB可以认识ext4文件系统所以它能够直接读取/boot目录下的配置文件弹出你熟悉的那紫底白字的启动菜单。问题就出在Windows身上。Windows重装时会把MBR整个抹掉重写完全用自己的引导代码替换掉GRUB的引导代码。Windows的引导代码只有一个功能——寻找并启动Windows的bootmgr也就是Windows Boot Manager。它压根不支持Linux的文件系统也不会去辨认硬盘上哪个分区是Ubuntu。于是MBR里GRUB的入口没了自然开机就再也看不到那个双系统菜单。这里有个关键细节这个状态下你的Ubuntu系统和所有数据其实都还在硬盘上一个字节都没丢。丢的只是引导入口就像一栋房子门牌被摘了房子本身还好好的。1.3 UEFI模式下ESP分区里的启动项为何被删现在新电脑大部分已经是UEFI引导了情况稍有不同但结果是一样的。UEFI模式下硬盘上会有一个专门的EFI系统分区ESP分区Fat32格式小几百MB。主板固件开机时会去扫描这个分区里的EFI文件然后把它们作为启动项列出来。Windows重装时会在ESP分区里建一个EFI/Microsoft/Boot/bootmgfw.efi文件并把这个文件设为固件的第一启动项。而Ubuntu安装时会把GRUB的EFI程序写到ESP分区的EFI/ubuntu/目录下文件名通常是shimx64.efi因为Ubuntu启用安全启动或grubx64.efi。正常情况下UEFI固件里会有两个启动项一个是Ubuntu指向GRUB一个是Windows Boot Manager指向Windows的bootmgfw.efi。关键问题来了重装Windows的时候安装程序可能做两件事。第一它会清理EFI分区中其他系统的启动文件尤其是当你选择了删除所有分区再安装这种干净安装方式时第二它会直接修改UEFI固件里的BootOrder变量把自己设为第一位。如果固件里之前指向GRUB的启动项被删掉了那开机就直接进Windows。更狠的情况是GRUB入口和Windows入口都在但顺序变了不仔细看BIOS菜单根本不知道Ubuntu还活着。所以不管你是老电脑还是新电脑只要后装WindowsGRUB就面临着被覆盖或者被删除的命运。这就是文章标题里那个问题的根源。2. 动手之前先诊断你的电脑是哪种引导模式2.1 在Windows里确认磁盘分区表类型修复引导之前必须搞清楚自己电脑到底是Legacy BIOS还是UEFI模式。同一个问题两种模式下的修复方法完全不同。搞错方向可能折腾一晚上还是进不去系统。如果你现在还能进Windows引导没彻底丢只是GRUB没了最快的判断方式是在Windows里打开命令提示符管理员权限输入diskpart list disk看输出结果磁盘那一行的Gpt列如果带星号说明磁盘是GPT分区表使用的是UEFI引导如果不带星号说明是MBR分区表对应Legacy BIOS引导。另外一个更直观的方法在Windows里打开系统信息看BIOS模式这一项如果显示UEFI那就是UEFI模式显示传统那大概率是Legacy。但如果你现在连Windows都进不去引导全丢开机黑屏那就稍微麻烦点得靠BIOS设置界面来判断。重启电脑开机时按Del或F2进入固件设置找Boot Mode或Boot Option这一类选项看看是UEFI还是Legacy一般是二选一的关系。有些电脑默认只支持UEFI那就不用纠结了。2.2 从Live USB查看分区结构确认Ubuntu的系统分区无论如何修复引导都需要一个UbuntuLiveUSB。如果你手头没有找一台正常的电脑用Rufus或自带的“启动盘创建器”做一个Ubuntu安装U盘就行。制作过程不多说只要是Ubuntu的ISO镜像用UEFI方式写入U盘基本都能在不同电脑上通用。从U盘启动后选择试用Ubuntu而不是安装Ubuntu进入Live桌面环境。打开终端运行下面的命令看磁盘结构sudo fdisk -l这个命令会列出所有磁盘和分区。你需要找两样东西一个是Ubuntu的根分区挂载点写着/、大小跟你安装Ubuntu时给的容量对得上另一个是EFI系统分区类型显示EFI System大小100-500MB不等在UEFI模式下才有。如果当时安装Ubuntu时没有单独分/boot那/boot就是根分区里的一个目录不用额外处理。再确认一下分区里的数据还在不在防止重装Windows时误删了Linux分区。挂载根分区比如sudo mount /dev/nvme0n1p6 /mnt ls /mnt可以看到bin、etc、home、usr这些熟悉的Linux目录说明Ubuntu安然无恙。看到这个心里就踏实了接下来不管怎么折腾都不会丢数据。2.3 快速判断到底该走哪条修复路线经过上面的诊断你现在应该能回答这几个问题问题判断依据对应修复方案分区表是GPT还是MBRfdisk -l 输出里的Disklabel typeGPT走UEFI路线MBR走Legacy路线有没有ESP分区fdisk -l输出里有没有EFI System有就挂载它没有就说明是LegacyUbunut根分区数据还在吗mount之后有没有bin、etc等目录在就放心修不在先找分区恢复/boot是独立分区吗有没有大小几百MB的Linux分区独立的话修复时要单独挂载它这样一个表列下来方向就清晰了。接下来分别说两种模式的修复动作你可以直接跳到符合自己情况的那一节。3. 最快的修复路线用Boot-Repair一键恢复引导3.1 准备Boot-Repair的环境如果你不想跟命令行较劲那我强烈建议先试Boot-Repair这个工具。它的原理很简单扫描整个磁盘找出所有操作系统的安装位置然后帮你重新安装GRUB并让GRUB接管启动。整个过程基本是图形化点按钮非常省事。在Live Ubuntu桌面里打开终端输入以下命令安装sudo apt update sudo add-apt-repository ppa:yannubuntu/boot-repair sudo apt install boot-repair -y安装好之后运行boot-repair它会自动检测你的磁盘信息然后给你两个大按钮——推荐修复和高级选项。3.2 执行修复并处理可靠性问题先点推荐修复。Boot-Repair会做一堆事情挂载你的Ubuntu根分区、重新安装GRUB、更新grub.cfg配置文件、如果检测到Windows也会把它加进启动菜单。过程大概几分钟输出一堆日志最后它会弹出一个URL类似paste.ubuntu.com/xxxx这个是修复日志的链接。这里有个坑我必须提醒一下Boot-Repair修复过程中需要联网。它的某些步骤会重新下载grub相关软件包断网的情况下很可能报错比如grub-install失败或者update-grub的os-prober找不到Windows。所以请确认你的Live系统已经连上网络再执行修复。修复完成之后提示信息一般会说请重启试试。这时候把U盘拔掉正常重启如果看到GRUB菜单蹦出来里面同时有Ubuntu和Windows两个选项那恭喜你问题解决了。3.3 Boot-Repair修不好时说明什么然而事情往往没那么顺利。我遇到过几次Boot-Repair明明提示成功重启后却依然直接进Windows或者干脆黑屏。这种情况并不代表工具没用而是说明系统里有它搞不定的因素。最常见的两种情况如果是UEFI模式Boot-Repair可能识别不到ESP分区或者挂载出错导致GRUB写入了错误的EFI路径固件压根找不到它。如果Linux是逻辑卷LVM或者整个盘做了加密Boot-Repair默认方案可能没能力正确处理GRUB装不上。对于第一种情况解决办法是改用高级选项并手动指定ESP挂载点。在高级选项里找到GRUB location那一栏选择你的ESP分区并设置挂载点一般写/boot/efi。对于第二种情况就得老老实实走手动chroot修复路线这也是下文的重头戏。老话说得好工具解决不了的事情动手敲命令一定能解决。接下来就是我认为最有价值的一部分——手动修复的完整过程。4. 手工修复GRUBchroot方案的完整步骤4.1 chroot的原理把系统借壳还魂手动修复GRUB的核心是chroot。打个比方你现在用Live USB启动这个系统是临时借来的而硬盘上的Ubuntu是个完整的操作系统但无法自己启动。chroot命令可以让你临时把这个Live系统的根目录切换到你硬盘上那个Ubuntu的根目录里就好像借壳还魂——用Live USB的内核去操作硬盘上那个真实的Ubuntu环境。一旦chroot进去你运行的命令比如grub-install、update-grub就都以为自己在硬盘上那个Ubuntu系统里运行这样生成的配置文件、安装的引导代码就会写到正确的位置。整个过程比较长分成六个环节来讲每一步的命令我都会给出并标注每条命令的作用。4.2 挂载根分区和系统目录进入Live桌面打开终端。先用fdisk -l确认分区情况我以我的实际环境举例假设Ubuntu根分区是/dev/nvme0n1p6ESP分区是/dev/nvme0n1p1。如果你用的是SATA硬盘盘符会变成/dev/sda类似的形式。第一步把根分区挂载到/mntsudo mount /dev/nvme0n1p6 /mnt这一步如果你是UEFI模式并且有独立的ESP分区还需要把它挂载到/mnt/boot/efisudo mkdir -p /mnt/boot/efi sudo mount /dev/nvme0n1p1 /mnt/boot/efi如果你的Ubuntu当时把/boot单独分出来那还要先挂载/boot分区再挂ESP。顺序不能乱先挂根再挂/boot最后挂/boot/efisudo mount /dev/nvme0n1p5 /mnt/boot sudo mount /dev/nvme0n1p1 /mnt/boot/efi接下来挂载虚拟文件系统。chroot进去之后Live系统的内核需要看到这些动态的目录才能真正干活sudo mount --bind /dev /mnt/dev sudo mount --bind /proc /mnt/proc sudo mount --bind /sys /mnt/sys sudo mount --bind /run /mnt/run这里特别说一下/run有些人只挂载前三个结果chroot之后update-grub偶尔会出现奇怪的警告。把/run也绑上去很多莫名问题都能避免。4.3 复制DNS配置并chroot进入chroot环境之前还有一个小动作推荐做一下拷贝Live系统的DNS配置到/mnt/etc/resolv.conf。为什么会用到它呢因为后面执行update-grub时如果检测到os-prober相关的包缺失可能会尝试联网更新元数据没有DNS就会失败。sudo cp -a /etc/resolv.conf /mnt/etc/resolv.conf然后进入chroot环境sudo chroot /mnt敲完之后你会发现命令行提示符变了比如变成rootubuntu:/#这说明你已经在硬盘上那个Ubuntu系统内部了后面所有命令都会作用在那个系统上。4.4 安装GRUBUEFI和Legacy两条路线现在进入关键环节。根据你之前的诊断结果选其中一种执行。Legacy BIOS模式下把GRUB安装到硬盘的MBR位置。注意目标不是某个分区而是整块磁盘比如/dev/sdagrub-install /dev/sda执行成功后会输出Installation finished. No error reported。这代表GRUB引导代码已经成功写进MBR。UEFI模式下安装GRUB到ESP分区。在chroot环境里ESP分区已经挂载在/boot/efi所以命令是grub-install --targetx86_64-efi --efi-directory/boot/efi --bootloader-idubuntu关于--bootloader-id它决定EFI启动菜单里显示的名称。用ubuntu也可以用grub或者你想起的任何名字都行关键是后面重启的时候你要能找到这个条目。装完GRUB本体之后生成启动菜单配置文件update-grub这个命令会扫描系统的所有分区查找已安装的操作系统并写入/boot/grub/grub.cfg。输出里如果能找到类似Found Windows Boot Manager on /dev/nvme0n1p1这样的信息说明Windows也成功加入了GRUB菜单。这里有个常见问题update-grub提示没找到Windows。原因是新版Ubuntu默认禁用了os-proberWindows的探测脚本。处理方式很简单echo GRUB_DISABLE_OS_PROBERfalse /etc/default/grub update-grub重新跑一遍Windows就出现了。4.5 修复UEFI启动项并调整顺序Legacy模式下grub-install和update-grub做完就能重启。但UEFI模式还有最后一步确认UEFI固件里有没有生成对应的启动项。如果不进BIOS设置你可以在chroot里用efibootmgr直接查看和添加。先查看当前启动项efibootmgr输出里会看到BootOrder、Boot0000、Boot0001这些条目。如果里面没有Ubuntu相关的条目手动添加一条efibootmgr --create --disk /dev/nvme0n1 --part 1 --label Ubuntu --loader \EFI\ubuntu\shimx64.efi注意--part后面的数字对应ESP分区号我这里是1--loader是ESP分区内的EFI文件路径反斜杠的路径格式不能写错。如果Ubuntu条目已经有了但排在Windows后面用-o参数调整顺序efibootmgr -o 0000,0001把代表Ubuntu的编号放在最前面Windows编号放后面。重启后就能看到GRUB菜单了。做完这些退出chroot环境输入exit然后重启exit sudo umount -R /mnt sudo reboot如果一切顺利熟悉的GRUB菜单应该回来了。5. 修复之后的新麻烦Windows时间不对、默认启动项不对5.1 UTC时钟引发的Windows时间错乱很多人在修复完引导、能正常进入双系统之后又冒出另一个经典问题Windows里面显示的时间和Ubuntu里面相差8小时。这不是什么随机故障背后是两套系统对硬件时钟RTC的认知不同。Linux默认把硬件时间当作UTC协调世界时来理解然后根据时区设置换算成本地时间显示。Windows则默认把硬件时间直接当作本地时间。如果北京时间是早上8点Windows认为硬件时间也是8点而Ubuntu认为硬件时间是UTC的8点换算成北京时间就是16点。两个系统交替使用同一块硬件时钟就差了8小时。如果你觉得改Linux这边更顺手可以在Ubuntu终端里执行timedatectl set-local-rtc 1这会让Linux也把硬件时间当成本地时间跟Windows保持一致。执行完可以再执行timedatectl确认输出里没有提示RTC in local TZ的问题。改完以后重启一次Windows时间显示就正常了。我个人比较推荐这个方案因为Windows对时间同步的依赖更强改Linux一处就能同时兼顾。5.2 GRUB默认启动项指向了Windows另一个小问题是GRUB菜单虽然回来了但每次开机默认进入Windows倒计时结束自动选择Windows。这是因为GRUB的default配置默认是0而菜单里第一项可能就是Windows项。特别是当os-prober把Windows放在Ubuntu之前时就会这样。想要默认进Ubuntu编辑GRUB配置文件sudo nano /etc/default/grub看GRUB_DEFAULT这一行默认是0代表第一个菜单项。如果Ubuntu项是第N项从0开始数就把数字改成N。更新完配置后sudo update-grub这样重启后默认就回到Ubuntu。还有一种更直观的办法在GRUB菜单界面按e临时编辑启动项把quiet splash后面加上自己的参数但那只对当前启动有效配置持久化还是得改文件。6. 吃一堑长一智以后怎么规划双系统引导6.1 把引导入口和系统盘分离这次修好之后我重新审视了自己的装机规划。当初图省事把Ubuntu和Windows装在了一块硬盘的两个分区里结果重装Windows时MRB被覆盖连带两个系统的引导一起失效。后来我在另一台机器上尝试了一种更省心的方案——准备两块独立的硬盘一块装Windows另一块装Ubuntu。引导文件也在各自的硬盘上互不干扰重装任何一个系统都不会影响另一个。如果你只有一块硬盘想尽量避免重装Windows导致的引导覆盖可以试试把GRUB装到U盘或者独立的启动分区。做法是安装Ubuntu时选择手动分区让/boot挂载到单独的ext4分区不用太大1GB足够然后grub-install时把引导代码指向这个分区所在的磁盘。这样Windows重装只会覆盖自己磁盘的MBR或ESPGRUB保存在独立区域仍然能启动。缺点是开机时需要手动选择从哪个设备启动不过BIOS里设置一下启动顺序也就解决了。6.2 平时备份EFI分区的关键目录说到备份很多人装了Linux好几年都没备份过EFI分区直到出问题才后悔。EFI分区整个也就几百MB备份非常快。在Ubuntu正常运行时执行sudo cp -a /boot/efi/EFI /home/用户名/efi_backup_日期下次引导丢了进Live USB把备份拷回ESP分区的EFI目录再配合grub-install的--efi-directory参数十分钟就能恢复。这比在网上找各种教程从头排查要快太多。6.3 重装Windows前留好后路最后提醒一句如果你确定了短期内还要重装Windows请在重装之前手动把Ubuntu修复工具准备妥当。具体来说把Ubuntu Live USB先做好记下自己Ubuntu根分区在哪个磁盘哪个分区编号比如/dev/nvme0n1p6有条件的把上面说的EFI目录备份一份存到U盘或移动硬盘。这三样东西都准备好了重装Windows就是有惊无险的小事一桩。重装Windows时也选择一下——如果不想让Windows覆盖整个磁盘的引导记录可以在安装程序选择安装位置时确保只选择你想要放Windows的那个分区而不是直接选删除全部现有分区。Windows安装程序在写入引导时有了现有引导文件会增加覆盖面积其中也包括Linux的那部分入口。我在后来的实践里养成了一个习惯所有涉及系统安装的机器都在手边备一个Live USB上面同时放了Ubuntu镜像和Boot-Repair工具。双系统引导丢了这件事听起来吓人其实只要摸清了原理、知道数据还在修复就是一条命令和几条命令的区别。希望这篇文章能把这条一条命令的路讲明白让你下次遇上引导丢失的时候心里有底手上不慌。