如何修复 grub 启动错误:“找不到符号‘grub_calloc’

mde*_*uss 53 boot grub2

刚刚在 20.04 (Xubuntu) 上运行了最新一批更新,现在我收到了 GRUB 错误:

symbol 'grub_calloc' not found
Run Code Online (Sandbox Code Playgroud)

我进入了“grub 救援”外壳,但不知道在那里做什么可能有用。对我来说,“找不到符号”意味着 grub 包存在某种构建错误,但我真的不知道 grub 是如何工作的。我注意到此更新还包括“固件”,不确定这是否相关。我最好的选择是从 live CD 启动,看看我是否可以以某种方式将更新回滚到 grub?

编辑添加:

好的,感谢很多人!这就是我认为我现在理解的内容。

  1. 在“非 UEFI”系统上,grub 安装在两个独立的部分。第一个也是最基本的部分是在启动时启动的部分。但是对于它的大部分功能,它需要第二部分。这些部分必须对齐 - 任何部分都不需要其他部分的任何功能,而实际上并不存在。

    当这些部分没有对齐并且没有提供函数 grub_calloc 时,就会出现可见的运行时问题。我不是 100% 清楚 grub_calloc 是属于第二个、更大的部分还是第一个。我会期待第二个,但 grub 构建系统是一件相当艺术的作品,所以我不知道:)。

  2. 问题的根本原因是grub更新并没有保证部分都更新了。理想情况下,如果不这样做会导致 grub 安装失败,并且系统应该恢复到安全状态。这不会发生。

    这实际上对我来说仍然有点神秘。默认情况下,更新需要做的就是将每个部分放在当前部分所在的位置,因为显然这有效。如果安装位置/驱动器是配置驱动的,并且无法到达这些位置之一,那么不知何故,配置数据和现实之间就会出现不匹配。只要部件之间没有引入新的依赖关系,这可能不会显示为问题。

所有解决方案都涉及重新安装 grub 以确保两个部分对齐。实际上没有必要返回到以前的版本(尽管这会起作用),因为损坏的并不是 grub 运行时本身。有多种方法可以实现这一点,具体取决于您的环境,但运行引导修复实时磁盘对我有用。

为了避免将来出现这种错位,确保系统上的 grub 安装程序配置为安装到正确的设备可能很有用。

此更新解决了一些重要的错误(请参阅 Ubuntu 安全通知 4432)。如果您已恢复 grub 来解决此问题,请注意您会遇到这些问题。

小智 16

在简单的 2 分区安装中使用 Linux Mint 19.3 bios grub 设置。

GRUB2 更新后,机器在重启时崩溃并进入救援模式。

error: symbol 'grub_calloc' not found    
Run Code Online (Sandbox Code Playgroud)

为了恢复 GRUB,我启动到 Linux Mint 19.3 Live USB 记忆棒并在终端中发出以下命令:

sudo mount /dev/sda1  /mnt    
sudo grub-install --root-directory=/mnt/  /dev/sda    
Run Code Online (Sandbox Code Playgroud)

重新启动后,桌面显示得很好。

  • 考虑到不同的发行版、救援引导方法和根分区,给出的命令可以解决问题。谢谢!方法是:使用U盘、CDROM或BIOS linux启动PC,挂载root分区,将grub安装到启动设备(调整root挂载路径和启动设备) (4认同)
  • 首先,LM 在这里是题外话,其次,不清楚重新安装 grub2 应该如何解决这个问题。 (2认同)

小智 7

我和 Rick N. 2 磁盘在同一条船上,但它们不在 RAID 中。我用过这个工具https://sourceforge.net/p/boot-repair-cd/home/Home/

我从 Ubuntu 帮助页面https://help.ubuntu.com/community/Boot-Repair找到了该工具

它似乎安装了一些以前不存在的 GUI 功能(从我记事起,该系统一直是 CLI 专用的)但我再次运行,这是重要的部分。

