ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Ubuntu升级卡在grub-efi-amd64-signed?三步修复UEFI引导器报错

Ubuntu升级卡在grub-efi-amd64-signed?三步修复UEFI引导器报错 这个问题我在给一台跑了好几年的旧服务器做版本升级时正好撞上过。系统卡在grub-efi-amd64-signed的 configure 阶段进退两难网上翻到的方案大多是互相抄细节又对不上。后来折腾出几条可靠路径这里把来龙去脉一次性说清楚。1. 这个报错的真面目为什么升级会卡在“目录已存在”这种小事情上先明确一件事grub-efi-amd64-signed是 Ubuntu 在 UEFI 启动模式下负责安装引导程序的核心包它负责把经过微软签名认证的shimx64.efi和grubx64.efi放到 ESPEFI 系统分区通常是/boot/efi的特定目录里。报错信息看起来像是权限问题或者目录空间不足但实际上绝大多数情况下是目录残留冲突。打个比方你搬进新家衣柜抽屉里前任房客留下的旧袜子还没清走新衣服就塞不进去。这个包安装时会在/boot/efi/EFI/ubuntu/下写入文件如果目录结构有残留或者父目录被某些升级脚本处理得状态不一致它就直接抛错。我在实际排障中还遇到过一个容易误导人的变体日志里提示gzip: stdout: No space left on device这是 ESP 分区写满了。这个分区默认只有 100MB 左右内核更新、旧引导文件堆积都会挤占它。这类问题本质上也是目录/空间问题处理优先级要先于纯粹的目录残留。另有一个规律比较隐蔽这个报错经常出现在从 20.04 往 22.04、或 22.04 往 24.04 的大版本升级release-upgrade过程中而不是日常的apt upgrade。原因是大版本升级会重构引导器而日常升级只是更新内核。所以一旦你在升级时看到这个报错先别慌系统并不是坏了只是升级过程被打断了修复思路反而比较明确。1.1 先自查你遇到的是哪种错误表现为了不盲目操作建议先看下当前状态。在你卡住的界面通常是 dpkg configure 失败的红底界面选择“返回”或直接开另一个终端窗口执行df -h /boot/efi ls -la /boot/efi/EFI/ubuntu/第一段命令看 ESP 分区占用情况第二段看目录里有没有异常残留比如.dpkg-old、.dpkg-dist、shimx64.efi.old这类备份文件或者多出来了带日期后缀的目录。正常情况应该是这样的结构total 16 drwx------ 3 root root 4096 ... . drwx------ 5 root root 4096 ... .. -rwx------ 1 root root 156K ... grub.cfg -rwx------ 1 root root 6.9M ... grubx64.efi -rwx------ 1 root root 1.9M ... shimx64.efi如果你看到了mmx64.efi、fallback.efi甚至陌生子目录基本就是上次安装残留或第三方工具写进去的。这时候中断操作对照下面的修复路径来。2. 最稳妥的 3 步修复路径从半成品状态拉回可用系统对于卡在 dpkg configure 阶段、尚未完全中断的情况以下 3 步修复法成功率最高而且不会对系统造成额外破坏。2.1 第 1 步让 dpkg 状态回稳在卡住的界面或新开的终端里先执行dpkg --configure -a这一步是让所有处于“半配置”状态的包重新走一遍安装脚本。如果它执行到一半依然在grub-efi-amd64-signed报错退出就执行apt update apt install --fix-broken--fix-broken会让 apt 尝试修复依赖关系并重新配置坏掉的包。很多网上教程只写到这一步但对目录残留问题这步往往不能根治。如果执行后依然报同样的错进入第 2 步。2.2 第 2 步处理 EFI 目录中的残留这里要区分两种场景。第一种是目录里有.old后缀的旧文件直接挪走而不是删除方便回滚mkdir -p /root/efi_backup mv /boot/efi/EFI/ubuntu/grubx64.efi.old /root/efi_backup/ 2/dev/null mv /boot/efi/EFI/ubuntu/shimx64.efi.old /root/efi_backup/ 2/dev/null mv /boot/efi/EFI/ubuntu/*.bak /root/efi_backup/ 2/dev/null第二种是目录权限或文件系统状态异常导致安装脚本无法正确写入。把目录权限恢复到标准状态mount -o remount,rw /boot/efi rm -rf /boot/efi/EFI/ubuntu等等这里我要强调一个分寸问题。随意删整个/boot/efi/EFI/ubuntu目录风险较大如果当前系统是唯一的引导入口删除后一旦断电或其他原因导致引导器重建失败机器可能起不来。更稳妥的做法是把它改名为备份目录而不是直接删除mv /boot/efi/EFI/ubuntu /boot/efi/EFI/ubuntu.bak.$(date %Y%m%d)这样 dpkg 脚本运行时会认为目标目录不存在从而以全新状态创建并写入文件。如果修复后发现引导正常删除这个备份目录即可万一异常随时可以改回原名恢复。2.3 第 3 步重新配置引导器并更新 NVRAM 启动项目录清理后重新配置包然后写入新的引导文件dpkg --configure -a apt install -f这里如果提示grub-efi-amd64-signed包处于“被阻止”或“未安装”状态可以先显式重装触发它的 postinst 脚本重新执行apt install --reinstall grub-efi-amd64-signed grub-efi-amd64 shim-signed最后更新 GRUB 配置并确保 UEFI 启动项正确update-grub grub-install我在多次修复中发现一个很关键的细节grub-install后面不要跟设备名比如/dev/sda让它自动探测即可。如果手动指定了错误的磁盘比如写到了软raid成员盘或 NVMe 的某个分区上反而可能搞乱 NVRAM 启动项。让它自动处理在绝大多数单系统场景会更稳。到这里标准 3 步法就完成了。重启前建议先执行一次efibootmgr -v确认能看到ubuntu开头的启动项并且路径指向\EFI\ubuntu\shimx64.efi。如果你看到的还是旧路径或者有多个重复启动项可以使用efibootmgr调整顺序但这属于后续优化不影响系统修复与否。3. 如果 3 步法失败排查链条与重装系统的体面方案上面的方法对大多数半路卡死的情况有效但还有一类更棘手的情况你的系统是从旧版本一路滚上来的EFI 分区里已经有乱七八糟的历史残留或者 grub 包本身版本冲突导致dpkg --configure -a死循环。我遇到过最极端的案例是ESP 分区里居然有 5 个shimx64.efi的不同副本分别属于 grub-efi-ia32、grub-efi-amd64 和 shim-signed 不同版本。这种情况强行按目录清理思路处理容易越清越乱。3.1 先确认系统还能不能引导在放弃之前先确认当前系统是否还能正常重启。如果你是通过 SSH 远程操作的或者是在虚拟机里操作而宿主机不太方便接回显这里建议先创建一个“安全网”grub-mkconfig -o /boot/grub/grub.cfg这个操作不涉及 UEFI 引导器只是重新生成 GRUB 菜单。它能在断电或误删后确保 GRUB 还能进菜单界面而不至于直接黑屏。做完后再尝试dpkg --configure -a如果依然失败进入下一条更硬核的路径。3.2 直接绕过软件包安装脚本走“手工安装引导器”方案这个思路的核心是既然 dpkg 脚本跑不过去那就先让引导器处于可用状态然后反查 dpkg 数据库把包标记为已安装最后让系统认为“一切正常”。手工安装引导器的命令如下mount -o remount,rw /boot/efi grub-install --targetx86_64-efi --efi-directory/boot/efi --bootloader-idubuntu --recheck这里几个参数的用意--targetx86_64-efi明确指定 64 位 EFI 引导器避免默认目标可能干出奇怪的事。--efi-directory/boot/efi告诉 grub-install ESP 挂载点在哪。--bootloader-idubuntu决定写入 NVRAM 的启动项名称和目录名即/boot/efi/EFI/ubuntu/。--recheck让 grub-install 检查磁盘设备映射关系在设备变动后会重新生成 device.map。执行成功后手动宣告 dpkg 数据库中的包已安装dpkg --configure -a如果它又尝试重新配置 grub 包并且又报错跳过它echo grub-efi-amd64-signed hold | dpkg --set-selections把这个包保持住不参与升级绕开问题。系统整体还是可以用的引导也正常只是后续升级需要留意。这个方法属于“剑走偏锋”不推荐给怕麻烦的人但对于确认了 ESP 分区有写入权限却依然反复失败的场景是最省时间的方案。3.3 真正的“体面方案”备份根文件系统后重装如果你没有太多旧数据负担或者机器上已经没啥关键服务了重新安装可能是性价比最高的方案。很多人听到“重装”就皱眉但如果做对备份实际痛苦程度很低。重装前需要备份的内容按优先级排列/etc/下的所有配置文件特别注意/etc/netplan、/etc/ssl、/etc/ssh。/home/下的用户目录。/var/www、/srv、/opt等自定义软件/数据目录。通过dpkg --get-selections /tmp/pkglist.txt导出的已安装软件包列表。/boot/efi/EFI/ubuntu/下如果还有有效的.efi文件最好也拷出来留存。重装时选择“清除整个磁盘并重新安装”然后在恢复阶段用apt install从 pkglist 批量恢复软件。这种方式比在坏掉的系统上继续“外科手术”要节省至少半天时间。而且重装后 UEFI 启动项会被全新写入不会再出现残留文件导致的各种诡异问题。我的实际体验是如果你的机器上主要跑的是 Docker 容器、Nginx、数据库之类的常见服务重装完全不会影响业务连续性只要把数据盘单独挂载好甚至能比修复原系统更快恢复到可用状态。4. 预防胜于修复余下注意事项与长期维护心得关于这个报错值得记住的不只是“怎么修”还有“为什么会这样”。每次遇到此类问题我都会提醒自己做好几件小事避免未来重蹈覆辙。4.1 系统升级前检查 ESP 分区空间这一条最容易被忽视。grub-efi-amd64-signed报错里有一大类其实是 ESP 分区空间不足导致的。检查方式df -h /boot/efi如果使用率超过 80%建议在升级前清理旧内核镜像和旧引导备份。清理旧内核的安全做法是apt autoremove --purge这个命令会移除不用的旧内核但要注意它只移除 Debian/Ubuntu 内核包管理的旧版本。如果/boot/efi下还有手动放置的.efi文件你需要手动确认是否可以删除。一个常见技巧是查看/boot/efi/EFI/下的子目录凡是你自己不认识、且不在ubuntu、Boot、Microsoft三件套内的大概率是某些分发版或工具写入的可以考虑备份到别的分区再删。如果空间实在紧张还可以扩大 ESP 分区但那个操作比较复杂需要在 Live USB 环境下用 parted/GParted 调整分区表且有变砖风险。我个人建议不如重装或者先把不常用的启动项清理掉。4.2 谨防手动修改/boot/efi/EFI/ubuntu/grub.cfg这个文件在 ESP 分区里负责 GRUB 的菜单显示不是主配置文件。手动改这个文件的后果是下次update-grub会直接覆盖它你做的“优化”全部白费。如果你想调整启动参数正确入口是/etc/default/grub改完执行update-grub。我见过有人为了让 GRUB 菜单显示分辨率更舒服直接改 ESP 里的 grub.cfg结果升级后那个文件被覆盖分辨率又回去了还以为是升级导致的问题白白排查了半天。这类“改了个寂寞”的操作在这个目录结构下的确更容易踩中。4.3 升级前启用系统快照或做可回滚备份针对大版本升级最稳妥的保障是升级前用 LVM 快照或第三方工具如 Timeshift做一次系统快照。LVM 快照对流数据库型业务压力较大但对普通个人服务器来说几分钟就能完成。快照目录独立于 ESP 分区即使升级把根分区搞挂了也能从快照恢复。这里多说一句如果机器是 KVM/QEMU 虚拟机直接在宿主机层面做磁盘快照或备份再升级是最省心的路径。如果都不方便退而求其次至少把/etc打包一份放到其他分区tar -czf /tmp/etc_$(date %Y%m%d).tar.gz /etc这个备份在系统坏到只剩命令行救盘时能让你快速恢复关键网络配置。4.4 理解grub-efi-amd64-signed与shim-signed的耦合关系很多人只知道前者报错不知道它和shim-signed是强绑定关系。在 Secure Boot 开启的机器上UEFI 固件首先加载的是微软签名的shimx64.efi再由 shim 加载 GRUB。所以如果shim-signed升级失败或版本不匹配grub-efi-amd64-signed的 postinst 脚本也会报错。遇到这种情况安装时把这两个包一起重装通常能解决问题apt install --reinstall shim-signed grub-efi-amd64-signed grub-efi-amd64重装后注意确认/boot/efi/EFI/ubuntu/shimx64.efi和grubx64.efi的时间戳是最新的。如果时间戳没变说明安装脚本根本没执行到写入那一步问题还是出在 dpkg 状态或目录上。4.5 一个常被忽略的状态Secure Boot 与grub-efi-ia32部分机器尤其是某些品牌机的 UEFI 固件虽然是 64 位但出于兼容性原因引导文件却是 32 位版本。如果安装时错误地装了grub-efi-ia32后续升级时会不断出现奇怪冲突日志里一会儿报grub-efi-ia32的一堆问题一会儿又报grub-efi-amd64-signed的问题。检查当前究竟用的是哪个版本dpkg -l | grep grub-efi如果看到输出中存在grub-efi-ia32且你的机器 CPU 架构是 x86_64建议手动卸载它并安装 amd64 版本apt purge grub-efi-ia32 apt install --reinstall grub-efi-amd64-signed这里有个细节有些固件确实只认 32 位引导器这属于特殊情况。在动手卸载前先查主板说明书或者用efibootmgr -v看看当前 UEFI 启动项指向的路径如果是EFI/BOOT/BOOTIA32.EFI那你反而需要保留 ia32。总之确认一下再动手。5. 事后复盘一次完整修复案例的流程串联理论说得再多不如看一次完整案例的流程串联。假设我现在接到一台无法通过 SSH 远程执行apt upgrade的服务器这是最常见的现场完整修复过程如下通过物理终端或 IPMI 进入系统看到 dpkg 中断界面。先不选任何选项另开 tty 登录。执行df -h /boot/efi。若空间告急先清出至少 20MB 空间删旧内核等。执行ls -la /boot/efi/EFI/ubuntu/看到grubx64.efi.old这类文件先移到备份目录。执行dpkg --configure -a。这次它可能依然报错原因是 dpkg 状态数据库里 grub 相关包标记异常。此时执行rm -f /var/lib/dpkg/updates/*清掉 dpkg 更新锁然后再次dpkg --configure -a。如果包还是报错执行apt install --fix-broken。它会尝试下载缺失的依赖并重新配置。如果卡在配置脚本上按住 n 跳过 postinst 脚本在手动模式下可以这样或者直接mv /boot/efi/EFI/ubuntu /boot/efi/EFI/ubuntu.bak后再次配置。配置通过后执行update-grub和grub-install确保引导器实际写入。执行efibootmgr -v确认启动项正确必要情况下用efibootmgr -o调整启动顺序。重启验证能进系统后执行apt update apt full-upgrade让系统把补丁补齐。这里面第 4 步被人提得很少。/var/lib/dpkg/updates/*目录下的 update 事务残留有时候也会导致 dpkg 卡在奇怪状态。删除它的风险极低因为里面只是事务日志不是包数据本身。这招在很多 dpkg 卡死的场景都能见效值得记住。另外要特别提一下不要在修复过程中同时开多个终端执行 apt/dpkg 命令。这个看似理所当然的常识在多人协作维护的机器上经常被打破一旦两个 dpkg 进程同时操作数据库轻则锁冲突重则状态错乱后面排查的成本指数级上升。6. 我的长期观察这个报错背后其实是升级习惯的问题修得多了之后我发现grub-efi-amd64-signed报错高发本质上反映的是很多人对大版本升级的敬畏不够。Ubuntu 的 LTS 版本支持期很长很多服务器从 18.04 一路升上来中间跨越了两次 bootloader 架构重构一次是传统 BIOS 转 UEFI一次是 shim 签名机制升级老旧的 ESP 分区结构和新的安装脚本逻辑自然会产生摩擦。如果你做好以下三件事遭遇这个报错的概率会大幅下降每半年做一次apt update apt full-upgrade而不是憋大招直接跨版本升级。频繁的小升级会让 grub 相关包的迁移路径提前暴露和解决而不是攒到跨版本时一次性爆发。了解机器是 Legacy BIOS 还是 UEFI 引导。两类引导方式下 grub 包的行为完全不同grub-pc是传统 BIOS 版grub-efi-amd64-signed是 UEFI 版。搞混了会死得很惨。不要随意删除/boot/efi里的文件。很多人在清理磁盘空间时误删了 EFI 目录下的关键文件结果下一次升级时包管理器发现文件缺失直接崩溃。关于“要不要禁用 Secure Boot 来一劳永逸”的问题我个人的建议是尽量别动。Secure Boot 是系统安全防线的重要组成部分为了省事而关闭它未来跑一些安全审计工具或应对合规要求时会非常被动。而且这个报错和 Secure Boot 本身没关系关不关都解决不了实际问题。写到这基本已经把grub-efi-amd64-signed报错的所有关键链路捋完了。如果你手头正遇到这个问题建议从第 2 章的 3 步法开始大概率能解决问题如果不行再看第 3 章的深度方案。祝你一次通过不用重装。
返回列表