Removing Unused LINUX Kernels by Shell Script


Published: 2019-04-27
Updated: 2019-04-27
Web: https://fritzthecat-blog.blogspot.com/2019/04/removing-unused-linux-kernels-by-shell.html


When you list your LINUX kernels you will find out that upgrading to a new version does not remove the old kernel. It stays on disk and inside the grub boot-manager menu as a fallback-system. This may become a problem when your /boot file-system is of restricted size (maybe due to a dedicated boot-partition). Anyway these kernels are not needed in case your LINUX starts up nicely after upgrade.

This Blog is about how to remove unused kernels.
Mind that the preceding '$' in all commands below is the UNIX terminal prompt and does not belong to the command itself.

Listing Kernels

I did this on Ubuntu, which is a Debian system, thus I used dpkg to list kernels.


$ dpkg --list | grep "linux-" | grep "image-"
rc linux-image-3.13.0-32-generic 3.13.0-32.57 amd64 Linux kernel image for version 3.13.0 on 64 bit x86 SMP
rc linux-image-3.13.0-43-generic 3.13.0-43.72 amd64 Linux kernel image for version 3.13.0 on 64 bit x86 SMP
rc linux-image-3.13.0-44-generic 3.13.0-44.73 amd64 Linux kernel image for version 3.13.0 on 64 bit x86 SMP
rc linux-image-3.13.0-45-generic 3.13.0-45.74 amd64 Linux kernel image for version 3.13.0 on 64 bit x86 SMP
rc linux-image-3.13.0-46-generic 3.13.0-46.79 amd64 Linux kernel image for version 3.13.0 on 64 bit x86 SMP
rc linux-image-3.13.0-53-generic 3.13.0-53.89 amd64 Linux kernel image for version 3.13.0 on 64 bit x86 SMP
rc linux-image-3.13.0-74-generic 3.13.0-74.118 amd64 Linux kernel image for version 3.13.0 on 64 bit x86 SMP
ii linux-image-3.13.0-92-generic 3.13.0-92.139 amd64 Linux kernel image for version 3.13.0 on 64 bit x86 SMP
rc linux-image-4.15.0-42-generic 4.15.0-42.45 amd64 Signed kernel image generic
ii linux-image-4.15.0-43-generic 4.15.0-43.46 amd64 Signed kernel image generic
ii linux-image-4.15.0-48-generic 4.15.0-48.51 amd64 Signed kernel image generic
rc linux-image-4.4.0-124-generic 4.4.0-124.148 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-4.4.0-128-generic 4.4.0-128.154 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-4.4.0-131-generic 4.4.0-131.157 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-4.4.0-138-generic 4.4.0-138.164 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-4.4.0-140-generic 4.4.0-140.166 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-4.4.0-31-generic 4.4.0-31.50 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-4.4.0-34-generic 4.4.0-34.53 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-4.4.0-83-generic 4.4.0-83.106 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-4.4.0-87-generic 4.4.0-87.110 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-4.4.0-92-generic 4.4.0-92.115 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-4.4.0-97-generic 4.4.0-97.120 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-4.4.0-98-generic 4.4.0-98.121 amd64 Linux kernel image for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-3.13.0-32-generic 3.13.0-32.57 amd64 Linux kernel extra modules for version 3.13.0 on 64 bit x86 SMP
rc linux-image-extra-3.13.0-43-generic 3.13.0-43.72 amd64 Linux kernel extra modules for version 3.13.0 on 64 bit x86 SMP
rc linux-image-extra-3.13.0-44-generic 3.13.0-44.73 amd64 Linux kernel extra modules for version 3.13.0 on 64 bit x86 SMP
rc linux-image-extra-3.13.0-45-generic 3.13.0-45.74 amd64 Linux kernel extra modules for version 3.13.0 on 64 bit x86 SMP
rc linux-image-extra-3.13.0-46-generic 3.13.0-46.79 amd64 Linux kernel extra modules for version 3.13.0 on 64 bit x86 SMP
rc linux-image-extra-3.13.0-53-generic 3.13.0-53.89 amd64 Linux kernel extra modules for version 3.13.0 on 64 bit x86 SMP
rc linux-image-extra-3.13.0-74-generic 3.13.0-74.118 amd64 Linux kernel extra modules for version 3.13.0 on 64 bit x86 SMP
ii linux-image-extra-3.13.0-92-generic 3.13.0-92.139 amd64 Linux kernel extra modules for version 3.13.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-124-generic 4.4.0-124.148 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-128-generic 4.4.0-128.154 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-131-generic 4.4.0-131.157 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-138-generic 4.4.0-138.164 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-140-generic 4.4.0-140.166 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-31-generic 4.4.0-31.50 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-34-generic 4.4.0-34.53 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-83-generic 4.4.0-83.106 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-87-generic 4.4.0-87.110 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-92-generic 4.4.0-92.115 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-97-generic 4.4.0-97.120 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
rc linux-image-extra-4.4.0-98-generic 4.4.0-98.121 amd64 Linux kernel extra modules for version 4.4.0 on 64 bit x86 SMP
ii linux-image-generic 4.15.0.48.50 amd64 Generic Linux kernel image
ii linux-signed-generic 4.15.0.48.50 amd64 Complete Signed Generic Linux kernel and headers (dummy transitional package)
rc linux-signed-image-3.13.0-44-generic 3.13.0-44.73 amd64 Signed kernel image generic
rc linux-signed-image-3.13.0-45-generic 3.13.0-45.74 amd64 Signed kernel image generic
rc linux-signed-image-3.13.0-46-generic 3.13.0-46.79 amd64 Signed kernel image generic
rc linux-signed-image-3.13.0-53-generic 3.13.0-53.89 amd64 Signed kernel image generic
rc linux-signed-image-3.13.0-74-generic 3.13.0-74.118 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-124-generic 4.4.0-124.148 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-128-generic 4.4.0-128.154 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-131-generic 4.4.0-131.157 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-138-generic 4.4.0-138.164 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-140-generic 4.4.0-140.166 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-31-generic 4.4.0-31.50 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-34-generic 4.4.0-34.53 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-83-generic 4.4.0-83.106 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-87-generic 4.4.0-87.110 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-92-generic 4.4.0-92.115 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-97-generic 4.4.0-97.120 amd64 Signed kernel image generic
rc linux-signed-image-4.4.0-98-generic 4.4.0-98.121 amd64 Signed kernel image generic

