Removing old kernels - Debian based system

Linux systems that use the apt package management system do not remove old kernels when you upgrade to a newer one and you will end up with your boot directory increasing in size with every kernel upgrade. The only reason you would want keep your old kernels is if you upgrade the kernel and for some reason your system doesn’t come up. Once you boot on a new kernel checked your system and everything it is okay there is no reason to keep the old kernels it just eats up disk space. Each distro names there kernels a little differently, so you will need to tweak the scripts below depending on your distro. I use two different distro’s Debian and Mint and will show the scripts I use. You need to remove both the kernel image and the header files packages. Also - I shouldn’t need to say this, but “sudo apt update && sudo apt dist-upgrade” you want your system to be up to date before you continue.

Example 1 - Debian 10 (buster)

Step 1 - List what kernel you are currently running.

$ uname -r
4.19.0-6-amd64

Step 2 - You will want to check the current installed kernel image. If you did a system upgrade and did not reboot the system you could have a running kernel different from the latest installed kernel package. Using the “apt show linux-image-amd64” compare the “Depends:” option with the running kernel version from the “uname -r” command, I’m on the same kernel “4.19.0-6-amd64”, so good to go. If the two are different you will need to reboot and check it again before you continue. Note:each distro uses different naming conventions, so use the command in “Step 3” if you are unsure of the meta package name. The meta package will be the last part of the “uname -r” command (for my Debian system 4.19.0-6-amd64)plus “linux-image”. So the package I want to show in this example is “linux-image-amd64”

$ apt show linux-image-amd64
Package: linux-image-amd64
Version: 4.19+105+deb10u1
Priority: optional
Section: kernel
Source: linux-latest (105+deb10u1)
Maintainer: Debian Kernel Team <debian-kernel@lists.debian.org>
Installed-Size: 17.4 kB
Provides: linux-latest-modules-4.19.0-6-amd64
Depends: linux-image-4.19.0-6-amd64
Download-Size: 8,076 B
APT-Manual-Installed: yes
APT-Sources: http://deb.debian.org/debian buster/main amd64 Packages
Description: Linux for 64-bit PCs (meta-package)
 This package depends on the latest Linux kernel and modules for use on PCs
 with AMD64, Intel 64 or VIA Nano processors.

Step 3 - List the installed kernels and header packages on your system;

$ dpkg --list | egrep -i  'linux-image|linux-headers'
ii  linux-headers-4.19.0-5-amd64                      4.19.37-5+deb10u2                    amd64        Header files for Linux 4.19.0-5-amd64
ii  linux-headers-4.19.0-5-common                     4.19.37-5+deb10u2                    all          Common header files for Linux 4.19.0-5
ii  linux-headers-4.19.0-6-amd64                      4.19.67-2+deb10u1                    amd64        Header files for Linux 4.19.0-6-amd64
ii  linux-headers-4.19.0-6-common                     4.19.67-2+deb10u1                    all          Common header files for Linux 4.19.0-6
ii  linux-headers-4.9.0-4-amd64                       4.9.65-3+deb9u1                      amd64        Header files for Linux 4.9.0-4-amd64
ii  linux-headers-4.9.0-4-common                      4.9.65-3+deb9u1                      all          Common header files for Linux 4.9.0-4
ii  linux-headers-amd64                               4.19+105+deb10u1                     amd64        Header files for Linux amd64 configuration (meta-package)
rc  linux-image-4.19.0-1-amd64                        4.19.12-1                            amd64        Linux 4.19 for 64-bit PCs (signed)
rc  linux-image-4.19.0-2-amd64                        4.19.16-1                            amd64        Linux 4.19 for 64-bit PCs (signed)
rc  linux-image-4.19.0-4-amd64                        4.19.28-2                            amd64        Linux 4.19 for 64-bit PCs (signed)
ii  linux-image-4.19.0-5-amd64                        4.19.37-5+deb10u2                    amd64        Linux 4.19 for 64-bit PCs (signed)
ii  linux-image-4.19.0-6-amd64                        4.19.67-2+deb10u1                    amd64        Linux 4.19 for 64-bit PCs (signed)
rc  linux-image-4.9.0-1-amd64                         4.9.6-3                              amd64        Linux 4.9 for 64-bit PCs (signed)
rc  linux-image-4.9.0-2-amd64                         4.9.18-1                             amd64        Linux 4.9 for 64-bit PCs (signed)
ii  linux-image-4.9.0-3-amd64                         4.9.30-2+deb9u5                      amd64        Linux 4.9 for 64-bit PCs
ii  linux-image-4.9.0-4-amd64                         4.9.65-3+deb9u1                      amd64        Linux 4.9 for 64-bit PCs
rc  linux-image-4.9.0-5-amd64                         4.9.65-3+deb9u2                      amd64        Linux 4.9 for 64-bit PCs
rc  linux-image-4.9.0-6-amd64                         4.9.88-1+deb9u1                      amd64        Linux 4.9 for 64-bit PCs
rc  linux-image-4.9.0-7-amd64                         4.9.110-3+deb9u2                     amd64        Linux 4.9 for 64-bit PCs
rc  linux-image-4.9.0-8-amd64                         4.9.130-2                            amd64        Linux 4.9 for 64-bit PCs
ii  linux-image-amd64                                 4.19+105+deb10u1                     amd64        Linux for 64-bit PCs (meta-package)

