#!/bin/sh # DESCRIPTION: fixes up /boot selected kernels for vmlinuz and initrd.img # # INSTALLATION: sudo wget 'https://gist.githubusercontent.com/anonyco/ec7c1d69b2ddde23fc1bdade017a0ad0/raw' \ # -O/etc/grub.d/01_fixup_boot_kernel && sudo chmod +x /etc/grub.d/01_fixup_boot_kernel # # ERROR HANDLING: Run this program with peace of mind knowing that any serious/critical error (that would likely bork # your computer if you were to reboot) will alert you with a graphical popup error dialog to catch your attention: # * IF either no initrd.img or no vmlinuz was found. This could happen if your system uses a different model # and is most likely indicative of this script being incompatible with your system's boot setup # * IF there's a version mismatch between the latest initrd.img/vmlinuz. This can happen, for example, if the # there's no disk space left on /boot and only of these is successfully copied to /boot by update-initramfs # * BOTH these errors will appear no matter what! Even if you run update-grub as a background automated task, # this script will seek out and hook into whatever graphical display it can find and show an error box on it # # BEHAVIOR: # 1. Chooses the latest available kernel version for vmlinuz and initrd.img # 2. IF you are current running an older kernel than the latest, then this script makes sure vmlinuz.old and # initrd.img.old point to the ones for your current running kernel (so you have a solid working backup option.) # 3. IF vmlinuz.old and initrd.img.old are left as-is IF they are not at the latest kernel AND are not dead links. # 4. Otherwise, vmlinuz.old and initrd.img.old are autoset to the oldest available vmlinuz and initrd.img.old # 5. All checks make sure the version of vmlinuz.old and initrd.img.old are matching versions and non-zero size and # you won't be notified if the versions don't match; this script will just skip choosing that version and search # for the next working verison-matching non-zero-size vmlinuz and initrd.img pair to use. # # SPDX-License-Id: GPL-3.0-only OLDDIR="$(pwd)" if cd /boot 2>/dev/null ; then OLDIFS="$IFS" oldestinitrd="" newestinitrd="" oldestvmlinuz="" newestvmlinuz="" thisscript="$0" runAsUserSourceFromPID() ( thepid="$1" theuser="$2" thegroup="$3" shift 3 if cdtopwd="$(/usr/bin/grep -m1 -zahe PWD= "/proc/$thepid/environ" 2>/dev/null)" ; then cd -- "${cdtopwd#"PWD="}" 2>/dev/null || true elif test -d "/home/$theuser" ; then cd -- "/home/$theuser" 2>/dev/null || true elif test -d "/home/$thegroup" ; then cd -- "/home/$thegroup" 2>/dev/null || true fi # shellcheck disable=SC2016 cdtopwd='$cdtopwd' sudo -i -A -u "$theuser" -g "$thegroup" </dev/null 2>&1 || true # First, we only search non-root seated session leaders. Then, we exaustively search the non-session-leaders for any x processes who might have our needed variables for psargs in -dNo -eo; do IFS=' ' # shellcheck disable=SC2009 for l in $(ps "$psargs" pid,euid,seat,euser,egroup 2>/dev/null | grep -ve ' 0 ' -e ' - ' -e ' EUSER '); do IFS=' ' # shellcheck disable=SC2086 set -- $l if test "x$*" = "x" ; then continue fi # notice the "-s" flag, which suppresses outputting any read errors, which will happen for processes we dont have permission to read their environment of if grep -asqe 'XAUTHORITY=/' "/proc/$1/environ" >/dev/null 2>&1 ; then #eval "$(printf "sudo -u '$2' -g '$3' /usr/bin/env "; xargs -0a"/proc/$1/environ" /usr/bin/printf "%q "; printf "-- gnome-terminal")" #if test "x' '" = "x$(/usr/bin/printf "%q" " " 2>/dev/null)"; then # printf "%s\n" eval "$(xargs -0a"/proc/$1/environ" /usr/bin/printf "%q\n")" #else # printf "%s\n" eval "$(xargs -r0a"/proc/$1/environ" sh -c 'IFS="'\''"; for a in "$@"; do o="$(printf "%s'"'\\\''"'" $a)"; printf "'\''%s'\''\n" "${o%"'"'\\\''"'"}"; done' --)" #fi #eval "$(env -i xargs -r0a"/proc/$1/environ" sh -c 'export "$@"; test "$PWD" != "/boot" && export cdtopwd="$PWD"; export -p' --)" #test -z "$cdtopwd" || cd -- "$cdtopwd" #/bin/bash -i #runAsUserSourceFromPID "$1" "$4" "$5" /usr/bin/gnome-terminal runAsUserSourceFromPID "$1" "$4" "$5" xmessage -default ok -geometry 300x200 -nearmouse "$(printf "%s\n" "$msg" | fold -sw 36)" return 0 fi done done ) IFS=' ' for file in $( printf "%s\n" initrd.img-* vmlinuz-* | sort -nt- -k2,2 ) do test -s "$file" || continue if test "${file#vmlinuz-}" = "$file" ; then oldestinitrd="${oldestinitrd:-$file}" newestinitrd="$file" else oldestvmlinuz="${oldestinitrd:-$file}" newestvmlinuz="$file" fi done IFS="$(printf "\t\n ")" if test "/$newestinitrd" = "/" -o "/$newestvmlinuz" = "/" ; then xmessage "FATAL ERROR WHILST GENERATING GRUB: $thisscript: could not find vmlinuz or initrd in /boot! System might be borked and you should investigate this before restarting!" -default ok -geometry 300x200 -nearmouse exit 1 fi if test "${newestinitrd#initrd.img-}" != "${newestvmlinuz#vmlinuz-}" ; then xmessage "FATAL ERROR WHILST GENERATING GRUB: $thisscript: version mismatch between $newestvmlinuz and $newestinitrd in /boot! System might be borked and you should investigate this before restarting!" -default ok -geometry 300x200 -nearmouse exit 1 fi #ln -sfT "$newestinitrd" initrd.img echo "[INFO] $thisscript: linked /boot/initrd.img -> $newestinitrd" >&2 #ln -sfT "$newestvmlinuz" vmlinuz echo "[INFO] $thisscript: linked /boot/vmlinuz -> $newestvmlinuz" >&2 alreadyerrored=0 if test "${oldestinitrd#initrd.img-}" != "${oldestvmlinuz#vmlinuz-}" ; then if test -s "vmlinuz-${oldestinitrd#initrd.img-}" ; then oldestvmlinuz="vmlinuz-${oldestinitrd#initrd.img-}" elif test -s "initrd.img-${oldestvmlinuz#vmlinuz-}" ; then oldestinitrd="initrd.img-${oldestvmlinuz#vmlinuz-}" else alreadyerrored=1 echo "[WARN] $thisscript: could not match old vmlinuz and initrd.img versions $oldestinitrd and $oldestvmlinuz as neither verisons have eachother. The old may be unavailable and this should be looked into." 1>&2 fi fi didMatchRepl=n if runningkernelver="$(uname -r >/dev/null 2>&1)" && test "initrd.img-$runningkernelver" != "$newestinitrd" then for file in initrd.img-*"$runningkernelver" vmlinuz-*"$runningkernelver" do test -s "$file" -a "$file" != "$newestvmlinuz" -a "$file" != "$newestinitrd" || continue if test "${file#vmlinuz}" = "$file" -a -s "vmlinuz-${file#initrd.img-}" ; then oldestinitrd="$file" oldestvmlinuz="vmlinuz-${file#initrd.img-}" didMatchRepl=y break elif test -s "initrd.img-${file#vmlinuz-}" ; then oldestinitrd="initrd.img-${file#vmlinuz-}" oldestvmlinuz="$file" didMatchRepl=y break fi done test "$didMatchRepl" = "n" && echo "[WARN] $thisscript: the currently running kernel version does not exist in /boot. This shouldnt be an issue as theres another kernel to boot but proceed carefully." 1>&2 fi if test "$alreadyerrored" -eq 1 then : ; elif test "$didMatchRepl" = "n" -a -s "$(readlink initrd.img.old >/dev/null 2>&1)" -a -s "$(readlink vmlinuz.old >/dev/null 2>&1)" -a "$newestinitrd" != "$(basename "$(readlink initrd.img.old >/dev/null 2>&1)" >/dev/null 2>&1)" then echo "[INFO] $thisscript: the existing initrd.img.old and vmlinuz.old are fine as-is and left unmodified" 1>&2 elif test "$oldestinitrd" != "$newestinitrd" then #oldinitrdlink="$(basename "$(readlink initrd.img.old 2>/dev/null)" 2>/dev/null)" #if test "/$oldinitrdlink" = "/" -o "/$oldinitrdlink" = "/$newestinitrd" -o \! -s "$oldinitrdlink" #then #ln -sfT "$oldestinitrd" initrd.img.old echo "[INFO] $thisscript: linked /boot/initrd.img.old -> $oldestinitrd" >&2 #ln -sfT "$oldestvmlinuz" vmlinuz.old echo "[INFO] $thisscript: linked /boot/vmlinuz.old -> $oldestvmlinuz" >&2 #fi else echo "[WARN] $thisscript: could not update vmlinuz.old and initrd.img.old as the oldest found versions ($oldestinitrd and $oldestvmlinuz) either were the same as the latest version or they mismatched" 1>&2 fi cd -- "$OLDDIR" 2>/dev/null || true IFS="$OLDIFS" fi