Monday, May 17, 2010

Customizing grub, Part 2

In the last post, I talked about the general approach to customizing grub. Now I'll get into the details fix up those messy grub menus.

First, before mucking inside the config files, I'd like to change the order of the menu; I think that memtest should be after the other OS entries, so I'll run

$ sudo mv /etc/grub.d/20_memtest86+ \

Next, I hate how the entries in the boot menu are really bloated and non-user-friendly. I mean, when I'm choosing between Jaunty and Karmic and Lucid, I might not remember that kernel 2.6.31-21 is for Karmic. In any case, the menu entry format is ugly and I want to clean that up.

Let's do 30_os-prober first. That's the easier one. Scanning the file tells me that it chops up the output from os-prober and linux-boot-prober to build the menu entries. Let's run them to see what kind of stuff they spit out.

$ sudo os-prober
/dev/sda1:Windows 7 (loader):Windows:chain
/dev/sda3:Ubuntu 9.10 (9.10):Ubuntu:linux
$ sudo linux-boot-prober /dev/sda3
/dev/sda3:/dev/sda3:Ubuntu, Linux 2.6.31-21-generic:/boot/vmlinuz-2.6.31-21-generic:/boot/initrd.img-2.6.31-21-generic:root=UUID=d97e0b98-5e2e-4d91-9968-ee9f206eed3a ro quiet splash
/dev/sda3:/dev/sda3:Ubuntu, Linux 2.6.31-21-generic (recovery mode):/boot/vmlinuz-2.6.31-21-generic:/boot/initrd.img-2.6.31-21-generic:root=UUID=d97e0b98-5e2e-4d91-9968-ee9f206eed3a ro single

All the info is there, so all we have to do is chop it up and stick it back together differently. I want my menu entries from 30_os-prober to look like this:

Windows 7
Ubuntu 9.10 (2.6.31-21-generic)
Ubuntu 9.10 (2.6.31-21-generic, recovery mode)

instead of like this:

Windows 7 (loader) (on /dev/sda1)
Ubuntu, Linux 2.6.31-21-generic (on /dev/sda3)
Ubuntu, Linux 2.6.31-21-generic (recovery mode) (on /dev/sda3)

So, I'm going to use cut and sed. The man page for cut is good enough get a feel for it; cut is a tiny program. Not so for sed, especially if you don't know regular expressions yet. Bruce Barnett has some good info on sed and regular expressions.

To get a nice, clean string containing the OS name, just change the line that sets LONGNAME. Unmodified, LONGNAME holds the name of the OS like "Windows 7 (loader)" and "Ubuntu 9.10 (9.10)", which is rather bloated and ugly. So, we will cut off the stuff that matches the space, open-parenthesis, and anything afterwards:

DEVICE="`echo ${OS} | cut -d ':' -f 1`"   # no change; just for bearings
LONGNAME="`echo ${OS} | cut -d ':' -f 2 | tr '^' ' ' | sed 's/ (.*$//'`"

That alone will fix the entry for Windows.

The Linux entry takes a bit more advanced hacking, because I want to display three bits of info:
  1. the OS name
  2. the kernel version
  3. whether this is a recovery kernel image
Right now, I can only check off number 1. To get the kernel version, we'll make a new variable:

LKERNEL="`echo ${LINUX} | cut -d ':' -f 4`"
LKERNELVERSION="`echo ${LKERNEL} | sed 's/^[^0-9]*\(.*$\)/\1/'`"

That will give a string like "2.6.31-21-generic". Yay! Number 2 is checked off.

For number 3 (is this a recovery image?) we'll use grep in the if-statement below. After the fi, we'll build the string for the menu entry.

LKERNELVERSION="`echo ${LKERNEL} | sed 's/^[^0-9]*\(.*$\)/\1/'`"  # added in previous step by Chaim Leib
if [ "`echo ${LINUX} | grep 'recovery'`" ] ; then
  LRECOVERY=", recovery mode"


Next post, I'll be showing how to modify 10_linux, so that the main boot entry is cleaned up as well! See you next time!

No comments:

Post a Comment