ubuntu重启后进入initramfs的解决方法,以及关于initramfs的相关知识
问题分析进入到Ubuntu16.04后发现无法复制、粘贴,但是用ls -l查看权限都是正常的。重启发现一直卡在关机的界面,于是硬重启(按下机箱的reset按钮),重启后进入到initramfs的shell提示符。原因分析回顾Linux系统启动过程,进入initramfs就意味着kernel已经load了,就差挂载rootfs了。说明是rootfs所在的磁盘出现了问题。解决方法用cat...
问题描述
进入到Ubuntu16.04后发现无法复制、粘贴,但是用ls -l查看权限都是正常的。重启发现一直卡在关机的界面,于是硬重启(按下机箱的reset按钮),重启后进入到initramfs的shell提示符。
原因分析
回顾Linux系统启动过程,进入initramfs就意味着kernel已经load了,就差挂载rootfs了。说明是rootfs所在的磁盘出现了问题。
解决方法
-
用cat /proc/cmdline会找到rootfs所在磁盘的UUID。
-
用sudo blkid会找到所有磁盘的UUID和它对应的dev/下的设备号,比如说/dev/sdc1。
-
用fsck -l /dev/sdc1来修复磁盘文件系统(innodes、blocks),一路按y就可以修复磁盘了。
最终成功。
相关知识
1.initramfs是什么?
The initramfs is a gzipped cpio archive. At boot time, the kernel unpacks that archive into RAM disk, mounts and uses it as initial root file system. All finding of the root device happens in this early user space.
在initramfs的提示符下,也可以看到和rootfs差不多的文件夹:bin、lib等。
2.initramfs的作用是?
It is used for mounting the real rootfs which has all your data. The initramfs carries the modules needed for mounting your rootfs.
3. 一定要有initramfs吗?
initramfs中包含的module都是为了mount rootfs,但是这些module其实都可以编译到kernel中,那么还需要initramfs吗?
答案是:“depends on your system”。
一个必须需要initramfs的例子就是对加密设备的访问。现在考虑一下没有initramfs、但是在挂载rootfs前需要向用户询问密码的场景。这个询问密码是需要在user space执行的,但是只有rootfs挂载后,才可以在user space中执行这个功能。于是这显然是一个chicken and egg problem,无解。
因此对于这种情况,除了rootfs之外,必须有一个临时的、可以实现在user space实现相关功能的fs,即initramfs。
那么这些user space的utility都来自与哪里?实际上都来自于rootfs。因此,可以把initramfs理解为是rootfs的精简版。
4. initramfs在哪里?
进入ubuntu后,在/boot/grub目录下,有一个grub.ctg文件,有这样一段:
menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-95e0c7e4-bca0-4431-b225-c5a27347c8e7' {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_msdos
insmod ext2
set root='hd2,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd2,msdos1 --hint-efi=hd2,msdos1 --hint-baremetal=ahci2,msdos1 95e0c7e4-bca0-4431-b225-c5a27347c8e7
else
search --no-floppy --fs-uuid --set=root 95e0c7e4-bca0-4431-b225-c5a27347c8e7
fi
linux /boot/vmlinuz-4.15.0-88-generic root=UUID=95e0c7e4-bca0-4431-b225-c5a27347c8e7 ro quiet splash $vt_handoff
initrd /boot/initrd.img-4.15.0-88-generic
}
最后一行的initrd就是initramfs对应的文件:/boot/initrd.img-4.15.0-88-generic。
用file指令查看这个文件:
$ file initrd.img-4.15.0-45-generic
initrd.img-4.15.0-45-generic: ASCII cpio archive (SVR4 with no CRC)
可以看出它是一个cpio的档案文件,大小只有60多MB。而Ubuntu一个完整的rootfs大概是GB的级别。
5. initramfs中都有哪些文件?
如何解压缩initrd.img-4.15.0-45-generic?
虽然用file指令可以看出该文件是一个ASCII cpio文件,但是用cpio -id < initrd.img-4.15.0-45-generic却只能得到如下的文件:
└── kernel
└── x86
└── microcode
└── AuthenticAMD.bin
这显然不对,因为initrd.img-4.15.0-45-generic的大小是68.5MB,而这个AuthenticAMD.bin只有27.4KB。顺便说一句,这个AuthenticAMD.bin文件是对AMD CPU的microcode打补丁的文件。更过关于microcode的知识,可以看这篇。
正确提取initrd.img-4.15.0-45-generic的方法如下,首先用binwalk来查看initrd.img-4.15.0-45-generic的组成:
$ binwalk initrd.img-4.15.0-45-generic
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 ASCII cpio archive (SVR4 with no CRC), file name: ".", file name length: "0x00000002", file size: "0x00000000"
112 0x70 ASCII cpio archive (SVR4 with no CRC), file name: "kernel", file name length: "0x00000007", file size: "0x00000000"
232 0xE8 ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86", file name length: "0x0000000B", file size: "0x00000000"
356 0x164 ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode", file name length: "0x00000015", file size: "0x00000000"
488 0x1E8 ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode/AuthenticAMD.bin", file name length: "0x00000026", file size: "0x00006B2A"
28072 0x6DA8 ASCII cpio archive (SVR4 with no CRC), file name: "TRAILER!!!", file name length: "0x0000000B", file size: "0x00000000"
28672 0x7000 ASCII cpio archive (SVR4 with no CRC), file name: "kernel", file name length: "0x00000007", file size: "0x00000000"
28792 0x7078 ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86", file name length: "0x0000000B", file size: "0x00000000"
28916 0x70F4 ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode", file name length: "0x00000015", file size: "0x00000000"
29048 0x7178 ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode/GenuineIntel.bin", file name length: "0x0000002A", file size: "0x002D2C00"
2989584 0x2D9E10 ASCII cpio archive (SVR4 with no CRC), file name: "TRAILER!!!", file name length: "0x0000000B", file size: "0x00000000"
2990080 0x2DA000 gzip compressed data, from Unix, last modified: 2020-02-23 06:04:02
24602446 0x177674E xz compressed data
40511347 0x26A2773 MySQL ISAM compressed data file Version 9
60684299 0x39DF80B MySQL ISAM compressed data file Version 3
可以看出,该文件后面还有gzip、xz、MYSQL ISAM压缩文件。
提取出gzip文件、并依次通过gzip和cpio对其解压:
dd if=initrd.img-4.15.0-45-generic of=image.gz bs=2990080 skip=1
gunzip image.gz
cpio -i < image
得到以下文件夹,这个就和我们在initramfs提示符下看到的差不多了:
.
├── bin
├── conf
├── etc
├── image
├── init
├── lib
├── lib64
├── run
├── sbin
├── scripts
├── usr
└── var
上述方法参考了Ubuntu18.04的解决方法。
我没有对initrd.img-4.15.0-45-generic剩下的两个文件xz compressed data和MYSQL ISAM继续研究。
6. initramfs中的文件如何执行?
ubuntu的wiki详细描述了这个过程。
总的来说,initramfs的执行过程是:
- 执行init进程
- init调用scripts文件夹其他脚本
1)init-top
2)init-premount
3)boot-top (your crypt scripts execute here - to ask the user password for eg)
4)boot-premount
5)boot:mount rootfs到/initramfs/root/
6)boot-bottom
7)init-bottom - init进程重新得到控制权,然后执行:
1)moves the /sys from initramfs to /initramfs/root/sys (in your real rootfs)
2)moves /proc from initramfs to /initramfs/root/proc
3)calls run-init to run the real init in your real rootfs kept in /root. run-init does something like
chroot to the real rootfs and then executes the init kept in /sbin/ or /bin or whatever user requested as a boot parameter.
更多推荐
所有评论(0)