pez-infra/ansible/dotfiles/scripts/gentoo-kernel-upgrade-systemd
Rasmus Wejlgaard 737d6e0bc1 initial commit
2026-03-28 12:39:41 +00:00

397 lines
12 KiB
Bash
Executable file

#!/bin/bash
#
# Gentoo Kernel Upgrade Script
# This script helps upgrade the gentoo-kernel-bin package safely.
#
# IMPORTANT: This script modifies boot files. A failed upgrade could
# prevent your system from booting. Ensure you have a backup plan.
#
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m' # No Color
EFI_DIR="/boot/efi"
BOOT_DIR="/boot"
# Print functions
info() { echo -e "${BLUE}==>${NC} ${BOLD}$1${NC}"; }
warn() { echo -e "${YELLOW}WARNING:${NC} $1"; }
error() { echo -e "${RED}ERROR:${NC} $1" >&2; }
success() { echo -e "${GREEN}==>${NC} $1"; }
# Check if running as root
check_root() {
if [[ $EUID -ne 0 ]]; then
error "This script must be run as root"
exit 1
fi
}
# Prompt user for confirmation
confirm() {
local prompt="$1"
local response
echo -e "${YELLOW}${prompt}${NC}"
read -p "Type 'yes' to confirm: " response
[[ "$response" == "yes" ]]
}
# Get the currently running kernel version
get_current_version() {
uname -r
}
# Get the latest installed kernel version from /usr/src
get_latest_installed_version() {
local latest
latest=$(ls -1d /usr/src/linux-*-gentoo-dist 2>/dev/null | sort -V | tail -1 | sed 's|.*/linux-||')
echo "$latest"
}
# Check for available updates using emerge
check_for_updates() {
info "Checking for gentoo-kernel-bin updates..."
echo
# Use emerge to check for updates (pretend mode)
if emerge -pvu gentoo-kernel-bin 2>/dev/null | grep -q "gentoo-kernel-bin"; then
local update_info
update_info=$(emerge -pvu gentoo-kernel-bin 2>/dev/null | grep -E "gentoo-kernel-bin|ebuild")
echo "$update_info"
return 0
else
return 1
fi
}
# Install the kernel update
install_kernel_update() {
info "Installing gentoo-kernel-bin update..."
echo
echo -e "${BOLD}The following command will be executed:${NC}"
echo -e " ${BLUE}emerge gentoo-kernel-bin${NC}"
echo
if ! confirm "Proceed with kernel package installation?"; then
warn "Installation cancelled by user"
return 1
fi
echo
emerge gentoo-kernel-bin
success "Kernel package installed successfully"
}
# Select the new kernel with eselect
select_kernel() {
local new_version="$1"
info "Available kernel versions:"
eselect kernel list
echo
# Find the number corresponding to the new version
local kernel_num
kernel_num=$(eselect kernel list | grep "$new_version" | sed 's/.*\[\([0-9]*\)\].*/\1/')
if [[ -z "$kernel_num" ]]; then
error "Could not find kernel version $new_version in eselect list"
echo "Please select the kernel manually:"
eselect kernel list
read -p "Enter the number to select: " kernel_num
fi
echo -e "${BOLD}The following command will be executed:${NC}"
echo -e " ${BLUE}eselect kernel set $kernel_num${NC}"
echo
if ! confirm "Set kernel $new_version as active?"; then
warn "Kernel selection cancelled by user"
return 1
fi
eselect kernel set "$kernel_num"
# Verify
info "Current kernel symlink:"
eselect kernel list | grep '\*'
echo
}
# Backup current boot files
backup_boot_files() {
info "Backing up current boot files..."
echo -e "${BOLD}The following operations will be performed in ${EFI_DIR}:${NC}"
echo -e " ${BLUE}mv vmlinuz.efi -> vmlinuz.efi.bak${NC}"
echo -e " ${BLUE}mv initramfs.img -> initramfs.img.bak${NC}"
echo
if [[ -f "${EFI_DIR}/vmlinuz.efi.bak" ]] || [[ -f "${EFI_DIR}/initramfs.img.bak" ]]; then
warn "Existing backup files will be overwritten!"
fi
if ! confirm "Backup current boot files?"; then
warn "Backup cancelled by user"
return 1
fi
cd "${EFI_DIR}"
if [[ -f "vmlinuz.efi" ]]; then
mv vmlinuz.efi vmlinuz.efi.bak
success "Backed up vmlinuz.efi"
fi
if [[ -f "initramfs.img" ]]; then
mv initramfs.img initramfs.img.bak
success "Backed up initramfs.img"
fi
echo
}
# Generate new initramfs
generate_initramfs() {
local version="$1"
info "Generating new initramfs for kernel ${version}..."
echo
echo -e "${BOLD}The following command will be executed:${NC}"
echo -e " ${BLUE}${EFI_DIR}/generate_initramfs.sh ${version} ${EFI_DIR}/initramfs.img${NC}"
echo
if ! confirm "Generate initramfs?"; then
warn "Initramfs generation cancelled by user"
return 1
fi
bash "${EFI_DIR}/generate_initramfs.sh" "${version}" "${EFI_DIR}/initramfs.img"
success "Initramfs generated successfully"
echo
}
# Copy new kernel to EFI partition
copy_kernel() {
local version="$1"
local kernel_source="${BOOT_DIR}/kernel-${version}"
info "Copying new kernel to EFI partition..."
echo
if [[ ! -f "$kernel_source" ]]; then
error "Kernel file not found: $kernel_source"
return 1
fi
echo -e "${BOLD}The following command will be executed:${NC}"
echo -e " ${BLUE}cp ${kernel_source} ${EFI_DIR}/vmlinuz.efi${NC}"
echo
if ! confirm "Copy new kernel to EFI partition?"; then
warn "Kernel copy cancelled by user"
return 1
fi
cp "$kernel_source" "${EFI_DIR}/vmlinuz.efi"
success "Kernel copied successfully"
echo
}
# Cleanup old kernel versions from /boot
cleanup_old_versions() {
info "Checking for old kernel versions to clean up..."
echo
# Find old initramfs and kernel files (excluding current version)
local initramfs_to_delete=()
local kernels_to_delete=()
while IFS= read -r f; do
initramfs_to_delete+=("$f")
done < <(ls ${BOOT_DIR}/initramfs-*.img 2>/dev/null | grep -v "$current_version" || true)
while IFS= read -r f; do
kernels_to_delete+=("$f")
done < <(ls ${BOOT_DIR}/kernel-* 2>/dev/null | grep -v "$current_version" || true)
# Check if there's anything to delete
if [[ ${#initramfs_to_delete[@]} -eq 0 ]] && [[ ${#kernels_to_delete[@]} -eq 0 ]]; then
success "No old kernel versions to clean up"
echo
return 0
fi
echo -e "${BOLD}The following files will be DELETED:${NC}"
echo
for f in "${initramfs_to_delete[@]}" "${kernels_to_delete[@]}"; do
echo -e " ${RED}$f${NC}"
done
echo
warn "This action cannot be undone!"
echo
if ! confirm "Delete these old kernel files?"; then
warn "Cleanup cancelled by user"
return 1
fi
echo
for f in "${initramfs_to_delete[@]}" "${kernels_to_delete[@]}"; do
rm -v "$f"
done
echo
success "Old kernel versions cleaned up"
echo
}
# Print summary of what will be done
print_summary() {
local current="$1"
local new="$2"
echo
echo -e "${BOLD}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BOLD}║ GENTOO KERNEL UPGRADE SUMMARY ║${NC}"
echo -e "${BOLD}╚════════════════════════════════════════════════════════════════╝${NC}"
echo
echo -e " Current running kernel: ${YELLOW}${current}${NC}"
echo -e " New kernel version: ${GREEN}${new}${NC}"
echo
echo -e "${BOLD}The following steps will be performed:${NC}"
echo " 1. Backup current vmlinuz.efi and initramfs.img"
echo " 2. Generate new initramfs using dracut"
echo " 3. Copy new kernel to EFI partition"
echo
echo -e "${RED}${BOLD}WARNING: This process modifies boot files!${NC}"
echo -e "${RED}If something goes wrong, your system may not boot.${NC}"
echo -e "${RED}Make sure you have a way to recover (live USB, backup, etc.)${NC}"
echo
}
# Main function
main() {
echo
echo -e "${BOLD}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BOLD}║ GENTOO KERNEL UPGRADE HELPER ║${NC}"
echo -e "${BOLD}╚════════════════════════════════════════════════════════════════╝${NC}"
echo
check_root
local current_version
current_version=$(get_current_version)
info "Currently running kernel: ${current_version}"
echo
# Check for updates
if ! check_for_updates; then
success "No updates available for gentoo-kernel-bin"
echo
local latest_installed
latest_installed=$(get_latest_installed_version)
if [[ "$latest_installed" != "$current_version" ]] && [[ -n "$latest_installed" ]]; then
# Installed kernel differs from running - offer to set up boot files
warn "Installed kernel ($latest_installed) differs from running kernel ($current_version)"
echo
if confirm "Would you like to set up boot files for $latest_installed?"; then
print_summary "$current_version" "$latest_installed"
if ! confirm "Proceed with the upgrade process?"; then
echo "Upgrade cancelled."
exit 0
fi
select_kernel "$latest_installed"
backup_boot_files
generate_initramfs "$latest_installed"
copy_kernel "$latest_installed"
echo
success "Kernel upgrade complete!"
echo
echo -e "${BOLD}Next steps:${NC}"
echo " 1. Reboot your system"
echo " 2. Verify the new kernel is running: uname -r"
echo " 3. Run this script again to clean up old versions"
echo
fi
else
# Running kernel is the newest - offer cleanup
cleanup_old_versions
fi
exit 0
fi
echo
if ! confirm "Would you like to install this kernel update?"; then
echo "Update cancelled."
exit 0
fi
echo
install_kernel_update
# Get the new version after installation
local new_version
new_version=$(get_latest_installed_version)
if [[ -z "$new_version" ]]; then
error "Could not determine new kernel version"
exit 1
fi
print_summary "$current_version" "$new_version"
if ! confirm "Proceed with the upgrade process?"; then
echo "Upgrade process cancelled. Kernel package is installed but boot files unchanged."
exit 0
fi
echo
select_kernel "$new_version"
backup_boot_files
generate_initramfs "$new_version"
copy_kernel "$new_version"
echo
success "Kernel upgrade complete!"
echo
echo -e "${BOLD}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BOLD}║ NEXT STEPS ║${NC}"
echo -e "${BOLD}╚════════════════════════════════════════════════════════════════╝${NC}"
echo
echo " 1. ${YELLOW}Reboot your system${NC}"
echo " 2. Verify the new kernel is running:"
echo " uname -r"
echo " Expected: ${GREEN}${new_version}${NC}"
echo
echo " 3. If the new kernel works correctly, run this script again"
echo " to clean up old versions"
echo
echo " 4. ${RED}If the system fails to boot:${NC}"
echo " - Boot from a live USB"
echo " - Mount your EFI partition"
echo " - Restore backups:"
echo " mv vmlinuz.efi.bak vmlinuz.efi"
echo " mv initramfs.img.bak initramfs.img"
echo
}
main "$@"