Linux: grub

起因

由于未知原因( 1、我猜测是升级了内核,且内核成为 grub 默认启动项; 2、也有可能是我删除了/lib/modules/6.8.0-48-generic 这个目录),导致Ubuntu 22.04启动失败,报错:Failed to start load kernel modules。

这让我有点慌,毕竟重装系统对我来说不难,但是系统内的软件安装和数据都是非常繁琐的,不到万不得已,肯定不会做这样的事,那么接下来只能查看原因,并寻求其他解决方法。

解决

首先,我通过物理按键强制关机,接着启动计算机,发现出现了grub菜单。

1
2
3
4
*Ubuntu
Advanced options for Ubuntu
Memory test (memtest86+)
Memory test (memtest86+, serial console 115200)

默认的ubuntu是启动失败的,所以选择 Advanced options for Ubuntu 进入子菜单,显示了多个内核选项:

1
2
3
4
*Ubuntu, with Linux 6.8.0-48-generic
Ubuntu, with Linux 6.8.0-48-generic (recovery mode)
Ubuntu, with Linux 6.8.0-47-generic
Ubuntu, with Linux 6.8.0-47-generic (recovery mode)

其实,默认启动的Ubuntu内核就是Linux 6.8.0-48-generic,但是失败了。所以我选择了Ubuntu, with Linux 6.8.0-47-generic ,然后就正常启动了。

以上就是解决过程,但是没有原理性的东西。为了进一步对于计算机开机启动流程的理解,还是要接着研究。

grub 菜单

grub是什么?

GNU GRUB 是一个多引导启动 加载程序。它源自 GRUB(GRand Unified Bootloader),最初由 Erich Stefan Boleyn 设计和实现。引导加载程序(Bootloader)有很多种,现如今在各种Linux发行版上基本都使用 grub2 作为引导加载程序。

正常进入计算机后,查看安装了多个linux image文件:

1
2
3
4
5
6
7
8
9
$ dpkg --get-selections | grep linux-image
linux-image-6.5.0-18-generic deinstall
linux-image-6.5.0-45-generic deinstall
linux-image-6.8.0-40-generic deinstall
linux-image-6.8.0-45-generic deinstall
linux-image-6.8.0-47-generic install
linux-image-6.8.0-48-generic install
linux-image-generic-hwe-22.04 install

接着查看linux-image的位置:

1
2
3
4
5
6
7
8
9
10
11
$ dpkg -L linux-image-6.8.0-47-generic
/.
/boot
/boot/vmlinuz-6.8.0-47-generic
/usr
/usr/share
/usr/share/doc
/usr/share/doc/linux-image-6.8.0-47-generic
/usr/share/doc/linux-image-6.8.0-47-generic/changelog.Debian.gz
/usr/share/doc/linux-image-6.8.0-47-generic/copyright

可以确认 /boot/vmlinuz-6.8.0-47-generic 就是内核文件的位置,当然 /boot 目录下还有其他内核文件,查看一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$/usr/share/doc# ll /boot
total 187836
drwxr-xr-x 5 root root 4096 11月 1 06:59 ./
drwxr-xr-x 21 root root 4096 9月 13 10:40 ../
-rw-r--r-- 1 root root 287058 10月 2 22:39 config-6.8.0-47-generic
-rw-r--r-- 1 root root 287024 10月 7 17:56 config-6.8.0-48-generic
drwx------ 3 root root 4096 1月 1 1970 efi/
drwxr-xr-x 5 root root 4096 11月 1 20:13 grub/
lrwxrwxrwx 1 root root 27 11月 1 06:58 initrd.img -> initrd.img-6.8.0-48-generic
-rw-r--r-- 1 root root 72002483 10月 21 09:59 initrd.img-6.8.0-47-generic
-rw-r--r-- 1 root root 72011182 11月 1 06:58 initrd.img-6.8.0-48-generic
lrwxrwxrwx 1 root root 27 11月 1 06:58 initrd.img.old -> initrd.img-6.8.0-47-generic
drwx------ 2 root root 16384 8月 8 09:53 lost+found/
-rw-r--r-- 1 root root 182800 2月 7 2022 memtest86+.bin
-rw-r--r-- 1 root root 184476 2月 7 2022 memtest86+.elf
-rw-r--r-- 1 root root 184980 2月 7 2022 memtest86+_multiboot.bin
-rw------- 1 root root 8657806 10月 2 22:39 System.map-6.8.0-47-generic
-rw------- 1 root root 8659561 10月 7 17:56 System.map-6.8.0-48-generic
lrwxrwxrwx 1 root root 24 11月 1 06:58 vmlinuz -> vmlinuz-6.8.0-48-generic
-rw------- 1 root root 14911880 10月 2 22:43 vmlinuz-6.8.0-47-generic
-rw------- 1 root root 14915976 10月 7 17:58 vmlinuz-6.8.0-48-generic
lrwxrwxrwx 1 root root 24 11月 1 06:58 vmlinuz.old -> vmlinuz-6.8.0-47-generic

