2013-04-06
What I needed to do with Grub2 to change my boot disk
On my work machine I have been very slowly migrating away from a
pair of old drives to a pair of new drives. For quite a while the only thing the old drives have been used for
has been booting from and holding /boot
; today I finally removed the
single surviving old disk and moved to booting off the new disks. It
turned out to be somewhat more involved than I expected.
The initial state was /dev/sda
as the old drive with /boot
as a
plain filesystems, /dev/sdb
and /dev/sdc
as the new drives with
/boot-n
(the new version of /boot
) as a mirrored RAID array and
filesystem.
My first step (some time ago actually) was to run grub2-install
to
install the boot blocks on sdb
(and sdc
, although I have no idea if
those work). Unfortunately I forgot to save the exact commands I used to
do this. My notes say that I bind-mounted /boot-n
on top of /boot
during this process so that grub2-install
would see the right thing in
the right place but I'm not sure how I handled device mappings.
Today I changed my /etc/fstab
to fix up the mounts (basically
changing /boot-n
into /boot
), shut the machine down, pulled the
old drive, shuffled the cables around, and booted up. The machine
started Grub2 but then couldn't boot Linux, ultimately because it
couldn't find the kernel and initramfs. This happened because I
forgot to update grub.cfg to tell it the new location and UUIDs of
the new /boot
. Although Grub2 could find the new /boot
in
order to load grub.cfg, the various kernel stanzas in grub.cfg
re-specify where to find the kernel and initramfs with boiler plate
like this:
set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' bfe06079-ea84-49cb-a028-d5b1ad47cfba else search --no-floppy --fs-uuid --set=root bfe06079-ea84-49cb-a028-d5b1ad47cfba fi linux /vmlinuz-....
(The complexity of a Grub2 grub.cfg
is why I'm not really fond
of Grub2. I'm not sure we need a shell script interpreter embedded
in the boot system, and if it has to be fully programmable I wish
they'd used a better language.)
Since my /boot
was no longer (MS-DOS) partition 1 or a filesystem with
that UUID, this failed and everything bombed out.
To get the machine booted I dropped into the Grub2 command line and used
its ls
command to see what was there (per the Fedora page on Grub2). After finding that I wanted
'md/13
' (I believe) I went back and changed the 'set root=...
' line
to specify it, then told Grub2 to try booting. This worked, although
Grub2 warned me that it still couldn't find the particular UUID.
Fixing this permanently required revising grub.cfg
; I actually did
this twice, once the hard way and once the easy way. The hard way is to
use blkid
to look up the new /boot
's UUID then carefully edit all of
the stanzas to change the set root=...
bit to md/13
and change the
UUID in the search
lines. While this worked I didn't think that all of
those --hint-...
bits were correct any more and they made me nervous.
The easy way to fix this is to use grub2-mkconfig -o /tmp/foo
and
then pick through /tmp/foo
for the official and proper way to do
all of this boiler plate. It turned out to be (for me):
set root='mduuid/<md-uuid>'
....
search --no-floppy --fs-uuid --set=root --hint='mduuid/<md-uuid>' <fs-uuid>
(grub2-mkconfig
looked up the UUIDs for itself.)
(The really easy way would be to just use grub2-mkconfig
to
regenerate your grub.cfg
, but I have an old-style grub.cfg
that
I happen to like and didn't want to have replaced with the new
Fedora 18 grub2-mkconfig
version. Also note that the grub.cfg that
grub2-mkconfig
creates for you may look nothing like the grub.cfg that
the Fedora installer creates. This is a complete mess and I hope that
Fedora fixes it someday.)
I'm sure that I'm going to need to do this again sometime in the future.
In that future, the smart thing to do will be to update grub.cfg
before the initial reboot (after the final copy from the old /boot
,
for obvious reasons). I'm not sure if grub2-mkconfig
would give the
right results (even with making the new /boot
the actual /boot
), but
clearly I can just look up the UUIDs by hand.
PS: no, I don't know why Grub2 and grub.cfg
don't have a final
fallback of 'where you got the grub.cfg from'. Probably it's for the
same reason that Grub2 needs a shell script interpreter.