LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Blogs > drask
User Name
Password

Notices


Rating: 4 votes, 4.75 average.

#howmany for grub 2

Posted 12-05-2009 at 08:46 PM by drask
Updated 12-05-2009 at 10:39 PM by drask

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:
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
(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:
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
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.
Code:
if [ "x${GRUB_HOWMANY}" = "x" ] || ! [ "x`echo ${GRUB_HOWMANY} | sed 's/^[0-9]\+\(\.[0-9]\+\)\?$//'`" = "x" ] ;then
  GRUB_HOWMANY=0
fi
then a "found" variable to keep track of how many kernels have been added to the menu
Code:
found=0
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

Code:
while ( [ "x$list" != "x" ] && ( [ "${GRUB_HOWMANY}" -eq "0" ] || [ "$found" -lt "${GRUB_HOWMANY}" ] )); do
  found=$(( found + 1 ));
To set the number of kernels, add the following line to /etc/default/grub

Code:
GRUB_HOWMANY=N
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
Code:
sudo update-grub
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.
Posted in Uncategorized
Views 26270 Comments 1
« Prev     Main     Next »
Total Comments 1

Comments

  1. Old Comment
    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 drask is offline
 

  



All times are GMT -5. The time now is 09:15 AM.

Main Menu
Advertisement
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration