This article tries to simply the situation for people who dual boot/multi boot their computer systems, be them Debian, Mint, Arch, Fedora, openSUSE, etc, or Windows.
For multi booting all the operation systems, I have a standalone boot partition as well as an UEFI ESP partition. From there, any operation systems on my disk can be booted. A Debian boot entry looks like this:
Let me stress again that this is just one single entry. There are also several "Advanced options" that goes with each Linux system, so my multi-boot
grub.cfg file looks scary, because it is humongous. But that's not the only problem.
Problem #1: Because it is in a standalone boot partition, I normally don't need to mount it, but whenever I got my kernel manually or automatically upgraded, I have to remember to mount this partition and update the boot entries there. Otherwise,
- I will not be able to boot up my system again, if the old kernels are somehow/automatically purged.
- I will not be able to take advantage of the new kernel, even if they have been installed.
Problem #2: I like to bring my
40_custom up to the top of my menu selection, instead of down at the bottom.
Problem #3: I like to order my boot entries in the order I want, instead of being determined by their partition orders.
grub can generate boot entries automatically, all above problem are blind spots of
grub, and you have to come up with your own ways of dealing with them.
The good news is that the
grub.cfg file does not have to be so humongous, scary, and messy. At the end of this article, you'll find that things can be pretty simple. Scroll to the bottom to see if you don't want to go through the discovery journey that leads towards it. I.e. you'll find that
Things can be so simple that people can start writing/maintaining the grub boot menu by hands now. And in the next blog, we can see that things can be even more simpler, with the help of easygen.
Let the journey begin -- we'll going to go through a series of steps to simplify the
grub.cfg file so that in the end, they can be edited manually. Now, step number one,
Let's take a look how big my
grub.cfg file is:
$ wc /boot/grub/grub.cfg 355 1338 15006 /boot/grub/grub.cfg
Over 350 lines! Let's first simplify the
grub.cfg file by remove the "Advanced options" menu entries, as I've been using Linux for over 20 years, and not a single chance had I ever need to dip into those options. Moreover, the grub menu can be easily edited if I want, say to boot into single mode. They can go for sure:
$ sed '/^submenu .Advanced options for /,/^}/d' /boot/grub/grub.cfg | wc 183 581 5602
The file size almost dropped in half and now is under 200 lines.
Look at the following lines in the above posted grub boot menu:
Has anyone ever wondering what it is doing?
Well, it turns out that
the conditional code checking for this feature is pointless in all modern Linux distributions
So why still keep it around?
if conditions are second that need to go. After that, a single boot entry will look like:
Now, why are there so many
insmod statements in each boot entry? My computer contains either Linux or Windows, and they reside all in GPT, as ext4 partitions. I.e.,
All my Linux will need the same modules, so it doesn't make sense to repeat every one of them in each individual boot entry.
Can I load all the modules I need only once at the beginning, and save each individual boot entries from repeating themselves?
It turns out that I can. So now my Linux boot entry looks like this:
It'll be tedious to go through each boot entry and do the above clean up, so a little help from a script will definitely be the way to go, and here it is:
Now it is time to tackle Problem #1 -- whenever my kernel is upgraded, I don't want to
- mount my boot partition, and
- update the boot entries there
I want my boot partition's boot entries to be able to survive such change and always boot to the latest kernel, whatever they are. Is that possible? Well,
It sure can, using the trick like this:
Look at the
linux /vmlinuz line, there is still a
root=UUID=xxx parameter there. Now what if I reformat the partition and install a new Linux? The
UUID will surely change and the above boot entry will surely not be able to survive such change.
This hurdle is the most difficult of all. Luckily someone has already looked into such problem, but sadly, nobody else even care, judging from the up-votes from the SO question and answer. Anyway, here, the prestige of the whole article, here is the solution:
probe -u $root --set=rootuuid line will set the
$rootuuid variable, then it get passed to the next
linux /vmlinuz line.
Hooray~~, problem solved!!
Now, take a closer look at the
search --no-floppy --fs-uuid ... line.
What does it do?
It actually set the
$root grub variable according to a fixed
UUID value on that line, and therefore change the boot partition, which will undermine the whole effort of our above attempt.
That will surely need to go away.
The above discovery journey was a step by step one and it has been logged here:
The boot entries were build from the ground up and move step by step to the top. All entries are verified to be working fine.
Once upon a time, people write their own boot menu. But
grub2 came alone and people just gave up such practice and rely solely on the machine.
The journey in this article show that things do not have to be that way as the only way -- we can still write our own boot menu, just do not let the humongous file size scare you off, as a single boot menu entry now can be as simple as:
Most of which are boilerplate that don't need to be changed. I.e., the only things that matter are the
'Debian GNU/Linux' and the
'hd0,gpt2'. We don't need to hunt for the UUIDs, and we don't need to remember to mount boot partition and update the boot entries any more. It can boot to whatever latest kernel it is, and it will still work even we reformat the partition and install a new Linux, and it will still work even we change the distro from Debian, to Mint, Arch, Fedora, or openSUSE etc.
There are a few more boilerplates that need to be in place so that you can only write the above few lines and everything will work out magically, which will be covered in next article, with the help of easygen.