First column is the package flag

  • rc: It means package is in remove/deinstall state and only config file exists.

  • ii: It means package is in install state and it is 100% installed on the system.

Second column is what we are interested in, that is the list of all the header packages and kernel packages we have installed on the system. My list is pretty short, but you will be surprised on how many packages are on your system if you have been running it for any length of time. There are five packages I want to leave on my Debian 10 system:

  • linux-image-amd64 (the kernel meta package - the package name you use to install with the “apt install” command)

  • linux-image-x.x.x-x-amd64 (the actual kernel image that the meta package installs in this case “linux-image-4.19.0-6-amd64”)

  • linux-headers-amd64 (the header meta package which installs two header packages - the package name you use to install with the “apt install” command)

  • linux-header-x.x.x-x-amd64 (the actual header files for the amd64 kernel that the meta package installs in this case “linux-headers-4.19.0-6-amd64”)

  • linux-header-x.x.x-x-common (the actual common header files that the meta package installs in this case “linux-headers-4.19.0-6-common”)

Step 4 - run the following commands and scripts to remove all of your old kernels. Set variable “v” to the kernel version we are running on and list it :

$ v="$(uname -r | awk -F '-amd64' '{ print $1}')"
$ echo "$v"
4.19.0-6

Set variable “i” to the packages we want to keep and list them;

$ i="linux-headers-amd64|linux-image-amd64|linux-headers-${v}-amd64|linux-headers-${v}-common|linux-image-$(uname -r)"
$ echo "$i"
linux-headers-amd64|linux-image-amd64|linux-headers-4.19.0-6-amd64|linux-headers-4.19.0-6-common|linux-image-4.19.0-6-amd64

Test to see what we are going to remove with our script;

root@jupiter:~# dpkg --list | egrep -i  'linux-image|linux-headers' | awk '/ii/{ print $2}' | egrep -v "$i"
linux-headers-4.19.0-5-amd64
linux-headers-4.19.0-5-common
linux-headers-4.9.0-4-amd64
linux-headers-4.9.0-4-common
linux-image-4.19.0-1-amd64
linux-image-4.19.0-2-amd64
linux-image-4.19.0-4-amd64
linux-image-4.19.0-5-amd64
linux-image-4.9.0-1-amd64
linux-image-4.9.0-2-amd64
linux-image-4.9.0-3-amd64
linux-image-4.9.0-4-amd64
linux-image-4.9.0-5-amd64
linux-image-4.9.0-6-amd64
linux-image-4.9.0-7-amd64
linux-image-4.9.0-8-amd64

Remove the packages;

root@jupiter:~# apt-get --purge remove $(dpkg --list | egrep -i  'linux-image|linux-headers' | awk '/ii/{ print $2}' | egrep -v "$i")
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following package was automatically installed and is no longer required:
  linux-kbuild-4.9
Use 'apt autoremove' to remove it.
The following packages will be REMOVED:
  linux-headers-4.19.0-5-amd64* linux-headers-4.19.0-5-common* linux-headers-4.9.0-4-amd64* linux-headers-4.9.0-4-common* linux-image-4.19.0-1-amd64*
