Note to Self

Remove old kernels from Ubuntu Linux

Even if you run apt-get autoremove regularly, for some reason or another, old kernels will start to build up over time. To save space and to keep your machine clean, you may want to clean up occasionally.

The following steps could probably be automated, but since playing around with removing kernels may be dangerous, I prefer (for once) to do it manually.

Bring your system up-to-date

The first step is to make sure your system is up-to-date. For me, the sequence to do that (for which I do have a script, of course) is:

sudo apt-get update
sudo apt-get dist-upgrade -yuf 
sudo apt-get autoremove -y
sudo apt-get autoclean

Reboot

You may be prompted to reboot after this. Do it even if you are not, as you may be going to remove the kernel you are currently running. This may leave your machine in an unbootable state temporarily. Better not risk that.

Look which kernel you are running

Run uname -r and take note of the result. This is the kernel version you are running now.

Look which kernel-related packages you have installed

Run dpkg -l | egrep "^ii *linux-(headers|image|modules|tools)-[1-9]" . The kernel you are currently running should be the one with the highest version number.

Use apt-get (or your favourite tool) to remove everything that does not belong to the current kernel (or maybe also the one before that – to keep one older kernel is probably more superstition and hand-waving than actually useful but I do it anyway). Try to remove the old image packages all in one command, that should save same time as the boot structure needs to be re-built only once.

Look for left-over module directories

Finally, take a look at the /lib/modules directory. There may be sub-directories in there that belong to old kernel versions, for example if you had used VirtualBox on your version with older kernels, and additional files were put into these folders, so they were not deleted when the corresponding modules packages were removed. You can throw away everything that corresponds to kernels you just removed.

Script

Here is a script that tried to automate the identification process. It does not directly remove anything; it only tells you what you should do. One reason is that it doesn't really sort the kernel versions correctly; if for example parts of the version number change from one digit to two or from two to three, it will give you a wrong result. If you are happy, you can run it and pipe it through | fgrep sudo | sh to actually make it do something.

This comes obviously with no warranty whatsoever. I have tried on a number of real and virtual systems, and it worked fine there, but your mileage may vary.

#! /bin/bash
#

running_kernel_version="$(uname -r | sed 's/-generic$//')"
kernel_packages="$(dpkg -l | egrep '^ii *linux-(headers|image|modules|tools)-[1-9]' | awk '{print $2}')"
kernel_versions="$(for i in $kernel_packages
do
    if echo $i | fgrep -q "$running_kernel_version"
    then
        :
    else
        echo $i | sed -E 's/^linux-(headers|image|modules|tools)-([-.0-9]+)(-generic|)$/\2/'
    fi
done | sort -ur)"
keep_kernel_versions="$running_kernel_version $(echo $kernel_versions | cut -d ' ' -f 1-2)"
echo Keep kernel versions: $keep_kernel_versions
remove_kernel_versions="$(echo $kernel_versions | egrep -v '('"$(echo $keep_kernel_versions | sed 's/ /|/')"')')"
echo Remove kernel versions: $remove_kernel_versions
if [ -z "$remove_kernel_versions"]
then
    echo No packages to remove
else
    remove_kernel_packages="$(dpkg -l | egrep '^ii *linux-(headers|image|modules|tools)-('"$(echo "$remove_kernel_versions" | sed 's/ /|/')"')' | awk '{print $2}')"
    echo Remove kernel packages: $remove_kernel_packages
    echo "sudo apt remove -y $(echo $remove_kernel_packages)"
fi
remove_modules_folders="$(ls -d /lib/modules/* | egrep -v '('"$(echo $keep_kernel_versions | sed 's/ /|/')"')')"
if [ -z "$remove_modules_folders" ]
then
    echo No folders to remove
else
    echo Remove modules folders: $remove_modules_folders
    echo "sudo rm -rf $(echo $remove_modules_folders)"
fi