Removing old kernels from Ubuntu

Run an Ubuntu system long enough, and you’ll eventually have a large number of kernels installed. These don’t cause any harm, but they do take up disk space and appear in the GRUB menu at boot. So every now and again, I take a moment and purge the old kernels.

When you have just one system, this is easy. Just list all packages with dpkg -l or a graphical manager like Synaptic, and mark the old ones for removal.

But there are some gotchas. Don’t remove the currently-running kernel. It would be bad. Also don’t remove the latest kernel. That’s the one you want to be running.

So when cleaning up, you must carefully pick all the kernels, modules, and headers you want to purge. It is tiresome to do this by hand more than once. So I wrote a bash macro to do it for me. Just paste this into the shell:

This code does the following:

  1. Find the version of the newest (highest-numbered) kernel
  2. Find the version of the currently-running kernel
  3. List all kernel images, modules, and headers
  4. Exclude everything matching the newest or current kernel versions
  5. Use apt-get to purge all the rest

Update 2012-09-06: The code to find KERNEL_HIGHEST was wrong. It gave incorrect results when version numbers increase in order of magnitude (such as from 3.2.0-9 to 3.2.0-10), and had problems with beta kernels (such as linux-image-3.3.0-030300rc2-generic). This could cause one old kernel to be retained, or the newest kernel to be removed, as long as it wasn’t the running kernel. The bug is now fixed. Thanks to Dean Henrichsmeyer at Canonical for providing feedback.

Update 2012-11-29: The above command only works on Ubuntu 10.04 and later. Prior to this release, sort is missing the -V switch to sort by version number.

Tags: ,

  1. The Open Sourcerer’s avatar

    Thanks very much for this.

    It’s something that had bugged me for ages and since I saw your post I have used it loads of times to rescue systems that had:

    * No inodes left because of loads of header dirs in /usr/src
    * No space in /boot because of loads of old vmlinuz images

    It’s a real help.

    Thanks again.

    Al

    Reply

    1. Tyler Wagner’s avatar

      Al,

      Please note that my code was flawed. Please see the update.

      Reply

    2. The Open Sourcerer’s avatar

      Thanks for the ping about the update.

      I hadn’t been affected by it [yet] ;-)

      Al

      Reply

    3. Dragonslayr’s avatar

      Would you mind much to let me know what to add to leave the last three kernels? Removing kernels makes me nervous. :)

      I did put this at the end to tell me what was now installed..
      dpkg –get-selections | grep linux-image ;\

      Reply

      1. Tyler Wagner’s avatar

        Sorry, you’ll have to build your own enormous one-liner for that. :)

        Reply

        1. Mike’s avatar

          Just add another line to define a third variable which tails the last two kernels found, then pluck out the first line only using head -n 1 on the result:

          KERNEL_2ND_HIGHEST=$(dpkg -l 'linux-image-[0-9.]*-[0-9]*-[a-zA-Z0-9]*' | grep ^ii | awk '{print $2}' | sort -V | tail -n 2 | head -n 1| sed 's/^linux-image-\([0-9.]*-[0-9]*\)-.*$/\1/') ; \

          then add this new variable to your sed delete command:

          sed "/$KERNEL_CURRENT/d;/$KERNEL_HIGHEST/d;/$KERNEL_2ND_HIGHEST/d"

          Reply

          1. Tyler Wagner’s avatar

            Thanks, Mike. I actually do this with Python now, which makes things like “retain x kernels” much easier. But it’s hard to beat Bash for pasting into a terminal.

            Reply

            1. Mike’s avatar

              Or dumping into a cronjob ;-)
              How’s your python solution work?

              Reply

              1. Tyler Wagner’s avatar

                My Python solution is ag, a script I usually install as /usr/local/bin/ag. Reading it over, I could modify it to create a list of versions to retain by sorting and trimming the list. If you do, please provide a patch.

                Reply

Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">