linux-image-4.19.0-2-amd64* linux-image-4.19.0-4-amd64* linux-image-4.19.0-5-amd64* linux-image-4.9.0-1-amd64* linux-image-4.9.0-2-amd64*
linux-image-4.9.0-3-amd64* linux-image-4.9.0-4-amd64*  linux-image-4.9.0-5-amd64* linux-image-4.9.0-6-amd64* linux-image-4.9.0-7-amd64*
linux-image-4.9.0-8-amd64*
0 upgraded, 0 newly installed, 16 to remove and 0 not upgraded.
After this operation, 646 MB disk space will be freed.
Do you want to continue? [Y/n]

Looking at the output from the script notice that my installed kernel is omitted 4.19.0-6-amd64. By doing this I freed up 646M of disk space. Hit enter to continue and it will remove all of the old kernels and header files.

dpkg --list | egrep -i  'linux-image|linux-headers'
ii  linux-headers-4.19.0-6-amd64                      4.19.67-2+deb10u1                    amd64        Header files for Linux 4.19.0-6-amd64
ii  linux-headers-4.19.0-6-common                     4.19.67-2+deb10u1                    all          Common header files for Linux 4.19.0-6
ii  linux-headers-amd64                               4.19+105+deb10u1                     amd64        Header files for Linux amd64 configuration (meta-package)
ii  linux-image-4.19.0-6-amd64                        4.19.67-2+deb10u1                    amd64        Linux 4.19 for 64-bit PCs (signed)
ii  linux-image-amd64                                 4.19+105+deb10u1                     amd64        Linux for 64-bit PCs (meta-package)

Much better only have the files for the current kernel…….. To be safe lets make sure we didn’t remove something that we shouldn’t have. This will just reinstall the most recent kernel and headers packages

sudo apt --reinstall install linux-image-amd64 linux-headers-amd64
Reading package lists... Done
Building dependency tree
Reading state information... Done
0 upgraded, 0 newly installed, 2 reinstalled, 0 to remove and 0 not upgraded.
Need to get 0 B/14.8 kB of archives.
After this operation, 0 B of additional disk space will be used.
(Reading database ... 335095 files and directories currently installed.)
Preparing to unpack .../linux-headers-amd64_4.19+105+deb10u1_amd64.deb ...
Unpacking linux-headers-amd64 (4.19+105+deb10u1) over (4.19+105+deb10u1) ...
Preparing to unpack .../linux-image-amd64_4.19+105+deb10u1_amd64.deb ...
Unpacking linux-image-amd64 (4.19+105+deb10u1) over (4.19+105+deb10u1) ...
Setting up linux-headers-amd64 (4.19+105+deb10u1) ...
Setting up linux-image-amd64 (4.19+105+deb10u1) ...

One last step is to upgrade Grub so it knows we removed all the old kernels.

$ sudo update-grub
Generating grub configuration file ...
Found background image: /usr/share/images/desktop-base/desktop-grub.png
Found linux image: /boot/vmlinuz-4.19.0-6-amd64
Found initrd image: /boot/initrd.img-4.19.0-6-amd64
done

Example 2 – Mint 19.2 Cinnamon

$ uname -r
4.15.0-65-generic

List what packages are installed…..may more on this system.

dpkg --list | egrep -i  'linux-image|linux-headers'
ii  linux-headers-4.15.0-36                      4.15.0-36.39                                        all          Header files related to Linux kernel version 4.15.0
ii  linux-headers-4.15.0-36-generic              4.15.0-36.39                                        amd64        Linux kernel headers for version 4.15.0 on 64 bit x86 SMP
ii  linux-headers-4.15.0-39                      4.15.0-39.42                                        all          Header files related to Linux kernel version 4.15.0
ii  linux-headers-4.15.0-39-generic              4.15.0-39.42                                        amd64        Linux kernel headers for version 4.15.0 on 64 bit x86 SMP
ii  linux-headers-4.15.0-43                      4.15.0-43.46                                        all          Header files related to Linux kernel version 4.15.0
ii  linux-headers-4.15.0-43-generic              4.15.0-43.46                                        amd64        Linux kernel headers for version 4.15.0 on 64 bit x86 SMP
ii  linux-headers-4.15.0-46                      4.15.0-46.49                                        all          Header files related to Linux kernel version 4.15.0
ii  linux-headers-4.15.0-46-generic              4.15.0-46.49                                        amd64        Linux kernel headers for version 4.15.0 on 64 bit x86 SMP
ii  linux-headers-4.15.0-55                      4.15.0-55.60                                        all          Header files related to Linux kernel version 4.15.0
ii  linux-headers-4.15.0-55-generic              4.15.0-55.60                                        amd64        Linux kernel headers for version 4.15.0 on 64 bit x86 SMP
ii  linux-headers-4.15.0-64                      4.15.0-64.73                                        all          Header files related to Linux kernel version 4.15.0
ii  linux-headers-4.15.0-64-generic              4.15.0-64.73                                        amd64        Linux kernel headers for version 4.15.0 on 64 bit x86 SMP
ii  linux-headers-4.15.0-65                      4.15.0-65.74                                        all          Header files related to Linux kernel version 4.15.0
ii  linux-headers-4.15.0-65-generic              4.15.0-65.74                                        amd64        Linux kernel headers for version 4.15.0 on 64 bit x86 SMP
ii  linux-headers-4.4.0-101                      4.4.0-101.124                                       all          Header files related to Linux kernel version 4.4.0
......many more lines

