这篇文章主要介绍UEFI启动流程、Linux系统下的备份还原以及grub引导修复。
UEFI相关知识
UEFI启动要求硬盘上有一个特殊的分区——EFI系统分区。它是FAT32格式带有efi、boot标志的分区,大小一般在300MB到500MB之间,用来存储系统的EFI boot loader以及启动时固件使用的应用程序。
Boot Loader 是在操作系统内核运行之前运行的一段小程序。这段小程序可以将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
我们看看自己电脑上的情况,先用 fdisk 找到EFI分区,再用 df 找到挂载点,一般是在 /boot/efi 目录下。
$ sudo fdisk -l
Disk /dev/nvme0n1: 238.5 GiB, 256060514304 bytes, 500118192 sectors
.......
Device Start End Sectors Size Type
/dev/nvme0n1p1 2048 616447 614400 300M EFI System
/dev/nvme0n1p2 616448 23685119 23068672 11G Linux swap
/dev/nvme0n1p3 23685120 118970367 95285248 45.4G Linux filesystem
......
$ df -lh
文件系统 容量 已用 可用 已用% 挂载点
/dev/nvme0n1p3 45G 9.3G 33G 22% /
/dev/nvme0n1p1 300M 32M 269M 11% /boot/efi
/dev/nvme0n1p4 89G 8.4G 77G 10% /home
.....
# 再看看这个目录下有哪些文件
# jzc @ jzc-PC in /boot/efi/EFI [12:11:08] C:130
$ tree -L 2
.
├── boot
│ ├── bootx64.efi
│ ├── grub.cfg
│ └── grubx64.efi
├── deepin
│ ├── fbx64.efi
│ ├── grub.cfg
│ ├── grubx64.efi
│ ├── mmx64.efi
│ └── shimx64.efi
├── Microsoft
│ ├── Boot
│ └── Recovery
└── ubuntu
├── grub.cfg
└── grubx64.efi
EFI分区有一个顶层目录——EFI文件夹,里面有不同的操作系统创建的子文件夹(例如ubuntu deepin Windows)。其中bootx64.efi是默认的引导程序,grubx64.efi是grub引导程序,shimx64.efi是shim引导程序(shim用于安全启动Secure Boot,调用grub)。一般安装Linux的电脑会关闭Secure Boot,这样grubx64.efi 和 shimx64.efi 就没什么区别了。
如果要启动Windows系统,UEFI应加载 EFI/Microsoft/Boot/bootmgfw.efi 。
如果要启动deepin系统,UEFI应加载 EFI/deepin/grubx64.efi 。
那么*.efi 文件是从哪里来的呢?
操作系统安装器会创建 /EFI/<distro> 目录,把引导程序(grubx64.efi)放入其中,然后在UEFI 启动管理器中创建入口点(开机按下F12键选择从何处启动)。
Win8安装时会首先创建自己的目录/efi/microsoft/boot,并在里面放置bootmgfw.efi ,然后再把bootmgfw.efi拷一份到/efi/boot里并命名成bootx64.efi,这样系统默认就从win8启动了。
然后你装ubuntu的时候,ubuntu也会创建/efi/ubutntu/这个目录并放一个grubx64.efi,作用类似于win8的bootmgfw.efi。
UEFI 启动管理器
简单来说,你可以把 UEFI 启动管理器视为启动菜单。例如开机按下F12键选择从何处启动。
UEFI 启动管理器可以进行配置,你可以向“启动菜单”添加项或者从中删除项。你也可以检查启动菜单,确保正确无误。我们不妨看一些典型的 efibootmgr 输出
# jzc @ jzc-PC in /boot/efi/EFI/deepin [14:28:28]
$ efibootmgr -v
BootCurrent: 0000
Timeout: 0 seconds
BootOrder: 0006,0001,0002,0003,0004,0005,0000
Boot0000* deepin PciRoot(0x0)/Pci(0x1d,0x0)/Pci(0x0,0x0)/NVMe(0x1,00-1B-44-4A-44-45-1A-7C)/HD(1,GPT,17b7c336-6227-4abf-86e4-421c91b21775,0x800,0x96000)/File(\EFI\deepin\grubx64.efi)
Boot0001* Diskette Drive BBS(Floppy,Diskette Drive,0x0)..BO
Boot0002* USB Storage Device BBS(USB,USB Storage Device,0x0)..BO
Boot0003* CD/DVD/CD-RW Drive BBS(CDROM,CD/DVD/CD-RW Drive,0x0)..BO
Boot0004* Onboard NIC BBS(Network,IBA CL Slot 00FE v0113,0x0)..BO
Boot0005* Windows PciRoot(0x0)/Pci(0x1d,0x0)/Pci(0x0,0x0)/NVMe(0x1,00-1B-44-4A-44-45-1A-7C)/HD(1,GPT,17b7c336-6227-4abf-86e4-421c91b21775,0x800,0x96000)/File(\EFI\Microsoft\Boot\bootmgfw.efi)
第一行表示当前系统的启动项。BootOrder 是列表中启动项的尝试顺序。其余输出显示了实际的启动项。我们稍后会说明每一个启动项具体作用。
如果正常启动 UEFI 固件,而不进行任何调整,UEFI 固件将按照BootOrder 中列出的顺序,尝试从“启动菜单”中的每个“项”进行启动。因此,在这台计算机上,UEFI 固件将尝试启动名为“deepin”的项,如果启动失败,然后再尝试启动名为“Windows”的项。
不得不说,现在UEFI功能很强大。不仅有图形界面、可以使用鼠标、还能在UEFI中手动设置引导项,相当于在Linux系统中使用efibootmgr命令。
UEFI启动模式下如何从u盘或移动硬盘引导
只要u盘或移动硬盘上有一个fat32的分区,分区的根目录下有个文件夹叫EFI,UEFI就会自动去查找相应的启动文件(.efi)
如果你刚制作了ubuntu(kylin)-13.04-64位的启动u盘,可以打开它,你会发现分区的文件系统是fat32,确实有一个EFI文件夹,进去看看就是各种.efi引导文件。因此现在想制作可启动的u盘或移动硬盘就简单了,只需要复制粘贴就行了。
UEFI启动流程
- 系统开机 - 上电自检(Power On Self Test 或 POST)。
- UEFI 固件被加载,并由它初始化启动要用的硬件。
- 固件读取其引导管理器以确定从何处(比如,从哪个硬盘及分区)加载哪个 UEFI 应用。
- 固件按照引导管理器中的启动项目,加载UEFI 应用。
- 已启动的 UEFI 应用还可以启动其他应用(对应于 UEFI shell 或 rEFInd 之类的引导管理器的情况)或者启动内核及initramfs(对应于GRUB之类引导器的情况),这取决于 UEFI 应用的配置。
系统引导流程
成功引导系统,需要具备以下条件:
- UEFI 固件正常
- UEFI 启动项对应正确的 *.efi 文件
- EFI分区存在
- 引导器( *.efi )及其配置文件正常
- 操作系统相关文件正常
满足这些条件后,系统启动的过程大致是:UEFI 根据 BootOrder 加载 EFI 分区中的某个引导器(grubx64.efi),引导器加载配置文件(grub.cfg)呈现启动菜单(GRUB 菜单),用户选择启动项后引导器加载操作系统内核。
备份
对于喜欢折腾的人来说,系统崩溃是常有的事,所以备份系统就是一件不容忽视的事情。由于 Linux 系统本身的优越性,系统的备份和还原还是比较容易的。主要表现在以下方面:
- Linux 系统所有的数据都以文件的形式存在,所以备份就是直接拷贝文件;硬盘分区也被当成文件,所以可以直接克隆硬盘数据。
- Linux 系统自带很多实用工具,比如 tar、dd、rsync 等,备份还原系统不需要购买或下载第三方软件。
- Linux 系统在运行时其硬盘上的文件可以直接被覆盖,所以还原系统的时候不需要另外的引导盘。(当然,系统完全挂掉到无法启动这种情况还是需要另外的引导盘的。)
备份Linux的策略有很多,比如dd备份磁盘,dump备份文件系统,tar打包文件等等。
这篇文章介绍的是livecd启动tar打包备份系统的方法。之所以用livecd启动,是为了防止运行时需要备份的文件被修改。同时livecd方便后续恢复系统和修复引导。如果系统严重损坏,只能从livecd启动了。
先看看系统已经挂载的磁盘
$ df -hl
文件系统 容量 已用 可用 已用% 挂载点
udev 3.8G 0 3.8G 0% /dev
tmpfs 778M 1.8M 776M 1% /run
/dev/nvme0n1p3 45G 8.4G 34G 20% /
tmpfs 3.8G 2.5M 3.8G 1% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 3.8G 0 3.8G 0% /sys/fs/cgroup
/dev/nvme0n1p1 300M 32M 269M 11% /boot/efi
/dev/nvme0n1p4 89G 3.3G 82G 4% /home
tmpfs 778M 32K 778M 1% /run/user/1000
这里重点关注三个地方
/dev/nvme0n1p3 45G 8.4G 34G 20% /
/dev/nvme0n1p1 300M 32M 269M 11% /boot/efi
/dev/nvme0n1p4 89G 3.3G 82G 4% /home
说明当前系统依赖的文件储存在nvme0n1硬盘的第一、三、四分区,这个信息很重要。因为用livecd启动时,我们需要手动挂载这些分区到对应的目录,然后才能正确备份。如果你在livecd里忘记挂载/dev/nvme0n1p4,那么/mnt/home目录里是空的,你就少备份了一些数据。
这里顺便说一下/mnt和/media的区别,一般手动挂载的放在/mnt(手动建好挂载点,再用命令挂载),系统自动挂载的放在/media。
从livecd启动,开始备份之前,先介绍一下tar命令。
tar [-cxtzjvfpPN] 压缩文档的名称 欲备份目录
参数:
-c :建立一个压缩文件的参数指令(create 的意思);
-x :解开一个压缩文件的参数指令!
-t :查看 tarfile 里面的文件!
注意:在参数中,c/x/t 仅能存在一个!不可同时存在!因为不可能同时压缩与解压缩。
-z :是否同时具有 gzip 的属性?亦即是否需要用 gzip 压缩?
-j :是否同时具有 bzip2 的属性?亦即是否需要用 bzip2 压缩?
-v :压缩的过程中显示文件!这个常用,但不建议用在背景执行过程!
-f :使用档名,请留意,在 f 之后要立即接档名喔!不要再加参数!
-p :使用原文件的原来属性(属性不会依据使用者而变)
-P :(大写)可以使用绝对路径来压缩!
-N :(大写)比后面接的日期(yyyy/mm/dd)还要新的才会被打包进新建的文件中!
-C:(大写)目的目录,即切换到指定的目录
--exclude FILE:在压缩的过程中,不要将 FILE 打包!
--exclude参数有两个坑
第一要注意它的位置 `tar -cvzpf [archive] --exclude=[pattern] [FILE...]`
可以 `man tar` 看看语法 ` tar -c [-f ARCHIVE] [OPTIONS] [FILE...]` --exclude作为option不能放在最后面,否则失效。
第二个,如果排除目录,目录后不要加/。正确: --exclude=/home,错误: --exclude=/home/
用tar备份的特点:
- 保留权限
- 适合备份整个目录
- 可以选择不同的压缩方式
- 如果选择不压缩还能实现增量备份,部份还原,参考man tar
如果在Linux下备份自身系统,需要排除一些目录(很遗憾我们不使用这个方法,我们是用livecd备份另一个系统)
sudo tar -cvpzf /media/disk/backup.tgz --exclude=/proc --exclude=/lost+found --exclude=/tmp --exclude=/sys --exclude=/media --exclude=/home /
这些目录是不需要备份的。如:/proc目录、 /tmp目录、/sys目录,里面都是临时文件,备份容易出错,/home目录备份容易引起"tar: 由于前面延迟的错误而退出"的提示。 同时确保你没有任何东西挂载在/mnt、/media目录内,否则,会把被挂载的分区也备份在内,备份文件会很大。还要注意不要把备份文件本身也备份进去了,也需要剔除。
开始备份
- livecd启动
- 命令行切换root
sudo su
- 手动挂载原系统分区到/mnt /mnt/home /mnt/boot/efi 挂载备份用的移动硬盘
#先挂载根目录 mount /dev/nvme0n1p3 /mnt mount /dev/nvme0n1p4 /mnt/home mount /dev/nvme0n1p1 /mnt/boot/efi
- 切换工作目录
cd /mnt
- tar备份
tar -cvpzf /media/disk-1/backup.tgz .
注解:
备份文件的存放路径与名称为/media/disk-1/backup.tgz
备份时没有剔除任何目录,因为另一个linux没有运行,里面没有临时文件。
“cvpfz”是tar的选项,意思是“创建档案文件”、“保持权限”(保留所有东西原来的权限)、“使用gzip来减小文件尺寸”、“输出信息”。 - 记录原系统数据 包括 df -hl 输出 和 /mnt/etc/fstab 等
- 完成,可以
tar -tf backup.tgz
看看效果
还原
- livecd启动
- 调整磁盘分区 gparted (关注ESP)
- 命令行切换root
sudo su
- 手动挂载分区到/mnt /mnt/home /mnt/boot/efi
- 切换工作目录
cd /mnt
- 解压 tar -xvpzf backup.tgz
- 修复引导(下面重点讨论)
调整分区
如果恢复时不需要修改分区方案,可以跳过本节内容。如果你想迁移系统,或者是在全新的硬盘上恢复,那就必须调整分区了。我推荐使用livecd上的gparted工具编辑分区,能力比较强的可以试试gdisk或者parted命令。
先对本地磁盘分区状况有个大致了解,然后再创建新的分区用于还原系统。比如我想恢复Ubuntu系统,新建sda4分配合适的大小。再看看ESP分区正常,之后要挂载到/mnt/boot/efi 。
如果没有ESP分区,重建。
引导修复
成功引导系统,需要具备以下条件:
- UEFI 固件正常
- UEFI 启动项对应正确的 *.efi 文件
- EFI分区存在
- 引导器( *.efi )及其配置文件正常
- 操作系统相关文件正常
满足这些条件后,系统启动的过程大致是:UEFI 根据 BootOrder 加载 EFI 分区中的某个引导器(grubx64.efi),引导器加载配置文件(grub.cfg)呈现启动菜单(GRUB 菜单),用户选择启动项后引导器加载操作系统内核。
既然是还原的系统,UEFI 固件 和 操作系统相关文件应该是正常的。第三点上面已经讲了,如果不存在就重建。最容易出问题的是第二点和第四点。
因为UEFI的启动项 和 引导器的配置文件 依赖分区的UUID。还原后分区状况很可能修改过了,UUID不一样,所以引导失败。下面是我的UEFI启动项设置,可以看到 e08182..... 那一串东西就是UUID。
$ efibootmgr -v
Boot0008* deepin PciRoot(0x0)/Pci(0x1d,0x0)/Pci(0x0,0x0)/NVMe(0x1,00-1B-44-4A-44-45-1A-7C)/HD(1,GPT,17b7c336-6227-4abf-86e4-421c91b21775,0x800,0x96000)/File(\EFI\deepin\grubx64.efi)
Boot000D* UEFI: WDC WDS256G1X0C-00ENX0, Partition 6 HD(6,GPT,a02f7983-6cff-4a88-828c-679bdcaeba4c,0x1c5b0000,0xee6b3)/File(\EFI\boot\bootx64.efi)..BO
Boot000E* backup PciRoot(0x0)/Pci(0x14,0x0)/USB(18,0)/HD(1,GPT,e0818233-4b33-483d-b3e4-54a19f9c0601,0x800,0x96000)/File(\EFI\BOOT\grubx64.efi)
grub.cfg文件节选内容 932200a3.... 同样是UUID
set linux_gfx_mode=
export linux_gfx_mode
menuentry 'Deepin 15.11 GNU/Linux' --class deepin --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-932200a3-ff33-48a4-a1c9-23da8cd5d964' {
...
search --no-floppy --fs-uuid --set=root 932200a3-ff33-48a4-a1c9-23da8cd5d964
else
search --no-floppy --fs-uuid --set=root 932200a3-ff33-48a4-a1c9-23da8cd5d964
如果你还原后,可以进入之前的系统,那么你只需要 update-grub 更新一下就可以了。下次启动时grub菜单会出现系统的引导项。update-grub 做了两件事,1. 检测硬盘上的系统,生成grub.cfg文件 2. 添加UEFI启动项
如果不能进入系统,需要用livecd启动重装grub
livecd重装grub 参考 https://linuxsuperuser.com/reinstall-grub2-efi-bootloader-ubuntu/
操作成功后,看到EFI分区多出了boot ubuntu目录。
重启后成功引导了Ubuntu系统,但没有进入图形界面,进入了紧急模式。猜测是/etc/fstab配置问题,修改UUID后成功进入桌面!
参考资料:
https://wiki.mageia.org/en/About_EFI_UEFI
https://en.wikipedia.org/wiki/EFI_system_partition#Linux
https://en.wikipedia.org/wiki/GNU_GRUB#Startup_on_systems_using_UEFI_firmware
https://www.cnblogs.com/youxia/p/linux013.html