Linux UEFI与备份还原(引导修复)

这篇文章主要介绍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/ 目录,把引导程序(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启动流程

  1. 系统开机 - 上电自检(Power On Self Test 或 POST)。
  2. UEFI 固件被加载,并由它初始化启动要用的硬件。
  3. 固件读取其引导管理器以确定从何处(比如,从哪个硬盘及分区)加载哪个 UEFI 应用。
  4. 固件按照引导管理器中的启动项目,加载UEFI 应用。
  5. 已启动的 UEFI 应用还可以启动其他应用(对应于 UEFI shell 或 rEFInd 之类的引导管理器的情况)或者启动内核及initramfs(对应于GRUB之类引导器的情况),这取决于 UEFI 应用的配置。

系统引导流程

成功引导系统,需要具备以下条件:

  1. UEFI 固件正常
  2. UEFI 启动项对应正确的 *.efi 文件
  3. EFI分区存在
  4. 引导器( *.efi )及其配置文件正常
  5. 操作系统相关文件正常

满足这些条件后,系统启动的过程大致是: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备份的特点:

  1. 保留权限
  2. 适合备份整个目录
  3. 可以选择不同的压缩方式
  4. 如果选择不压缩还能实现增量备份,部份还原,参考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目录内,否则,会把被挂载的分区也备份在内,备份文件会很大。还要注意不要把备份文件本身也备份进去了,也需要剔除。

开始备份

  1. livecd启动
  2. 命令行切换root sudo su
  3. 手动挂载原系统分区到/mnt /mnt/home /mnt/boot/efi 挂载备份用的移动硬盘
    #先挂载根目录
    mount /dev/nvme0n1p3  /mnt
    mount /dev/nvme0n1p4  /mnt/home
    mount /dev/nvme0n1p1  /mnt/boot/efi
    
  4. 切换工作目录 cd /mnt
  5. tar备份
    tar -cvpzf /media/disk-1/backup.tgz .
    注解:
    备份文件的存放路径与名称为/media/disk-1/backup.tgz
    备份时没有剔除任何目录,因为另一个linux没有运行,里面没有临时文件。
    “cvpfz”是tar的选项,意思是“创建档案文件”、“保持权限”(保留所有东西原来的权限)、“使用gzip来减小文件尺寸”、“输出信息”。
  6. 记录原系统数据 包括 df -hl 输出 和 /mnt/etc/fstab 等
  7. 完成,可以tar -tf backup.tgz看看效果

还原

  1. livecd启动
  2. 调整磁盘分区 gparted (关注ESP)
  3. 命令行切换root sudo su
  4. 手动挂载分区到/mnt /mnt/home /mnt/boot/efi
  5. 切换工作目录 cd /mnt
  6. 解压 tar -xvpzf backup.tgz
  7. 修复引导(下面重点讨论)

调整分区

如果恢复时不需要修改分区方案,可以跳过本节内容。如果你想迁移系统,或者是在全新的硬盘上恢复,那就必须调整分区了。我推荐使用livecd上的gparted工具编辑分区,能力比较强的可以试试gdisk或者parted命令。

Linux UEFI与备份还原(引导修复)_第1张图片
gparted1.png
Linux UEFI与备份还原(引导修复)_第2张图片
gparted2.png

先对本地磁盘分区状况有个大致了解,然后再创建新的分区用于还原系统。比如我想恢复Ubuntu系统,新建sda4分配合适的大小。再看看ESP分区正常,之后要挂载到/mnt/boot/efi 。

如果没有ESP分区,重建。


Linux UEFI与备份还原(引导修复)_第3张图片
esp.png

引导修复

成功引导系统,需要具备以下条件:

  1. UEFI 固件正常
  2. UEFI 启动项对应正确的 *.efi 文件
  3. EFI分区存在
  4. 引导器( *.efi )及其配置文件正常
  5. 操作系统相关文件正常

满足这些条件后,系统启动的过程大致是: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/

Linux UEFI与备份还原(引导修复)_第4张图片
grub.png

操作成功后,看到EFI分区多出了boot ubuntu目录。


Linux UEFI与备份还原(引导修复)_第5张图片
esp2.png

重启后成功引导了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

https://blog.csdn.net/sunnylgz/article/details/8055315

https://blog.csdn.net/xiongyangg/article/details/23693803

你可能感兴趣的:(Linux UEFI与备份还原(引导修复))