Remove Old Kernels In Ubuntu With One Command

October 2, 2010 by
Filed under: command line, HowTo, linux, Ubuntu 

A while back I wrote a post on how to remove old kernels from your Ubuntu system. While that process works just fine, it is a four step process. One person who read that post left a comment with a nice command line one-liner that removes all but the currently running kernel. And while that one-liner works quite well, I must admit that I don't understand all the regular expressions used in it, so I decided to try and come up with my own one-liner to remove the old kernels from my system.

I'm going to take you through this step by step so you can see how the individual commands in this one-liner tie together. If you're impatient, you can skip to the end to see the final command.

Step 1) List all packages that start with "linux-"

We'll use the dpkg command with the -l switch to list the packages, whether installed or not, that start with the string linux-.

dpkg -l linux-*

Step 2) Filter that list to show only installed packages

To filter the list, I'm going to pipeline the output of the first command into the awk command. I'm also going to use awk to filter out everything but the package names.

dpkg -l linux-* | awk '/^ii/{ print $2 }'

Step 3) Filter out packages for the currently running kernel

OK, so now I'm down to a pretty limited number of packages, but I don't want to remove the packages for my currently running kernel. I'm going to use a few commands to do that. First off, I can determine my currently running kernel with the uname -r command. Currently on my system that command outputs: 2.6.32-25-generic.

To do my package filtering, I only want the numeric portion of that output. I'll pipeline the output of uname -r and use the cut command with a hyphen as the field delimiter. I'll cut fields 1 & 2.

uname -r | cut -f1,2 -d"-"

Now I'm going to use this result as the filter for a grep command. In Linux, to use the result of one command as an argument in another command, you enclose the command in single back-quotes ( ` that's the key to the left of the 1 on a standard US keyboard). So here's my one-liner so far.

dpkg -l linux-* | awk '/^ii/{ print $2}' | grep -v -e `uname -r | cut -f1,2 -d"-"`

This is the output so far on my system:

linux-firmware
linux-generic
linux-headers-2.6.32-24
linux-headers-2.6.32-24-generic
linux-headers-generic
linux-image-2.6.32-24-generic
linux-image-generic
linux-libc-dev
linux-sound-base

Step 4) Filter the list for only the kernel packages

So now I have a package list that excludes the packages for my current kernel. The only packages from the list above that I want to remove are: linux-headers-2.6.32-24, linux-headers-2.6.32-24-generic, linux-image-2.6.32-24-generic.

What makes these packages unique from the others in the list is that they all contain numbers. So I can use grep again to filter the list down to only packages with numbers in their names. I'll pipeline the output of the previous command into grep -e [0-9].

dpkg -l linux-* | awk '/^ii/{ print $2}' | grep -v -e `uname -r | cut -f1,2 -d"-"` | grep -e [0-9]

So now the output on my system is only the following:

linux-headers-2.6.32-24
linux-headers-2.6.32-24-generic
linux-image-2.6.32-24-generic

Step 5) Putting it all together: Removing the packages

So now that I have a good list of packages I can use another pipe and the xargs command to invoke apt-get to remove the packages. First I'm going to show it using the --dry-run switch with apt-get. That way you can give it a try without actually changing your system.

dpkg -l linux-* | awk '/^ii/{ print $2}' | grep -v -e `uname -r | cut -f1,2 -d"-"` | grep -e [0-9] | xargs sudo apt-get --dry-run remove

If everything looks good after the dry run, you can go ahead and remove the old kernels with:

dpkg -l linux-* | awk '/^ii/{ print $2}' | grep -v -e `uname -r | cut -f1,2 -d"-"` | grep -e [0-9] | xargs sudo apt-get -y purge

So there you have it. One command, albeit a long one, to remove the old kernels from your Ubuntu system. I imagine the same command should work on other Debian based systems as well, but I've only tested this on my 32 bit system. I'd be interested to know if it works just as well on a 64 bit system.

Comments

