Edit: This is no longer necessary with the release of Xenial Xerus 16.04. See the red below.
If you find that autoremove wants to only keep the latest kernel. Or even if you boot into a previous kernel autoremove will remove the most current kernel,
here is a workaround until Bug #1440608 is fixed.
There are 2 important parts to this workaround.
This is not my work but Jarnos's work and it works well allowing 2 kernels to be kept as you would expect it to do.
You could make a backup copy first if you want: sudo cp /etc/kernel/postinst.d/apt-auto-removal /etc/kernel/postinst.d/apt-auto-removal.bak
1) Edit and replace /etc/kernel/postinst.d/apt-auto-removal with this: (from post #40 on that bug)
Code:
#!/bin/sh -e
# Author: Steve Langasek <steve.langasek@canonical.com>
# Jarno Suni <8@iki.fi>
#
# Mark as not-for-autoremoval those kernel packages that are:
# - the currently booted version
# - the kernel version we've been called for, if not removing it
# - the latest kernel version (determined using rules copied from the
# grub package for deciding which kernel to boot)
# - the second-latest kernel version, if the booted kernel version is
# already the latest to ensure a fallback remains available in the
# event the newly-installed kernel at this ABI fails to boot. In the
# common case, this results in exactly two kernels saved, but it can
# result in three kernels being saved. It's better to err on the
# side of saving too many kernels than saving too few.
#
# We generate this list and save it to /etc/apt/apt.conf.d instead of marking
# packages in the database because this runs from a postinst script, and apt
# will overwrite the db when it exits.
eval $(apt-config shell APT_CONF_D Dir::Etc::parts/d)
test -n "${APT_CONF_D}" || APT_CONF_D="/etc/apt/apt.conf.d"
config_file=${APT_CONF_D}/01autoremove-kernels
eval $(apt-config shell DPKG Dir::bin::dpkg/f)
test -n "$DPKG" || DPKG="/usr/bin/dpkg"
# No specific apt config variable for dpkg-query?
DPKG_QUERY="${DPKG}-query"
triggered_version="$1"
if [ -n "$1" ]
then
regex_argument="$(echo "$1" | sed -e 's#\.#\\.#g')"
#Check if the kernel given in argument is desired to be removed:
${DPKG_QUERY} -W -f='${Package} ${db:Status-Abbrev}\n' |
grep -Eq '^((linux|kfreebsd|gnumach)-image|linux-image-extra)-'"$regex_argument"' (r|p)H' &&
triggered_version=""
fi
running_version="$(uname -r)"
version_test_gt ()
{
local version_test_gt_sedexp="s/[._-]\(pre\|rc\|test\|git\|old\|trunk\)/~\1/g"
local version_a="`echo "$1" | sed -e "$version_test_gt_sedexp"`"
local version_b="`echo "$2" | sed -e "$version_test_gt_sedexp"`"
$DPKG --compare-versions "$version_a" gt "$version_b"
return "$?"
}
list="$(${DPKG_QUERY} -W -f='${db:Status-Abbrev} ${Package}\n' |
awk '/^ii (linux|kfreebsd|gnumach)-image-[0-9]+\./ && $2 !~ /-dbg$/ { print $2 }' |
xargs apt-mark showauto |
sed -e 's#\(linux\|kfreebsd\|gnumach\)-image-##')"
latest_version=""
previous_version=""
for i in $list; do
if version_test_gt "$i" "$latest_version"; then
previous_version="$latest_version"
latest_version="$i"
elif version_test_gt "$i" "$previous_version"; then
previous_version="$i"
fi
done
if [ "$latest_version" != "$running_version" ]
then
# We have at least two kernels that we have reason to think the
# user wants, so don't save the second-newest version.
previous_version=""
fi
kernels="$(echo "$latest_version
$triggered_version
$running_version
$previous_version" | sort -Vu | sed -e 's#\.#\\.#g' )"
generateconfig() {
cat <<EOF
// DO NOT EDIT! File autogenerated by $0
APT::NeverAutoRemove
{
EOF
apt-config dump --no-empty --format '%v%n' 'APT::VersionedKernelPackages' | while read package; do
for kernel in $kernels; do
echo " \"^${package}-${kernel}$\";"
done
done
echo '};'
}
generateconfig > "${config_file}.dpkg-new"
mv "${config_file}.dpkg-new" "$config_file"
2) Create a cron job that will run at startup to perform an autoremove like this: (this is from post #26 and #27 of that bug and also created by Jarnos)
Create this file: /etc/cron.d/boot-auto-removal that contains the following:
Code:
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
@reboot root /etc/kernel/postinst.d/apt-auto-removal
That's it. Upon a reboot, you will be able to keep at least 2 kernels.
You may also want to add your name to that bug as this has affected every version of Ubuntu back to 12.04.
Edit: the more people on that bug, the more attention it gets.
Also here is the original thread about this: http://ubuntuforums.org/showthread.php?t=2251168
Edit: If you changed your /etc/kernel/postinst.d/apt-auto-removal file with the above, you could either leave it or replace it with what came out with Xenial Xerus' release:
Code:
#!/bin/sh
set -e
# Mark as not-for-autoremoval those kernel packages that are:
# - the currently booted version
# - the kernel version we've been called for
# - the latest kernel version (as determined by debian version number)
# - the second-latest kernel version
#
# In the common case this results in two kernels saved (booted into the
# second-latest kernel, we install the latest kernel in an upgrade), but
# can save up to four. Kernel refers here to a distinct release, which can
# potentially be installed in multiple flavours counting as one kernel.
eval $(apt-config shell APT_CONF_D Dir::Etc::parts/d)
test -n "${APT_CONF_D}" || APT_CONF_D="/etc/apt/apt.conf.d"
config_file="${APT_CONF_D}/01autoremove-kernels"
eval $(apt-config shell DPKG Dir::bin::dpkg/f)
test -n "$DPKG" || DPKG="/usr/bin/dpkg"
list="$("${DPKG}" -l | awk '/^[ih][^nc][ ]+(linux|kfreebsd|gnumach)-image-[0-9]+\./ && $2 !~ /-dbg(:.*)?$/ && $2 !~ /-dbgsym(:.*)?$/ { print $2,$3; }' \
| sed -e 's#^\(linux\|kfreebsd\|gnumach\)-image-##' -e 's#:[^:]\+ # #')"
debverlist="$(echo "$list" | cut -d' ' -f 2 | sort --unique --reverse --version-sort)"
if [ -n "$1" ]; then
installed_version="$(echo "$list" | awk "\$1 == \"$1\" { print \$2;exit; }")"
fi
unamer="$(uname -r)"
if [ -n "$unamer" ]; then
running_version="$(echo "$list" | awk "\$1 == \"$unamer\" { print \$2;exit; }")"
fi
latest_version="$(echo "$debverlist" | sed -n 1p)"
previous_version="$(echo "$debverlist" | sed -n 2p)"
debkernels="$(echo "$latest_version
$installed_version
$running_version
$previous_version" | sort -u | sed -e '/^$/ d')"
kernels="$( (echo "$1
$unamer"; for deb in $debkernels; do echo "$list" | awk "\$2 == \"$deb\" { print \$1; }"; done; ) \
| sed -e 's#\.#\\.#g' -e '/^$/ d' | sort -u)"
generateconfig() {
cat <<EOF
// DO NOT EDIT! File autogenerated by $0
APT::NeverAutoRemove
{
EOF
for package in $(apt-config dump --no-empty --format '%v%n' 'APT::VersionedKernelPackages'); do
for kernel in $kernels; do
echo " \"^${package}-${kernel}$\";"
done
done
echo '};'
if [ "${APT_AUTO_REMOVAL_KERNELS_DEBUG:-true}" = 'true' ]; then
cat <<EOF
/* Debug information:
# dpkg list:
$(dpkg -l | grep '\(linux\|kfreebsd\|gnumach\)-image-')
# list of installed kernel packages:
$list
# list of different kernel versions:
$debverlist
# Installing kernel: $installed_version ($1)
# Running kernel: $running_version ($unamer)
# Last kernel: $latest_version
# Previous kernel: $previous_version
# Kernel versions list to keep:
$debkernels
# Kernel packages (version part) to protect:
$kernels
*/
EOF
fi
}
generateconfig "$@" > "${config_file}.dpkg-new"
mv -f "${config_file}.dpkg-new" "$config_file"
chmod 444 "$config_file"
And if you changed that file and have changed it back, you should delete the file /etc/cron.d/boot-auto-removal as well.
Bookmarks