1

I am trying to do something like this: How can I reinstall GRUB to the EFI partition?

However, I don't see how I can run chroot because it's an automated process (with Ansible, but that shouldn't matter; if this can be scripted in Bash, that'd work for me), so I am having trouble with grub-install.

My setup

Running a Ubuntu 18.04 system with a second hard drive (/dev/sdb) with two partitions: root partition (/dev/sdb2) mounted in /mnt/root, EFI partition (/dev/sdb1) mounted in /mnt/root/boot/efi. I copied everything from the running system to those two partitions as appropriate.

I've then tried to run this to install grub and make the second hard drive bootable:

grub-install /dev/sdb1 --efi-directory=/mnt/root/boot/efi --boot-directory=/mnt/root/boot --target=x86_64-efi

I've also tried (in addition) to regenerate the grub.cfg:

grub-mkconfig -o /mnt/root/boot/grub/grub.cfg

I know I probably need to mess with the UUIDs and tell GRUB which HD to boot from. The goal is to take out the second hard drive and boot it by itself in another machine (so GRUB may know it first as (hd1), but chances are it will be (hd0) in the new box.

Any idea on this?

EDIT:

I think GRUB is actually installed successfully. I am thrown into a grub> prompt, and can manually boot from the second hard drive. I guess that means I just need a working grub.cfg and possible /etc/fstab to make this work.

godfool
  • 21
  • 4
  • Boot drive is always hd0, so often first boot of anything not installed to first drive is an issue. Lets see details, use ppa version with your live installer (2nd option) or any working install, not Boot-Repair ISO: Please copy & paste the pastebin link to the Boot-info summary report ( do not post report), do not run the auto fix till reviewed. https://help.ubuntu.com/community/Boot-Repair I just install grub to sdb's ESP when installing. Posted work around to manually unmount & mount correct ESP during install #23 & #26 https://bugs.launchpad.net/ubuntu/+source/ubiquity/+bug/1396379 – oldfred Oct 19 '20 at 23:03
  • are you trying to clone your 18.04 system from drive "X" to drive "Y" and then configure grub on "Y" to make it bootable, so you can remove "Y" and boot it in another PC? – WU-TANG Oct 20 '20 at 02:46
  • @WU-TANG yes, exactly – godfool Oct 20 '20 at 12:26
  • @oldfred I will check out Boot Repair and see if it solves my problem, thanks! – godfool Oct 20 '20 at 12:29
  • There are much simpler ways to have done this... there are applications, there are even commands that can be used for cloning... With that said, if you get it working your own way, it builds experience. But if you end up needing other options, make it known. – WU-TANG Oct 20 '20 at 14:54
  • @WU-TANG I am open to suggestions. dd and co won't work well to clone a running system. – godfool Oct 20 '20 at 18:12
  • you just need to use a live CD/USB. Use your install disk and "try without installing". and clone the entire drive with dd.....OR you could also just use dd to clone the / partition and leave a small 10G space at the end and install another ubuntu in that space, it will install grub and recognize your cloned partition... once you get it booting, you can delete the small one... I'd leave some space at the beginning of the drive for the boot/UEFI partitions. you could probably attempt this now with your current state. Do this on the OTHER PC or disconnect your drive with the source copy – WU-TANG Oct 20 '20 at 18:27
  • This has to work unattended, so live CD is out. Not enough space on the hard drive to have two installs or a disk image for the second (because of system constraints). I think I am well aware of the usual ways to do it, but this isn't a usual way. Thanks for taking the time to answer, though! – godfool Oct 20 '20 at 18:40
  • can you clarify "has to work unattended, so a live CD is out"??? Also, for the other way, you dont need a second HUGE ubuntu install.. it can be a minimal install.. it doesnt even have to be ubuntu.. it can be any tiny linux that uses grub version 2, because grub is really all youre interested in. There are some pretty small ones, you just have to look them up. But yes these are quick unconventional ways to get it done – WU-TANG Oct 20 '20 at 19:21
  • I can't manually insert a CD (no drive) or anything. This has to be scriptable, no user input required (thus chroot doesn't work) – godfool Oct 20 '20 at 21:44

1 Answers1

0

I've finally got it to work, as follows (full Ansible playbook at the end).

I copy the original root partition to the new root partition, excluding some special mounts and (more significantly) the /boot directory contents, so I start from a clean slate:

rsync -ahPHAXx --delete --exclude={/dev/*,/proc/*,/sys/*,/tmp/*,/run/*,/boot/*,/mnt/*,/media/*,/lost+found/*} / /mnt/root

Then install grub:

grub-install --efi-directory=/mnt/esp --boot-directory=/mnt/root/boot --removable --target=x86_64-efi

Generate grub config:

grub-mkconfig -o /mnt/root/boot/grub/grub.cfg

This doesn't include the vmlinuz or initrd images for later (assuming an empty boot partition), so copy those over:

rsync -ahPHAXx --exclude="*/" --delete /boot/* /mnt/root/boot

Since the UUIDs are different, I need to update /mnt/root/boot/grub/grub.cfg and /mnt/root/etc/fstab, and replace every instance of the old UUID with the new one.

I also need to edit the ESP grub.cfg (in /mnt/esp/EFI/BOOT/grub.cfg) to look on hd0 instead of hd1.

I also removed reference to these /dev/sdb mounts from fstab, so all that is left is a line to mount the ESP, and one to mount /.

The whole Ansible playbook that does this for me is here:

---
- 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'

With these requirements:

---
collections:
  - community.general
godfool
  • 21
  • 4