When you find yourself with such a big list of kernels you don't want to remove them one by one. But before you apply a script you should try regular commands.

Regular Clean-Up Commands

First try this command:


$ sudo apt autoremove

Now check if they are gone. Listing /boot shows existing kernel files:


$ ls -la /boot

Any file in that directory that is named vmlinuz is a kernel. It should carry the version in its name. It is accompanied by other files like initrd.img, so you should always remove a kernel by system-commands, not by a file-remove.

If old kernels are still present, try this command:


$ sudo apt-get autoremove --purge

Still not gone? Now you would need to remove them one by one, e.g. for linux-image-3.13.0-32-generic:


$ sudo apt-get -y --purge remove linux-image-3.13.0-32-generic

But in case you have as many old kernels as I had, you may appreciate following script.

Clean-Up by Script

Don't ever remove the current kernel! You can find out its version by this command:


$ uname -r
4.15.0-48-generic

Also don't remove linux-image-generic.

To avoid any misconception, the following script just outputs command lines. Redirecting and executing the result is left up to you.

purge-generate.sh

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[ -z "$1" ] && {
echo "SYNTAX: purge-generate.sh kernelversionhead" >&2
echo " Example: purge-generate.sh 4.4.0" >&2
exit 1
}

KERNELVERSION=$1

list=`dpkg --list | grep linux- | grep image-`
kernels=`echo "\$list" | awk '
/linux-image-'\$KERNELVERSION'/ || /linux-signed-image-'\$KERNELVERSION'/ || /linux-image-extra-'\$KERNELVERSION'/ {
print $2
}'`

[ -z "$kernels" ] && {
echo "ERROR: no kernels found with version head $KERNELVERSION" >&2
echo "Found kernel images:" >&2
echo "$list" >&2
exit 2
}

for kernel in $kernels
do
echo "sudo apt-get -y --purge remove $kernel"
done

Redirect the output of this script to another script, set the new script executable, and then check it for mistakes before executing it!

$ chmod 700 purge-generate.sh
$ purge-generate.sh 3.13.0 >purge.sh
# check purge.sh before executing it!
$ chmod 700 purge.sh
$ ./purge.sh

The script requires an argument which is the version-head for the kernel(s) to remove. Mind that giving too few numbers (e.g. just "4.15") may include also the current kernel! That's the reason why you need to look at the generated script before executing it.

If everything worked out fine and kernels have been removed, you can update grub to remove obsolete menu items (sometimes already done automatically by apt-get -y --purge):


$ sudo update-grub

This will recreate /boot/grub/grub.cfg which contains the menu items. Further grub configurations you find in /etc/default/grub (modify this before executing update-grub!).

Script Comments

Lines 1-5:
The script first checks that the command line argument is not empty. Mind that the argument may give just the start of the version, so several kernels could be afftected! In case no version match was given, the script outputs its syntax and exits.

Lines 7-13:
The commandline argument is taken into variable KERNELVERSION, which is later injected into the awk script below. But first the kernels are found by listing all installed packages and grep-ing out those that are possibly kernel packages. The `backticks` (command-substitution) put the output of the contained command into variable list.

The awk script reduces the list to those lines that match the KERNELVERSION, and outputs the name of the kernel image, which is the second word, addressed through $2 (which is not variable of the enclosing shell!). Now the variable kernels holds all kernels to remove.

Mind that the double quotes in echo "\$list" are not dispensable. Without them the shell would remove newlines from variable list, and awk would receive just one single line.

Mind also the way how KERNELVERSION is injected into the awk script. The script-text for awk is enclosed into 'single quotes', which end directly before \$KERNELVERSION, and start again directly after. The backslash before $KERNELVERSION is needed due to the enclosing `backticks`, although some shells allow to leave this out.

Lines 15-20:
In case no kernel matched the given version, the script exits and lists existing kernels.

Lines 22-25:
When kernels matched the given version, a command line to remove it gets generated for each of them.





ɔ⃝ Fritz Ritzberger, 2019-04-27