#howmany for grub 2
Tags grub2 howmany
I don't really like the default behavior of Grub in Ubuntu to continue to add all the kernel updates to my grub boot menu. I never go back and use old kernels (except by mistake) and it just crowds up my boot menu.
In the past, I have used the #howmany option in /boot/grub/menu.lst to limit this to only the most recent kernel. Now that I am using Karmic Koala though, this option no longer appears to be available due to the fact that the default bootloader is now Grub 2.
The general recommendations I am seeing on the internet for users who would like the #howmany functionality are to either comment out the entries in /boot/grub/grub.cfg or manually remove old kernel packages using aptitude. This means that every time a kernel is updated, I either have to manually comment out more and more lines from the grub.cfg file despite many warnings not to edit that file directly, or go into aptitude and find and uninstall the old "linux-image" packages.
I decided to try and add support back in for the #howmany option by adding a GRUB_HOWMANY variable to /etc/defaults/grub. This turned out to be fairly simple.
Make backups of your original files before editing them. Issue the following commands to make the backups:
(the chmod is there because any scripts in the grub.d directory will be executed during an "update-grub", so the 10_linux_backup file might be executed after the 10_linux script, meaning that the original file would be used instead of our modified script and no changes would be observed. Make it non-executable and it won't be seen as a script).
First, I edited the /usr/sbin/grub-mkconfig file and added GRUB_HOWMANY to the list of optional, user-defined variables being exported as shown below:
Then I added some logic to /etc/grub.d/10_linux to check and see if GRUB_HOWMANY is a number and if not, then convert it to zero. By the way, I had not noticed that the file was being run in the "dash" shell instead of the "bash" shell, so my first version of the following line using native regular expressions didn't work at all.
then a "found" variable to keep track of how many kernels have been added to the menu
Last, I add a check to the while loop looping through kernels to stop after finding GRUB_HOWMANY (unless GRUB_HOWMANY is 0) and a line to increment $found each time
To set the number of kernels, add the following line to /etc/default/grub
where N is the number of kernels to set. In other words, use GRUB_HOWMANY=1 to show only the most recent kernel in the grub2 boot menu and GRUB_HOWMANY=2 to show two most recent kernels. To show all kernels, use GRUB_HOWMANY=0 or any non-numeric value such as GRUB_HOWMANY="ALL".
Finish by running
That's it. Now I get only the number of kernels I want, and I don't have to do anything after updating to a new kernel.
In the past, I have used the #howmany option in /boot/grub/menu.lst to limit this to only the most recent kernel. Now that I am using Karmic Koala though, this option no longer appears to be available due to the fact that the default bootloader is now Grub 2.
The general recommendations I am seeing on the internet for users who would like the #howmany functionality are to either comment out the entries in /boot/grub/grub.cfg or manually remove old kernel packages using aptitude. This means that every time a kernel is updated, I either have to manually comment out more and more lines from the grub.cfg file despite many warnings not to edit that file directly, or go into aptitude and find and uninstall the old "linux-image" packages.
I decided to try and add support back in for the #howmany option by adding a GRUB_HOWMANY variable to /etc/defaults/grub. This turned out to be fairly simple.
Make backups of your original files before editing them. Issue the following commands to make the backups:
Code:
sudo cp /usr/sbin/grub-mkconfig /usr/sbin/grub-mkconfig_backup sudo cp /etc/grub.d/10_linux /etc/grub.d/10_linux_backup sudo chmod a-x /etc/grub.d/10_linux_backup sudo cp /etc/defaults/grub /etc/defaults/grub_backup
First, I edited the /usr/sbin/grub-mkconfig file and added GRUB_HOWMANY to the list of optional, user-defined variables being exported as shown below:
Code:
# These are optional, user-defined variables. export GRUB_DEFAULT \ GRUB_HIDDEN_TIMEOUT \ GRUB_HIDDEN_TIMEOUT_QUIET \ GRUB_TIMEOUT \ GRUB_DISTRIBUTOR \ GRUB_CMDLINE_LINUX \ GRUB_CMDLINE_LINUX_DEFAULT \ GRUB_TERMINAL_INPUT \ GRUB_TERMINAL_OUTPUT \ GRUB_SERIAL_COMMAND \ GRUB_DISABLE_LINUX_UUID \ GRUB_DISABLE_LINUX_RECOVERY \ GRUB_GFXMODE \ GRUB_DISABLE_OS_PROBER \ GRUB_HOWMANY
Code:
if [ "x${GRUB_HOWMANY}" = "x" ] || ! [ "x`echo ${GRUB_HOWMANY} | sed 's/^[0-9]\+\(\.[0-9]\+\)\?$//'`" = "x" ] ;then GRUB_HOWMANY=0 fi
Code:
found=0
Code:
while ( [ "x$list" != "x" ] && ( [ "${GRUB_HOWMANY}" -eq "0" ] || [ "$found" -lt "${GRUB_HOWMANY}" ] )); do found=$(( found + 1 ));
Code:
GRUB_HOWMANY=N
Finish by running
Code:
sudo update-grub
Total Comments 1
Comments
-
Here is the full text of my /etc/grub.d/10_linux file:
Code:#! /bin/sh -e # grub-mkconfig helper script. # Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. # # GRUB is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # GRUB is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GRUB. If not, see <http://www.gnu.org/licenses/>. prefix=/usr exec_prefix=${prefix} libdir=${exec_prefix}/lib . ${libdir}/grub/grub-mkconfig_lib echo "libdir=$libdir"; if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then OS=GNU/Linux else OS="${GRUB_DISTRIBUTOR}" fi # loop-AES arranges things so that /dev/loop/X can be our root device, but # the initrds that Linux uses don't like that. case ${GRUB_DEVICE} in /dev/loop/*|/dev/loop[0-9]) GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"` # We can't cope with devices loop-mounted from files here. case ${GRUB_DEVICE} in /dev/*) ;; *) exit 0 ;; esac ;; esac if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \ || [ "`grub-probe -t abstraction --device ${GRUB_DEVICE} | sed -e 's,.*\(lvm\).*,\1,'`" = "lvm" ] ; then LINUX_ROOT_DEVICE=${GRUB_DEVICE} else LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} fi # add crashkernel option if we have the required tools if [ -x "/usr/bin/makedumpfile" ] && [ -x "/sbin/kexec" ]; then GRUB_CMDLINE_EXTRA="$GRUB_CMDLINE_EXTRA crashkernel=384M-2G:64M,2G-:128M" fi linux_entry () { cat << EOF menuentry "$1" { recordfail=1 if [ -n \${have_grubenv} ]; then save_env recordfail; fi EOF if [ "x$3" = "xquiet" ]; then cat << EOF set quiet=1 EOF fi save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" cat << EOF linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro $2 EOF if test -n "${initrd}" ; then cat << EOF initrd ${rel_dirname}/${initrd} EOF fi cat << EOF } EOF } list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi done` found="0"; if [ "x${GRUB_HOWMANY}" = "x" ] || ! [ "x`echo ${GRUB_HOWMANY} | sed 's/^[0-9]\+\(\.[0-9]\+\)\?$//'`" = "x" ] ;then GRUB_HOWMANY=0 fi while ( [ "x$list" != "x" ] && ( [ "${GRUB_HOWMANY}" -eq "0" ] || [ "$found" -lt "${GRUB_HOWMANY}" ] )); do found=$((found + 1)); linux=`version_find_latest $list` echo "Found linux image: $linux" >&2 basename=`basename $linux` dirname=`dirname $linux` rel_dirname=`make_system_path_relative_to_its_root $dirname` version=`echo $basename | sed -e "s,^[^0-9]*-,,g"` alt_version=`echo $version | sed -e "s,\.old$,,g"` linux_root_device_thisversion="${LINUX_ROOT_DEVICE}" initrd= for i in "initrd.img-${version}" "initrd-${version}.img" \ "initrd-${version}" "initrd.img-${alt_version}" \ "initrd-${alt_version}.img" "initrd-${alt_version}"; do if test -e "${dirname}/${i}" ; then initrd="$i" break fi done if test -n "${initrd}" ; then echo "Found initrd image: ${dirname}/${initrd}" >&2 else # "UUID=" magic is parsed by initrds. Since there's no initrd, it can't work here. linux_root_device_thisversion=${GRUB_DEVICE} fi linux_entry "${OS}, Linux ${version}" \ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_EXTRA} ${GRUB_CMDLINE_LINUX_DEFAULT}" \ quiet if [ "x${GRUB_DISABLE_LINUX_RECOVERY}" != "xtrue" ]; then linux_entry "${OS}, Linux ${version} (recovery mode)" \ "single ${GRUB_CMDLINE_LINUX}" fi list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '` done
Posted 12-05-2009 at 10:36 PM by drask