56 Responses to “Remove Old Kernels In Ubuntu With One Command”

  1. There's a simpler way: Remove all but the bare necessary: You can add a plus (+) behind the packages you want to keep:

    First get your kernel type:

    ktype=$(uname -r | sed 's/.*-\(generic\|i386\|server\|common\|rt\|xen\|ec2\)/\1/')

    If you already know your kernel typ, you may set it directly, e.g.:

    ktype=generic

    Then use the variable "ktype" to remove everything but the actual kernel image:


    sudo apt-get remove --purge 'linux-(headers|image)-.*' linux-image-$(uname -r)+ linux-image-$ktype+ linux-$ktype+

    If you need the headers, keep them too:


    sudo apt-get remove --purge 'linux-(headers|image)-.*' linux-headers-$(uname -r)+ linux-headers-$(uname -r | sed s/-$ktype//)+ linux-headers-$ktype+ linux-image-$(uname -r)+ linux-image-$ktype+ linux-$ktype+

    • Linerd says:

      My current kernel = 3.2.0-29-generic

      Using a dry run with your first command gives on my system

      Remv linux-headers-3.2.0-23-generic [3.2.0-23.36]
      Remv linux-headers-3.2.0-23 [3.2.0-23.36]
      Remv linux-headers-3.2.0-24-generic [3.2.0-24.39]
      Remv linux-headers-3.2.0-24 [3.2.0-24.39]
      Remv linux-headers-3.2.0-25-generic [3.2.0-25.40]
      Remv linux-headers-3.2.0-25 [3.2.0-25.40]
      Remv linux-headers-3.2.0-26-generic [3.2.0-26.41]
      Remv linux-headers-3.2.0-26 [3.2.0-26.41]
      Remv linux-headers-3.2.0-27-generic [3.2.0-27.43]
      Remv linux-headers-3.2.0-27 [3.2.0-27.43]
      Remv nvidia-current [295.40-0ubuntu1.1]
      Remv linux-headers-generic [3.2.0.29.31]
      Remv linux-headers-3.2.0-29-generic [3.2.0-29.46]
      Remv linux-headers-3.2.0-29 [3.2.0-29.46]
      Remv linux-image-3.2.0-23-generic [3.2.0-23.36]
      Remv linux-image-3.2.0-24-generic [3.2.0-24.39]
      Remv linux-image-3.2.0-25-generic [3.2.0-25.40]
      Remv linux-image-3.2.0-26-generic [3.2.0-26.41]
      Remv linux-image-3.2.0-27-generic [3.2.0-27.43]

      So I would lose my current kernel headers and for some reason, my nvidia driver. I don't want to lose my nvidia driver.

      Whereas a dry run with my command gives on my system

      Remv linux-headers-3.2.0-23-generic [3.2.0-23.36]
      Remv linux-headers-3.2.0-23 [3.2.0-23.36]
      Remv linux-headers-3.2.0-24-generic [3.2.0-24.39]
      Remv linux-headers-3.2.0-24 [3.2.0-24.39]
      Remv linux-headers-3.2.0-25-generic [3.2.0-25.40]
      Remv linux-headers-3.2.0-25 [3.2.0-25.40]
      Remv linux-headers-3.2.0-26-generic [3.2.0-26.41]
      Remv linux-headers-3.2.0-26 [3.2.0-26.41]
      Remv linux-headers-3.2.0-27-generic [3.2.0-27.43]
      Remv linux-headers-3.2.0-27 [3.2.0-27.43]
      Remv linux-image-3.2.0-23-generic [3.2.0-23.36]
      Remv linux-image-3.2.0-24-generic [3.2.0-24.39]
      Remv linux-image-3.2.0-25-generic [3.2.0-25.40]
      Remv linux-image-3.2.0-26-generic [3.2.0-26.41]
      Remv linux-image-3.2.0-27-generic [3.2.0-27.43]

      Your final command gives the same result as mine.

      Does the "+" notation tell apt-get to install the package rather than remove it? I'm not familiar with that option.

      • Linerd says:

        OK, I found it in the man page:

        If a plus sign is appended to the package name (with no intervening space), the identified package will be installed instead of removed.

  2. Gniourf says:

    With bash (don't know/care about other shells), it's better to quote the * in the dpkg command, to avoid an unwanted glob, just in case a file linux-something exists:
    dpkg -l linux-'*'

  3. Salocin.TEN says:

    Seems to work in the 64 bit PAE version as well! Thanks for the awesomeness!

  4. Sriram Rangan says:

    Amazing, I was really sleepy and this was just what I was looking for. Good job mate.

  5. John M says:

    Thanks very much. I needed this to remotely clear space from /boot on a remote PC using ssh. It worked a treat!

  6. I just had to cleanup my netbook and added a blog with more background info and a simpler command on my page; I'll keep that up to date when I find a newer or better way:

    http://marc.waeckerlin.org/computer/blog/remove_all_old_kernel_images_in_ubuntu

  7. Bruno says:

    Works great, Ubuntu 12.04 LTS 64 bits. Thanks!

  8. Works great in Ubuntu 12.04.1 LTS 32 bits as well. Thanks for adding a step wise tutorial, with details about each step. Great way to learn things. Kudos.

  9. Ed Holcroft says:

    This worked great on all my Ubuntu 12.04 64-bit servers on AWS. Thanks.

  10. a2461895 says:

    Beware of what you're doing if using this.
    This method is not fool-proof.
    On my system it wants to remove linux-libc-dev:amd64 too, which is a bad idea.

    Yes, it works on on 32-bits systems as the author already wrote, but I'm not so sure about 64-bits systems. There might be other packages that also meet the requirements and that are removed unexpectedly.

  11. Patrick says:

    Hi Guys
    I get this error when using this
    E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).

    This may be because it failed to install correctly as the /boot is 100% full can you repost the solution showing where you would put just the one image to remove in order to clean space so i can run it again please
    Many thanks

    • Linerd says:

      This post shows a more manual way of removing old kernels, if that's what you're looking for:
      http://tuxtweaks.com/2009/12/remove-old-kernels-in-ubuntu/

      • Patrick says:

        Hi Linerd
        That worked a treat thanks. My problem was an incomplete linux header update to 3.2.0-34 due to not enough space and everything i did failed because of this. With the old solution i was able to remove older versions one at a time and create the space to complete the update and remove all of the old ones with your in one command

        Many thanks it was very much appreciated

  12. Nate says:

    Thanks for not only sharing the command, but the logic behind it.

  13. Mark Preston says:

    Today, after 24 months of having old kernels pile up in /sda3 to the point that the OS failed, this post has removed the outdated kernels, and I have recovered 3 gig. Thank you very very much.

  14. Konstantin says:

    Did not work well on Ubuntu 12.10 (64bit) - it wanted to lot of extra things:

    Feb 22, 11:27:02> dpkg -l linux-* | awk '/^ii/{ print $2}' | grep -v -e `uname -r | cut -f1,2 -d"-"` | grep -e [0-9] | xargs sudo apt-get --dry-run remove
    Reading package lists... Done
    Building dependency tree
    Reading state information... Done
    The following packages were automatically installed and are no longer required:
    lib32z1 libavahi-client-dev libavahi-common-dev libgnutls-openssl27 libgnutlsxx27 libgpg-error-dev libidn11-dev libieee1284-3-dev libjbig-dev libkadm5clnt-mit8 libkadm5srv-mit8 liblzma-dev libp11-kit-dev libsensors4-dev libsnmp-perl libtasn1-3-dev libtiffxx5
    libusb++-0.1-4c2 libv4l-dev libwrap0-dev ncurses-term pax
    Use 'apt-get autoremove' to remove them.
    The following packages will be REMOVED:
    build-essential comerr-dev g++ g++-4.4 g++-4.7 google-earth-stable krb5-multidev libc6-dev libcups2-dev libcupsimage2-dev libcurl4-nss-dev libexif-dev libexpat1-dev libgcrypt11-dev libgnutls-dev libgphoto2-2-dev libjpeg-dev libjpeg-turbo8-dev libjpeg8-dev
    libkrb5-dev libmysqlclient-dev libncurses5-dev libpcre3-dev libperl-dev libpng12-dev librtmp-dev libsane-dev libsnmp-dev libsqlite3-dev libssl-dev libstdc++6-4.4-dev libstdc++6-4.7-dev libtiff5-dev libtool libusb++-dev libusb-1.0-0-dev libusb-dev linux-generic
    linux-headers-3.5.0-23 linux-headers-3.5.0-23-generic linux-headers-3.5.0-25 linux-headers-3.5.0-25-generic linux-headers-generic linux-image-3.5.0-17-generic linux-image-3.5.0-18-generic linux-image-3.5.0-19-generic linux-image-3.5.0-21-generic
    linux-image-3.5.0-22-generic linux-image-3.5.0-23-generic linux-image-3.5.0-25-generic linux-image-extra-3.5.0-17-generic linux-image-extra-3.5.0-18-generic linux-image-extra-3.5.0-19-generic linux-image-extra-3.5.0-21-generic linux-image-extra-3.5.0-22-generic
    linux-image-extra-3.5.0-23-generic linux-image-extra-3.5.0-25-generic linux-image-generic linux-libc-dev lsb-core python-dev python2.7-dev ruby-dev ruby1.8-dev ruby1.9.1-dev zlib1g-dev
    0 upgraded, 0 newly installed, 66 to remove and 0 not upgraded.
    Remv build-essential [11.5ubuntu3]
    Remv libcurl4-nss-dev [7.27.0-1ubuntu1.1]
    Remv libcupsimage2-dev [1.6.1-0ubuntu11.3]
    Remv libcups2-dev [1.6.1-0ubuntu11.3]
    Remv libkrb5-dev [1.10.1+dfsg-2]
    Remv krb5-multidev [1.10.1+dfsg-2]
    Remv comerr-dev [2.1-1.42.5-1ubuntu2]
    Remv g++ [4:4.7.2-1ubuntu2]
    Remv libusb++-dev [2:0.1.12-23]
    Remv g++-4.4 [4.4.7-2ubuntu1] [libstdc++6-4.4-dev:amd64 ]
    Remv libstdc++6-4.4-dev [4.4.7-2ubuntu1]
    Remv g++-4.7 [4.7.2-2ubuntu1] [libstdc++6-4.7-dev:amd64 ]
    Remv libstdc++6-4.7-dev [4.7.2-2ubuntu1]
    Remv google-earth-stable [6.0.3.2197-r0]
    Remv ruby-dev [4.9]
    Remv ruby1.9.1-dev [1.9.3.194-1ubuntu1.3]
    Remv ruby1.8-dev [1.8.7.358-4ubuntu0.1]
    Remv lsb-core [4.0-0ubuntu26.1]
    Remv libsane-dev [1.0.23-0ubuntu1]
    Remv libtiff5-dev [4.0.2-1ubuntu2.1]
    Remv libsnmp-dev [5.4.3~dfsg-2.5ubuntu1]
    Remv libperl-dev [5.14.2-13ubuntu0.1]
    Remv librtmp-dev [2.4+20111222.git4e06e21-1]
    Remv libgnutls-dev [2.12.14-5ubuntu4.1]
    Remv python-dev [2.7.3-0ubuntu7]
    Remv python2.7-dev [2.7.3-5ubuntu4]
    Remv libssl-dev [1.0.1c-3ubuntu2.1]
    Remv libmysqlclient-dev [5.5.29-0ubuntu0.12.10.1]
    Remv libpng12-dev [1.2.49-1ubuntu1]
    Remv zlib1g-dev [1:1.2.7.dfsg-13]
    Remv libgphoto2-2-dev [2.4.14-2]
    Remv libusb-dev [2:0.1.12-23]
    Remv libusb-1.0-0-dev [2:1.0.12-2]
    Remv libtool [2.4.2-1ubuntu2]
    Remv libsqlite3-dev [3.7.13-1]
    Remv libpcre3-dev [1:8.30-5ubuntu1]
    Remv libgcrypt11-dev [1.5.0-3ubuntu1]
    Remv libexpat1-dev [2.1.0-1ubuntu1]
    Remv libexif-dev [0.6.20-3]
    Remv libncurses5-dev [5.9-10ubuntu1]
    Remv libjpeg-dev [8c-2ubuntu7]
    Remv libjpeg8-dev [8c-2ubuntu7]
    Remv libjpeg-turbo8-dev [1.2.1-0ubuntu2]
    Remv libc6-dev [2.15-0ubuntu20]
    Remv linux-generic [3.5.0.25.31]
    Remv linux-headers-3.5.0-23-generic [3.5.0-23.35]
    Remv linux-headers-3.5.0-23 [3.5.0-23.35]
    Remv linux-headers-generic [3.5.0.25.31]
    Remv linux-headers-3.5.0-25-generic [3.5.0-25.38]
    Remv linux-headers-3.5.0-25 [3.5.0-25.38]
    Remv linux-image-extra-3.5.0-17-generic [3.5.0-17.28]
    Remv linux-image-3.5.0-17-generic [3.5.0-17.28]
    Remv linux-image-extra-3.5.0-18-generic [3.5.0-18.29]
    Remv linux-image-3.5.0-18-generic [3.5.0-18.29]
    Remv linux-image-extra-3.5.0-19-generic [3.5.0-19.30]
    Remv linux-image-3.5.0-19-generic [3.5.0-19.30]
    Remv linux-image-extra-3.5.0-21-generic [3.5.0-21.32]
    Remv linux-image-3.5.0-21-generic [3.5.0-21.32]
    Remv linux-image-extra-3.5.0-22-generic [3.5.0-22.34]
    Remv linux-image-3.5.0-22-generic [3.5.0-22.34]
    Remv linux-image-extra-3.5.0-23-generic [3.5.0-23.35]
    Remv linux-image-3.5.0-23-generic [3.5.0-23.35]
    Remv linux-image-generic [3.5.0.25.31]
    Remv linux-image-extra-3.5.0-25-generic [3.5.0-25.38]
    Remv linux-image-3.5.0-25-generic [3.5.0-25.38]
    Remv linux-libc-dev [3.5.0-25.38]

    • Linerd says:

      What listing do you get if you just enter to portion prior to the xargs command?

      dpkg -l linux-* | awk '/^ii/{ print $2}' | grep -v -e `uname -r | cut -f1,2 -d"-"` | grep -e [0-9]

      I've also documented a more manual way if you want to try that: http://tuxtweaks.com/2009/12/remove-old-kernels-in-ubuntu/

    • Matt says:

      I saw the same behavior and the problem is caused by the naming of the linux-libc-dev package. I fixed the problem by changing the command dpkg -l linux-* to dpkg -l linux-headers* -l linux-image*.

      The full command would be dpkg -l linux-headers* -l linux-image* | awk '/^ii/{ print $2}' | grep -v -e `uname -r | cut -f1,2 -d"-"` | grep -e [0-9] | xargs sudo apt-get remove

  15. Edgar Cheetham says:

    I have used your technique to remove old kernels and it has worked quite well in he past, and I thank you for that. However now, after upgrading from linux-headers-2.6.32-45 (2.6.32-45.103) to 2.6.32-45.104, when I type:
    :~$ dpkg -l linux-*
    I get this:
    No packages found matching linux-3.7.1.
    No packages found matching linux-3.8.0.
    What gives?

  16. John K says:

    Found this page when I needed to do some clean up on my system which was very helpful. I did make a change for filtering the package list that I would like to pass on:

    dpkg -l | awk --assign=mykernel=$(uname -r) '$2 ~ mykernel{next}$2 ~ /^linux-image-[0-9]/ || $2 ~ /^linux-headers-[0-9]/{print $2}' | xargs sudo apt-get -y purge

  17. [...] was able to fix it with a command written by Linerd.  He did a very nice job explaining it, so I would recommend that you follow through and read his [...]

  18. Larry says:

    This worked fine on a 64 bit system. no issues.

  19. Jay Fude says:

    Still works, 12.10 and linux mint (debian) on a 64 bit system.

Leave a 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> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>