DEV Community

Cover image for Journey towards a maintenance free system multi booting
suntong
suntong

Posted on • Updated on

Journey towards a maintenance free system multi booting

Problem statement and goal

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.

Although 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,

Remove the "Advanced options"

Let's take a look how big my grub.cfg file is:

$ wc /boot/grub/grub.cfg
  355  1338 15006 /boot/grub/grub.cfg
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

The file size almost dropped in half and now is under 200 lines.

Remove the unnecessary if conditions

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?

These if conditions are second that need to go. After that, a single boot entry will look like:

Remove the unnecessary module loading

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:

A little help please

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:

Toward maintenance free booting

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:

Maintenance free, at last!

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:

The probe -u $root --set=rootuuid line will set the $rootuuid variable, then it get passed to the next linux /vmlinuz line.

Hooray~~, problem solved!!

One step further

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.

Summary of the journey

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.

Conclusion

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.

Discussion (0)