在此感谢其他人的指导。

  • 好的,我设法使用引导修复工具来“修复”问题,这很好。但我认为它只是安装了以前版本的 GRUB,所以如果未来的更新继续推动损坏的版本,它可能不是一个“真正的”修复。不管怎样,谢谢。 (2认同)

icc*_*c97 5

这是我们在Azure Ubuntu 18.04 服务器上修复此问题的部分工作

问题似乎是升级 grub 的尝试失败。安全升级后无人值守重启会出现问题。

然后,我们从针对此问题的 Ubuntu 错误发布的评论中找到了这些说明:https : //bugs.launchpad.net/ubuntu/+source/grub2/+bug/1889509/comments/16

请注意,我对此稍作修改,下面是我在稍后对该错误的评论中提到的修改版本(https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1889509/comments/45

对于在查找此错误时最终出现在此处的 Azure 用户(同样适用于任何云,只需稍作更改),恢复步骤是:

使用 AzCli 部署恢复 VM,或者只是将受影响的 OS vm 磁盘的副本附加到救援 VM。完成后,连接到救援 VM 并:

$ sudo su -
# lsblk <-- this will identify the attached disk, usualy /dev/sdc, but can be /dev/sda or /dev/sdb
# mkdir /rescue
# mount /dev/sdc1 /rescue <-- this assumes /dev/sdc is the attached data disk
# for fs in {proc,sys,tmp,dev}; do mount -o bind /$fs /rescue/$fs; done
# cd /rescue
# chroot /rescue
# grub-install /dev/sdc <-- this assumes /dev/sdc is the attached data disk
# exit
# cd /
# for fs in {proc,sys,tmp,dev}; do umount /rescue/$fs; done
# umount /rescue
# rmdir /rescue
Run Code Online (Sandbox Code Playgroud)

现在您应该能够将修复后的磁盘换回受影响的 VM。

第一次尝试修复

我们发现以下 Azure 文档链接很有用:

好的,一步一步:

部署恢复 VM

那是什么类型的虚拟机?尝试创建一个常规的 Ubuntu 18.04 LTS VM。这就是您想要的 - 创建一个与损坏的服务器相匹配的恢复 VM

除了连接到现有磁盘外,一切正常。看起来您无法附加到磁盘,除非您首先以某种方式将其从另一台机器上移动(分离它)。

将受影响的操作系统虚拟机磁盘的副本附加到救援虚拟机。

要创建副本,您可以拍摄磁盘的只读快照,然后根据快照创建新的托管磁盘。

您需要快照的唯一磁盘是操作系统磁盘,而不是数据磁盘。

您可以创建没有数据磁盘的恢复 VM,只需自动创建的 OS 磁盘。

然后,您可以将托管磁盘操作系统快照作为数据磁盘添加到恢复 VM。

然后您可以登录恢复虚拟机并按照上述步骤操作。

所有步骤都完成了,没有错误 - 我们可以复制和粘贴确切的消息

临界线正在运行,grub-install您应该看到以下内容:

root@recoveryVM:/# grub-install /dev/sdc
Installing for i386-pc platform.
Installation finished. No error reported.
Run Code Online (Sandbox Code Playgroud)

然后注销并停止 VM。

然后您可以进入损坏的虚拟机并在虚拟机的磁盘部分下选择“交换操作系统磁盘”。

Reddit 迷你线程解释所需的挂载:https : //www.reddit.com/r/Ubuntu/comments/i0vlf0/repair_grub_boot_error_symbol_grub_calloc_not/

重复步骤

  1. 制作“损坏的”操作系统磁盘的快照(后缀_snap
  2. 从快照创建托管磁盘 -这必须与旧操作系统磁盘的等级相同,因为我们将用这个(后缀_recovery)完全替换旧操作系统磁盘- 源类型快照并使用刚刚创建的快照
  3. 将托管 OS 磁盘附加到恢复 VM(不需要停止/启动 recoveryVM)
  4. 通过 SSH 登录,运行恢复步骤,再次注销
  5. 从恢复 VM 分离托管 OS 磁盘(编辑 VM 磁盘并分离恢复 OS 磁盘)
  6. 停止“损坏的”VM(可能不需要,因为 OS 磁盘交换会停止它)
  7. 在“损坏的”虚拟机磁盘中单击“交换操作系统磁盘”并选择恢复操作系统磁盘作为替换
  8. 启动“恢复”的虚拟机
  9. 清理快照 - 但暂时保留损坏的操作系统磁盘 - 提醒一个月左右也将其删除

最后关闭恢复虚拟机并在一个月内将其删除

一些服务器的问题

我们遇到了两个服务器的修复不起作用的问题。所有命令都成功完成 - 但我们在启动 VM 时遇到相同的 grub 错误。

进一步调查显示了该/dev/sda/dev/sdb/dev/sdc在恢复VM发生了变化。我不知道为什么会这样。

这是在 sudo(但非 chroot)模式下运行时应该得到的结果lsblk(注意sda是恢复 VM 操作系统,并且sdc附加了要恢复的数据磁盘):

NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda       8:0    0   30G  0 disk
??sda1    8:1    0 29.9G  0 part /
??sda14   8:14   0    4M  0 part
??sda15   8:15   0  106M  0 part /boot/efi
sdb       8:16   0   16G  0 disk
??sdb1    8:17   0   16G  0 part /mnt
sdc       8:32   0   30G  0 disk
??sdc1    8:33   0 29.9G  0 part
??sdc14   8:46   0    4M  0 part
??sdc15   8:47   0  106M  0 part
sr0      11:0    1  628K  0 rom
Run Code Online (Sandbox Code Playgroud)


小智 1

与 linux mint 20 cinnamon 和 BIOS(而不是 EFI)grub 设置相同。

有人可以提供一些帮助吗?

编辑:我找到了问题的根本原因和解决方案。在我的例子中,根本原因是我有一个由 4 个磁盘构建的 RAID5,并且我认为,软件包升级期间的自动 grub 安装仅更新了“disk2”。由于我的 BIOS 从“disk1”启动,它有一个较旧的 grub,因此无法启动。我将 BIOS 更改为一次从每个磁盘启动(即:“disk1”、“disk2”、“disk3”、“disk4”),唯一工作的是“disk2”。

为了解决这个问题,我刚刚从“disk2”启动并执行:

sudo grub-install /dev/sda  
sudo grub-install /dev/sdc  
sudo grub-install /dev/sdd  
# ("disk2" is /dev/sdb and it was already working properly so I didn't install grub in that disk)  
sudo update-grub  
sudo reboot  
Run Code Online (Sandbox Code Playgroud)

然后重新配置我的 BIOS 以从“disk1”启动。这样,每次更新 grub 时我都会遇到类似的问题,并且会提醒 grub-install、grub-update 其余磁盘。

我希望这可以帮助处于同样情况的其他人。

  • 这不是一个完整的解决方案。因为执行上述操作,不会更新 debconf 数据库,并且下次推出 grub 更新时不会记住哪些驱动器需要安装 grub。请执行“$ sudo dpkg-reconfigure grub-pc”并指定您希望始终安装 grub 的所有驱动器,而不是手动调用 grub-install。它不仅可以解决当前启动失败的问题,还可以确保下次有软件包更新时所有 grub 都能正确更新。这样就不需要再次手动执行 grub-install 了。 (5认同)

小智 1

在这里使用 Linux Mint,同样的事情也发生在我身上。看起来像是最近的安全更新引起的,因为除了这个更新公告之外,我在 Google 上找不到其他任何内容。

通过启动到 Mint Live USB 并使用 Timeshift 恢复到更新 grub2 之前的时间点来解决。

  • 最近(10 小时前)有大量对 grub git head 的提交。如果 10 小时前的提交被作为更新推出,我会感到惊讶,但其中一个提交进行了大量更改,所有这些都相当于使用 grub_calloc 代替其他一些内存分配函数。另一个提交定义了 grub_calloc 函数并导出它们。因此,我越来越认为,此问题的根本原因是由于某种原因在某些情况下的安装无法确保正确安装 grub_calloc。 (4认同)