I wrote a Bash function for this very purpose. Sharing is caring, so here we go with a Bash function I have been using successfully on Debian 5 and 6 as well as Ubuntu versions between 10.04 and 12.10. It has evolved a bit over time but never failed me. It automates the "decision process".
NB: feel free to point out flaws and suggest improvements and I'll try my best to incorporate them.
function prune-kernels
{
[[ -f "/etc/debian_version" ]] || { echo -e "\033[01;32mERROR:\033[00m This has only been tested on Debian/Ubuntu."; return; }
[[ -e "/vmlinuz" ]] || { echo -e "\033[01;32mERROR:\033[00m Expected /vmlinuz to exist."; return; }
[[ "$UID" -eq "0" ]] || local SUDO=sudo
# Figure out the name of the newest and the previous kernel
local OLDKRNL=$(readlink -f /vmlinuz.old)
local NOWKRNL=$(readlink -f /vmlinuz)
# If vmlinuz doesn't exist, Also prune "/vmlinuz.old"?
[[ -e "/vmlinuz.old" ]] || OLDKRNL="$NOWKRNL"
# Also prune "/vmlinuz.old"? If so, pretend old and new have the same name to skip only the new one
[[ "$1" == "--old" ]] && local OLDKRNL="$NOWKRNL"
# Strip path
OLDKRNL="${OLDKRNL##*/vmlinuz-}"
NOWKRNL="${NOWKRNL##*/vmlinuz-}"
local VERSIONS=$(echo $(for krnl in /boot/vmlinuz-*; do echo "${krnl##*/vmlinuz-}"; done) $(for krnl in $(dpkg -l|command grep 'linux-image'|command grep '^ii'|command grep -v 'meta-package'|command grep 'linux-image-[[:digit:]]\.[[:digit:]]*\.[[:digit:]]'|awk '{print $2}'); do echo ${krnl##linux-image-}; done)|sort|uniq|sed -e "s:$NOWKRNL::g;s:$OLDKRNL::g;s:$(uname -r)::g")
echo -ne "\033[01;32mSkipping \033[01;33mthe following kernels:\033[00m $NOWKRNL"
[[ "$(uname -r)" == "$NOWKRNL" ]] || { echo -ne ", $(uname -r)"; }
echo -ne " (\033[0;32mcurrently running\033[00m)"
[[ "$OLDKRNL" == "$NOWKRNL" ]] || echo -ne ", $OLDKRNL (\033[0;33mold kernel\033[00m)"
echo ""
# Remove packages
local PACKAGES=$(for i in $VERSIONS; do echo -n "linux-image-$i linux-headers-$i "; done)
if [[ -n "$PACKAGES" ]]; then
echo -e "\033[0;32m[STEP 1] \033[01;33mRemoving packages\033[00m"
$SUDO apt-get remove $PACKAGES || { echo -e "\033[01;31mSeems that apt-get was not successful, aborting.\033[00m"; return; }
else
echo -e "\033[01;32mNo packages need to be removed.\033[00m"
fi
# Remove any remaining kernel images etc from /boot
local FILES=$(for fname in $(for i in $VERSIONS; do echo -n "/boot/abi-$i /boot/initrd.img-$i config-$i System.map-$i vmcoreinfo-$i vmlinuz-$i "; done); do [[ -f "$fname" ]] && { echo -n "$fname "; }; done)
if [[ -n "$FILES" ]]; then
echo -e "\033[0;32m[STEP 2] \033[01;33mNow removing remaining files:\033[00m $FILES"
$SUDO rm -f $FILES
else
echo -e "\033[01;32mNothing else to clean up.\033[00m"
fi
}
Put the function into a file and source it from your .bashrc
or simply source it from the shell ad hoc and run it then. Unless you did something fancy to your apt-get
settings, this will prompt before taking action.
The function also takes a parameter --old
to remove all but the running kernel. By default it will skip the running and the old (/vmlinuz.old
) kernels during pruning.
Also note: this function does work nicely even in scenarios where the running kernel is older than the current (/vmlinuz
link) and the old (/vmlinuz.old
link) kernels.
Disclosure: almost 1:1 copy from an earlier answer by me here.