This is the only change from the Debian example above, here are five packages I want to leave on my Mint 19.2 system:

  • linux-image-generic(the kernel meta package - the package name you use to install with the “apt install” command)

  • linux-image-x.x.x-x-generic (the actual kernel image that the meta package installs in this case “linux-image-4.15.0-65-generic”)

  • linux-headers-generic (the header meta package which installs two header packages - the package name you use to install with the “apt install” command)

  • linux-header-x.x.x-x-generic (the actual header files for the amd64 kernel that the meta package installs in this case “linux-headers-4.15.0-65-generic”)

  • linux-header-x.x.x-x (the actual common header files that the meta package installs in this case “linux-headers-4.15.0-65”)

Set variable “v” to the kernel version we are running on and list it. Then set variable “i” to the five packages I what we want to keep.

$ v="$(uname -r | awk -F '-generic' '{ print $1}')"
$ echo "$v"
4.15.0-65
$ i="linux-headers-generic|linux-image-generic|linux-headers-${v}-generic|linux-headers-${v}|linux-image-$(uname -r)"
$ echo "$i"
linux-headers-generic|linux-image-generic|linux-headers-4.15.0-65-generic|linux-headers-4.15.0-65|linux-image-4.15.0-65-generic

Print out what packages we will be removing…………..

$ dpkg --list | egrep -i  'linux-image|linux-headers' | awk '/ii/{ print $2}' | egrep -v "$i"
linux-headers-4.15.0-36
linux-headers-4.15.0-36-generic
linux-headers-4.15.0-39
linux-headers-4.15.0-39-generic
linux-headers-4.15.0-43
linux-headers-4.15.0-43-generic
linux-headers-4.15.0-46
linux-headers-4.15.0-46-generic
linux-headers-4.15.0-55
linux-headers-4.15.0-55-generic
linux-headers-4.15.0-64
linux-headers-4.15.0-64-generic
..........many more lines

Now we remove the packages.