从上面 /boot 目录下的信息来看,这不就是 grub 菜单里面的东西嘛。那么就下来只要在 grub.conf 找到菜单排列就好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# 省略...
menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b' {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root 0691b564-31ef-421c-9b8e-c7e498f0a651
linux /vmlinuz-6.8.0-48-generic root=UUID=78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b ro quiet splash $vt_handoff
initrd /initrd.img-6.8.0-48-generic
}
submenu 'Advanced options for Ubuntu' $menuentry_id_option 'gnulinux-advanced-78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b' {
menuentry 'Ubuntu, with Linux 6.8.0-48-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-6.8.0-48-generic-advanced-78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b' {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root 0691b564-31ef-421c-9b8e-c7e498f0a651
echo 'Loading Linux 6.8.0-48-generic ...'
linux /vmlinuz-6.8.0-48-generic root=UUID=78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b ro quiet splash $vt_handoff
echo 'Loading initial ramdisk ...'
initrd /initrd.img-6.8.0-48-generic
}
menuentry 'Ubuntu, with Linux 6.8.0-48-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-6.8.0-48-generic-recovery-78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b' {
recordfail
load_video
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root 0691b564-31ef-421c-9b8e-c7e498f0a651
echo 'Loading Linux 6.8.0-48-generic ...'
linux /vmlinuz-6.8.0-48-generic root=UUID=78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b ro recovery nomodeset dis_ucode_ldr
echo 'Loading initial ramdisk ...'
initrd /initrd.img-6.8.0-48-generic
}
menuentry 'Ubuntu, with Linux 6.8.0-47-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-6.8.0-47-generic-advanced-78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b' {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root 0691b564-31ef-421c-9b8e-c7e498f0a651
echo 'Loading Linux 6.8.0-47-generic ...'
linux /vmlinuz-6.8.0-47-generic root=UUID=78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b ro quiet splash $vt_handoff
echo 'Loading initial ramdisk ...'
initrd /initrd.img-6.8.0-47-generic
}
menuentry 'Ubuntu, with Linux 6.8.0-47-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-6.8.0-47-generic-recovery-78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b' {
recordfail
load_video
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root 0691b564-31ef-421c-9b8e-c7e498f0a651
echo 'Loading Linux 6.8.0-47-generic ...'
linux /vmlinuz-6.8.0-47-generic root=UUID=78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b ro recovery nomodeset dis_ucode_ldr
echo 'Loading initial ramdisk ...'
initrd /initrd.img-6.8.0-47-generic
}
}

# 省略...

上面的信息就更加完整了,计算机启动时 gurb 菜单就是按照这个配置文件输出的。既然 grub 菜单中Ubuntu默认内核 linuz-6.8.0-48-generic 启动失败,那么就修改为 linuz-6.8.0-47-generic。

编辑 /boot/grub/grub.conf,仅修改Ubuntu菜单里面的内容,其他内容不做修改

1
2
3
4
5
6
7
8
9
10
11
12
menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b' {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root 0691b564-31ef-421c-9b8e-c7e498f0a651
linux /vmlinuz-6.8.0-47-generic root=UUID=78ef3df0-dd4a-47f6-a7f9-4cda535dfe1b ro quiet splash $vt_handoff
initrd /initrd.img-6.8.0-47-generic
}

接着重启计算机,grub 默认使用 linuz-6.8.0-47-generic 内核文件(因为选择这个可以正常进入系统),直接进入到用户登录界面。