我正在尝试做这样的事情:如何将 GRUB 重新安装到 EFI 分区?
但是,我不知道如何运行,chroot
因为这是一个自动化过程(使用 Ansible,但这并不重要;如果可以在 Bash 中编写脚本,那对我来说就行得通了),所以我遇到了麻烦grub-install
。
我的设置
运行带有第二块硬盘 ( /dev/sdb
) 的 Ubuntu 18.04 系统,其中有两个分区:根分区 ( /dev/sdb2
) 安装在 中/mnt/root
,EFI 分区 ( /dev/sdb1
) 安装在 中/mnt/root/boot/efi
。我根据需要将正在运行的系统中的全部内容复制到了这两个分区中。
然后我尝试运行这个来安装 grub 并使第二个硬盘可启动:
grub-install /dev/sdb1 --efi-directory=/mnt/root/boot/efi --boot-directory=/mnt/root/boot --target=x86_64-efi
我还尝试过(另外)重新生成 grub.cfg:
grub-mkconfig -o /mnt/root/boot/grub/grub.cfg
我知道我可能需要弄乱 UUID 并告诉 GRUB 从哪个硬盘启动。目标是取出第二个硬盘并启动它通过它自己在另一台机器上(因此 GRUB 可能首先知道它(hd1)
,但很有可能它(hd0)
在新的机器中。
对此有什么想法吗?
编辑:
我认为 GRUB 确实已成功安装。我进入提示符grub>
,并可以从第二个硬盘驱动器手动启动。我想这意味着我只需要一个可行的grub.cfg
方法就/etc/fstab
可以完成这项工作。
答案1
我终于让它工作了,如下所示(最后有完整的 Ansible 剧本)。
我将原始根分区复制到新的根分区,排除一些特殊的挂载和(更重要的是)/boot
目录内容,因此我从一张白纸开始:
rsync -ahPHAXx --delete --exclude={/dev/*,/proc/*,/sys/*,/tmp/*,/run/*,/boot/*,/mnt/*,/media/*,/lost+found/*} / /mnt/root
然后安装grub:
grub-install --efi-directory=/mnt/esp --boot-directory=/mnt/root/boot --removable --target=x86_64-efi
生成 grub 配置:
grub-mkconfig -o /mnt/root/boot/grub/grub.cfg
这不包括稍后使用的vmlinuz
图像initrd
(假设启动分区为空),因此请将它们复制过来:
rsync -ahPHAXx --exclude="*/" --delete /boot/* /mnt/root/boot
由于 UUID 不同,我需要更新/mnt/root/boot/grub/grub.cfg
和/mnt/root/etc/fstab
,并用新的 UUID 替换旧 UUID 的每个实例。
我还需要编辑 ESP grub.cfg(在 中/mnt/esp/EFI/BOOT/grub.cfg
)以查看hd0
而不是hd1
。
我还/dev/sdb
从中删除了对这些安装的引用fstab
,因此剩下的只是一行用于安装 ESP,以及一行用于安装/
。
为我完成此操作的整个 Ansible 剧本如下:
---
- hosts:
- deploy
become: yes
become_method: sudo
vars:
device: /dev/sdb
tasks:
- name: Unmount
mount:
path: "/mnt/{{ item }}"
state: unmounted
with_items:
- esp
- root
- name: Delete partitions
community.general.parted:
device: "{{ device }}"
number: "{{ item }}"
state: absent
with_items:
- 1
- 2
- name: Create efi partition
community.general.parted:
device: "{{ device }}"
number: 1
label: gpt
fs_type: fat32
name: EFI System Partition
flags: [ esp, boot ]
part_start: "1MiB"
part_end: "513MiB"
state: present
register: part
- debug:
var: part
- name: Create root partition
community.general.parted:
device: "{{ device }}"
number: 2
name: root
label: gpt # need to repeat the label here, otherwise the first partition gets overwritten
part_start: "513MiB"
part_end: "100%"
state: present
- name: Make root partition ext4
filesystem:
dev: "{{ device }}2"
fstype: ext4
- name: Make efi partition fat32
shell: "mkfs.fat -F32 {{ device }}1"
- name: "Get UUID for existing root"
command: blkid -s UUID -o value /dev/sda2
register: root_uuid
changed_when: False
- name: "Get UUID for existing efi"
command: blkid -s UUID -o value /dev/sda1
register: efi_uuid
changed_when: False
- name: "Get UUID for new root"
command: blkid -s UUID -o value {{ device }}2
register: new_root_uuid
changed_when: False
- name: "Get UUID for new efi"
command: blkid -s UUID -o value {{ device }}1
register: new_efi_uuid
changed_when: False
- debug:
var: efi_uuid.stdout
- debug:
var: new_efi_uuid.stdout
- debug:
var: root_uuid.stdout
- debug:
var: new_root_uuid.stdout
- name: Mount root from the other device
mount:
path: /mnt/root
src: "{{ device }}2"
fstype: ext4
state: mounted
- name: Mount efi from the other device
mount:
path: /mnt/esp
src: "{{ device }}1"
fstype: vfat
state: mounted
- name: copy root partition over
shell: rsync -ahPHAXx --delete --exclude={/dev/*,/proc/*,/sys/*,/tmp/*,/run/*,/boot/*,/mnt/*,/media/*,/lost+found/*} / /mnt/root
args:
executable: /bin/bash
- name: copy boot images over
shell: rsync -ahPHAXx --exclude="*/" --delete /boot/* /mnt/root/boot
- name: install GRUB to make it bootable
shell: "grub-install --efi-directory=/mnt/esp --boot-directory=/mnt/root/boot --removable --target=x86_64-efi"
- name: Edit grub.cfg to point to hd0
replace:
path: /mnt/esp/EFI/BOOT/grub.cfg
regexp: hd1
replace: hd0
- name: Generate grub.cfg
shell: "grub-mkconfig -o /mnt/root/boot/grub/grub.cfg"
- name: Edit UUID in boot/grub/grub.cfg
replace:
path: /mnt/root/boot/grub/grub.cfg
regexp: "{{ root_uuid.stdout }}"
replace: "{{ new_root_uuid.stdout }}"
- name: Edit root UUID in etc/fstab
replace:
path: /mnt/root/etc/fstab
regexp: "{{ root_uuid.stdout }}"
replace: "{{ new_root_uuid.stdout }}"
- name: Edit ESP UUID in etc/fstab
replace:
path: /mnt/root/etc/fstab
regexp: "{{ efi_uuid.stdout }}"
replace: "{{ new_efi_uuid.stdout }}"
- name: Remove /dev/sdb references from fstab
lineinfile:
path: /mnt/root/etc/fstab
state: absent
regexp: '^/dev/sdb'
满足以下要求:
---
collections:
- community.general