Aesthetically editing grub.cfg

First, understand how Ubuntu configures Grub2.

  • /boot/grub/grub.cfg is the Grub2 menu
  • the update-grub command auto-generates that file
  • ...by reading default settings from /etc/defaults/grub
  • ...and running shellscripts in /etc/grub.d

So, if you don't want to edit grub.cfg after each kernel update, you want to tweak the scripts in /etc/grub.d so your changes get applied anytime update-grub is run.


Second, to answer your first question directly, I'm not familiar with any means of making specific boot options invisible but still accessible through the Grub menu. There are a lot of little things about Grub1 that didn't get reimplemented in Grub2, and it wouldn't surprise me if this was one of them.

Instead, you could make all the menu entries invisible (until highlighted) by setting the menu font color to the same as the background color. In /etc/grub.d/05_debian_theme, change menu_color_normal so that the first color (font) matches the second color (background). Leave menu_color_highlight different, so the entry under the cursor shows up.

# example from a likely-tweaked Karmic /etc/grub.d/05_debian_theme
set menu_color_normal=white/black
set menu_color_highlight=black/white

# ...to this
set menu_color_normal=black/black
set menu_color_highlight=black/white

Getting a separator into the Grub menu.

In Grub1 you'd insert a new entry like this. As I recall, you needed the root declaration to make it a valid menu entry, otherwise Grub1 ignored it.

# separator
title  --------------------
root

I suspect Grub2 might be similar. A very basic menu entry looks like this in grub.cfg:

# basic example
menuentry "Memory test (memtest86)" {
        linux   /boot/memtest86+.bin
}

Since "anything" in the double-quotes gets displayed as the title, you could fake a separator with that. Like Grub1, Grub2 wants the linux keyword to treat it as a real menu entry, so be careful you don't accidentally select it.

# a separator!  no, really!
menuentry "....." {
        linux   /boot/memtest86+.bin
}

Unfortunately, "anything" doesn't mean anything; while I was testing this I tried a long string of dashes ("----------------") and it never worked. But it likes the short string of dots shown above, so you can use that.

.....

Now, that's how to make one separator. To make a bunch, and to place them where you want them automatically, you need to add them into the scripts in /etc/grub.d.

For this example, let's put a simple separator between the various sections of grub.cfg. If you look at /etc/grub.d, you see the following scripts:

  • 00_header
  • 05_debian_theme
  • 10_linux - entries for Ubuntu kernels & recovery
  • 20_memtest86+ - entry for Memtest86+
  • 30_os-prober - entries for Windows & other Linux distros
  • 40_custom - nothing by default; special user entries can go here

We'll create a new script, separator, and place the following into it:

#!/bin/sh
# create a separator menu entry
cat << EOF
menuentry "....." {
  linux /boot/memtest86+.bin
}
EOF

Now, move that script into place for the first separator, and link it into place for the others. The scripts are executed in order, so if you want the first one to come before 10_linux, name it 09_separator or something.

cd /etc/grub.d

# start the editor, paste in the script above, save, and exit
sudo nano separator

# set executable
sudo chmod +x separator

# rename into the first position
mv separator 09_separator

# link into remaining positions (can also use cp)
ln -s 09_separator 19_separator
ln -s 09_separator 29_separator
# not really necessary since 40_custom is empty by default
ln -s 09_separator 39_separator

If you have a specific entry set as default in /etc/default/grub, you might need to update it -- Grub2 starts counting menu entries at 0, and each of these "separators" is a valid entry, so they count too. If your previous default entry was 0, and you've added one separator before it, remember to change GRUB_DEFAULT to 1

Now run update-grub, and examine /boot/grub/grub.cfg -- you should see the separators in there. If you do, reboot and check 'em out.

....

If you want to place separators elsewhere, say, between different kernel versions, you'll need to edit 10_linux (or another script) directly, and find the appropriate place to add the separator. You can use the lines from the script above; include everything except the first #!/bin/sh line.


If you want something prettier, use Grub splash images or themes. I need to give you a raincheck on those topics, but check the resources below.


Resources:

There are two big Grub2 guides on UbuntuForums that I've come to know and love:

  • The Grub 2 Guide (formerly Grub 2 Basics), which covers the basics, including Ubuntu-provided splash images and themes, and
  • Grub 2 Title Tweaks (or the I Don't Want It to Say "Microsoft Windows Vista Home Edition" Thread), which is a little more centered on tweaking certain scripts so the auto-generated grub.cfg shows more pleasant titles.
  • Also see the Grub 2 - 5 Common Tasks thread -- it's light on details but can get you started quickly.

GNU Grub 2 is another great resource. He's got a set of scripts for tweaking Karmic's Grub2 (full disclosure: I haven't tried them).

Grub Wiki's Theme Format page is a must for hacking on Grub2 themes.


Separator may be made of dashes if its first character is space. Also, it isn't necessary to use linux command for separator section, you may use any command like this:

menuentry " -----------------------------------------------------------" {
  echo "It is just a separator, select another item!"
}

Or even "true" to return silently:

menuentry " -----------------------------------------------------------" {
  true
}