sudo apt-get --purge remove $(dpkg --list | egrep -i  'linux-image|linux-headers' | awk '/ii/{ print $2}' | egrep -v "$i")
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages will be REMOVED:
  linux-headers-4.15.0-36* linux-headers-4.15.0-36-generic* linux-headers-4.15.0-39* linux-headers-4.15.0-39-generic* linux-headers-4.15.0-43* linux-headers-4.15.0-43-generic* linux-headers-4.15.0-46* linux-headers-4.15.0-46-generic*
  linux-headers-4.15.0-55* linux-headers-4.15.0-55-generic* linux-headers-4.15.0-64* linux-headers-4.15.0-64-generic* linux-headers-4.4.0-101* linux-headers-4.4.0-101-generic* linux-headers-4.4.0-104* linux-headers-4.4.0-104-generic*
  linux-headers-4.4.0-109* linux-headers-4.4.0-109-generic* linux-headers-4.4.0-116* linux-headers-4.4.0-116-generic* linux-headers-4.4.0-124* linux-headers-4.4.0-124-generic* linux-headers-4.4.0-21* linux-headers-4.4.0-21-generic*
  linux-headers-4.4.0-57* linux-headers-4.4.0-57-generic* linux-headers-4.4.0-59* linux-headers-4.4.0-59-generic* linux-headers-4.4.0-62* linux-headers-4.4.0-62-generic* linux-headers-4.4.0-64* linux-headers-4.4.0-64-generic*
  linux-headers-4.4.0-66* linux-headers-4.4.0-66-generic* linux-headers-4.4.0-72* linux-headers-4.4.0-72-generic* linux-headers-4.4.0-75* linux-headers-4.4.0-75-generic* linux-headers-4.4.0-77* linux-headers-4.4.0-77-generic*
  linux-headers-4.4.0-78* linux-headers-4.4.0-78-generic* linux-headers-4.4.0-79* linux-headers-4.4.0-79-generic* linux-headers-4.4.0-81* linux-headers-4.4.0-81-generic* linux-headers-4.4.0-83* linux-headers-4.4.0-83-generic*
  linux-headers-4.4.0-87* linux-headers-4.4.0-87-generic* linux-headers-4.4.0-91* linux-headers-4.4.0-91-generic* linux-headers-4.4.0-92* linux-headers-4.4.0-92-generic* linux-headers-4.4.0-93* linux-headers-4.4.0-93-generic*
  linux-headers-4.4.0-96* linux-headers-4.4.0-96-generic* linux-headers-4.4.0-97* linux-headers-4.4.0-97-generic* linux-headers-4.4.0-98* linux-headers-4.4.0-98-generic*
  linux-image-4.15.0-36-generic* linux-image-4.15.0-39-generic* linux-image-4.15.0-43-generic* linux-image-4.15.0-46-generic*
  linux-image-4.15.0-55-generic* linux-image-4.15.0-64-generic* linux-modules-extra-4.15.0-36-generic*
  linux-modules-extra-4.15.0-39-generic* linux-modules-extra-4.15.0-43-generic* linux-modules-extra-4.15.0-46-generic*
  linux-modules-extra-4.15.0-55-generic* linux-modules-extra-4.15.0-64-generic*

0 upgraded, 0 newly installed, 62 to remove and 17 not upgraded.
After this operation, 3,488 MB disk space will be freed.
Do you want to continue? [Y/n]

That freed up over 3G of space!!!! Now lets reinstall the kernel and header packages to make sure we didn’t break anything.

$ sudo apt-get --reinstall install linux-image-generic linux-headers-generic
Reading package lists... Done
Building dependency tree
Reading state information... Done
0 upgraded, 0 newly installed, 2 reinstalled, 0 to remove and 17 not upgraded.
Need to get 0 B/4,736 B of archives.
After this operation, 0 B of additional disk space will be used.
(Reading database ... 301089 files and directories currently installed.)
Preparing to unpack .../linux-headers-generic_4.15.0.65.67_amd64.deb ...
Unpacking linux-headers-generic (4.15.0.65.67) over (4.15.0.65.67) ...
Preparing to unpack .../linux-image-generic_4.15.0.65.67_amd64.deb ...
Unpacking linux-image-generic (4.15.0.65.67) over (4.15.0.65.67) ...
Setting up linux-image-generic (4.15.0.65.67) ...
Setting up linux-headers-generic (4.15.0.65.67) .

Show what kernel and header packages are installed

dpkg --list | egrep -i  'linux-image|linux-headers'
ii  linux-headers-4.15.0-65                      4.15.0-65.74                                        all          Header files related to Linux kernel version 4.15.0
ii  linux-headers-4.15.0-65-generic              4.15.0-65.74                                        amd64        Linux kernel headers for version 4.15.0 on 64 bit x86 SMP
ii  linux-headers-generic                        4.15.0.65.67                                        amd64        Generic Linux kernel headers
ii  linux-image-4.15.0-65-generic                4.15.0-65.74                                        amd64        Signed kernel image generic
ii  linux-image-generic                          4.15.0.65.67                                        amd64        Generic Linux kernel image

Now we update Grub to have only the current kernel

$ sudo update-grub
Sourcing file `/etc/default/grub'
Sourcing file `/etc/default/grub.d/50_linuxmint.cfg'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.15.0-65-generic
Found initrd image: /boot/initrd.img-4.15.0-65-generic
Found memtest86+ image: /boot/memtest86+.elf
Found memtest86+ image: /boot/memtest86+.bin
done