#!/usr/bin/env bash # # JbTecWiz Support Centre -- generated fix script # # Fault : /boot is full and updates fail # Fix : Clear old kernels on the RHEL family # Source: https://jbtecwiz.com/support/lnx-sto-boot-full # # Run as : Root shell # Expect : 25 minutes # Risk : medium # Reversible : NO -- read the undo note below # # WHEN THIS IS THE RIGHT FIX # dnf or yum. # # HOW TO UNDO IT # Reinstall a removed kernel with dnf install kernel-. # # Walks the fix one step at a time and asks before each. Steps with no # command are yours to do -- it prints those and waits. DRYRUN=1 prints # without executing; UNATTENDED=1 does not ask. # # -------------------------------------------------------------------- # NO WARRANTY - USE AT YOUR OWN RISK # # This script is provided by JbTecWiz as-is and with no warranty of any # kind, express or implied. You run it entirely at your own risk. # # JbTecWiz accepts no liability for any loss or damage arising from its # use, including but not limited to data loss, downtime, or configuration # changes that turn out to be wrong for your system. # # You are responsible for reading this script before running it, for # satisfying yourself that it suits the machine in front of you, and for # having a working backup first. Some steps cannot be undone. # -------------------------------------------------------------------- set -uo pipefail DRYRUN="${DRYRUN:-0}" UNATTENDED="${UNATTENDED:-0}" failed=0 if [ "$(id -u)" -ne 0 ]; then echo " This fix is documented as needing root. Re-run with sudo." >&2 exit 3 fi rule() { printf "\n%s\n" "$(printf '-%.0s' $(seq 1 70))"; if [ $# -gt 0 ]; then echo "$1"; fi; } prose() { echo "$1" | fold -s -w 74 | sed "s/^/ /"; } # Returns 0 when the caller should run the command, 1 when it should not. # A manual step always returns 1 -- there is nothing for the caller to run. step() { # step [command lines...] local n="$1" dotext="$2" why="$3" mode="$4"; shift 4 rule " Step $n of 5" prose "$dotext" if [ -n "$why" ]; then echo; prose "$why"; fi if [ "$mode" = "manual" ]; then echo; echo " -> Do this yourself, then press Enter to carry on." if [ "$UNATTENDED" = "0" ] && [ "$DRYRUN" = "0" ]; then read -r _; fi return 1 fi echo; printf " %s\n" "$@"; echo if [ "$DRYRUN" = "1" ]; then echo " (dry run -- not executed)"; return 1; fi if [ "$UNATTENDED" = "0" ]; then read -r -p " Run this step? [Y]es / [S]kip / [Q]uit " a case "$a" in [Qq]*) echo " Stopped at your request."; exit 0 ;; [Ss]*) echo " Skipped."; return 1 ;; esac fi return 0 } rule echo " /boot is full and updates fail" echo " Clear old kernels on the RHEL family" echo echo " Risk: medium NOT REVERSIBLE 25 minutes" echo prose 'No warranty. Use at your own risk - JbTecWiz accepts no liability. Read it before you run it, and have a backup.' rule echo if [ "$UNATTENDED" = "0" ] && [ "$DRYRUN" = "0" ]; then read -r -p " Ready? [y/N] " go case "$go" in [Yy]*) ;; *) echo " Nothing was changed."; exit 0;; esac fi if step 1 'Check what is installed and what is running.' '' cmd 'uname -r' 'rpm -q kernel' 'df -h /boot'; then uname -r rpm -q kernel df -h /boot if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 1 failed. The rest of the fix may depend on it." >&2 fi fi if step 2 'Remove old kernels, keeping the configured number. dnf refuses to remove the running one, which makes this considerably safer than the apt equivalent.' 'The installonly mechanism is aware of which kernel is booted and will not remove it. This is the supported path and it should be used in preference to removing packages by name.' cmd 'sudo dnf remove --oldinstallonly --setopt installonly_limit=2 kernel'; then sudo dnf remove --oldinstallonly --setopt installonly_limit=2 kernel if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 2 failed. The rest of the fix may depend on it." >&2 fi fi if step 3 'Set the retention limit permanently.' '' cmd 'sudo sed -i '\''s/^installonly_limit.*/installonly_limit=2/'\'' /etc/dnf/dnf.conf' 'grep installonly /etc/dnf/dnf.conf'; then sudo sed -i 's/^installonly_limit.*/installonly_limit=2/' /etc/dnf/dnf.conf grep installonly /etc/dnf/dnf.conf if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 3 failed. The rest of the fix may depend on it." >&2 fi fi if step 4 'Rebuild the boot configuration if entries are stale.' '' cmd 'sudo grub2-mkconfig -o /boot/grub2/grub.cfg' 'sudo grubby --info=ALL | grep ^kernel'; then sudo grub2-mkconfig -o /boot/grub2/grub.cfg sudo grubby --info=ALL | grep ^kernel if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 4 failed. The rest of the fix may depend on it." >&2 fi fi if step 5 'Complete any interrupted transaction.' '' cmd 'sudo dnf history' 'sudo dnf distro-sync'; then sudo dnf history sudo dnf distro-sync if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 5 failed. The rest of the fix may depend on it." >&2 fi fi rule " Confirm it worked" prose '/boot has space and the boot menu lists the expected kernels.' if [ "$DRYRUN" = "0" ]; then df -h /boot; sudo grubby --default-kernel fi rule if [ "$failed" -gt 0 ]; then echo " Finished with $failed failed step(s)." echo " Read the full write-up at https://jbtecwiz.com/support/lnx-sto-boot-full" else echo " Finished." fi echo prose 'To undo: Reinstall a removed kernel with dnf install kernel-.' rule