How to restore ArchLinux boot entries

From 清冽之泉
Jump to navigation Jump to search

Fx 问题

到底是启动项丢失,还是别的问题导致没有启动项?变量 x 不同,函数 F 不同。

当我遇到开机没有启动项,又没有任何报错时,我最明智的猜测只能是“启动项丢失”这个问题了。

后来问 ChatGPT,还有一些问题可能也有启动项丢失的表象:

  1. grubx64.efi 或 grub.cfg 被误删
  2. bios 里关闭了 UEFI 或启动了 legacy
  3. CMOS 电池没电了
  4. 硬盘坏了

如果 efibootmgr -v 里没有 Boot#### 指向 /EFI/GRUB/grub.efi,那就是主板忘记 EFI 启动项了。

修改字号

终端的字号都是能瞎眼的,改大字号很有必要。

cd /usr/share/kbd/consolefonts # 该文件夹有几十种字体,带字号。随便找个后几位大字号的就行
setfont ter-132n...

格式化 ESP

# 进 Live CD 操作,不建议在真机里开机操作
# 先备份
umount /dev/sdb1 2>/dev/null || : # 卸载可能的挂载点
mkdir /mnt1
mount /dev/sdb1 /mnt1
mkdir ~/boot-backup
cp -a /mnt1/* ~/boot-backup/
umount /mnt1

# 再格式化
lsblk -f /dev/sdb1 # 确认分区
mkfs.fat -F32 /dev/sdb1

挂载 ESP

ESP 指 EFI system partition。挂载系统启动分区。对我来说是:

  • /dev/sdb2 = /。它是 vfat 格式
  • /dev/sdb1 = /boot。它是 btrfs 格式

切记,以上两种格式,挂载方式不同,因为这个小坑我浪费了至少三小时。

mount -o subvol=@ /dev/sdb2 /mnt # 这一步中的 @ 极其重要,它是 btrfs 格式对 / 的设定,具体原因我不知道,总之它相当于传统意义上的 /
mkdir -p /mnt/boot
mount /dev/sdb1 /mnt/boot

挂载辅助

# 注意,以下文件夹不需要手动创建
mount -t proc /proc /mnt/proc 
mount -t sysfs /sys /mnt/sys
mount --rbind /dev /mnt/dev
mount --rbind /run /mnt/run

安装 grub

arch-chroot /mnt # 这样就进入了真实的系统,对硬盘的操作将真实存在。注意 arch-chroot 后界面角色的 root@archiso 是灰的。
cat /etc/fstab # 查看曾经的挂载
pacman -S linux linux-firmware   # 确保 /boot 下有 vmlinuz-linux 和 initramfs.img

一般挂载情况里得有类似的:

/dev/sdb2 / btrfs subvol=@,defaults 0 0
/dev/sdb1 /boot vfat defaults,iocharset=utf8 0 2
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
grub-mkconfig -o /boot/grub/grub.cfg
efibootmgr -v # 应该能看到 GRUB 项
exit
cd /
umount -lR /mnt
reboot

可选

pacstrap /mnt grub linux 应该也能修复损坏过的 /boot。未测试。

方案二

重植 ESP

  1. 挂载 /
  2. 挂载 ESP
  3. 重装内核文件 pacman -S linux linux-firmware # 确保 /boot 下有 vmlinuz-linux 和 initramfs.img
# systemboot 用这个:
bootctl --path=/boot install

/boot/loader/loader.conf:
default  arch
timeout  3

新建 /boot/loader/entries/arch.conf:
title   Arch Linux
linux   /vmlinuz-linux
initrd  /initramfs-linux.img
options root=UUID=$(blkid -s UUID -o value /dev/sdb2) rw
 blkid  root 分区的 UUID 填进去。
# grub 用这个:
pacman -S grub efibootmgr
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=arch
grub-mkconfig -o /boot/grub/grub.cfg