From 797e2c6fb565d47211d17e1d13fdd506d94f6c59 Mon Sep 17 00:00:00 2001 From: allen Date: Tue, 10 Feb 2026 16:32:56 -0800 Subject: [PATCH] Update rhel8-iso-update.sh --- rhel8-iso-update.sh | 273 ++++++++++++++++++++++++++++++++------------ 1 file changed, 198 insertions(+), 75 deletions(-) diff --git a/rhel8-iso-update.sh b/rhel8-iso-update.sh index 65b8a46..5afe5fc 100644 --- a/rhel8-iso-update.sh +++ b/rhel8-iso-update.sh @@ -2,13 +2,47 @@ #=============================================================================== # RHEL 8.10 Offline Update Script -# -# This interactive script guides administrators through applying updates -# from a locally-mounted ISO file. +#=============================================================================== +# +# DESCRIPTION +# Interactive script for applying RHEL 8.10 updates from a local ISO file +# in air-gapped or disconnected environments. +# +# SUPPORTED ISOs +# - Full_Latest_RHEL8_x86_64_patches_*.iso (full monthly update, ~30GB) +# - Incremental_Latest_RHEL8_X86_64_patches_*.iso (incremental update, smaller) +# +# USAGE +# sudo ./rhel8-iso-update.sh +# +# OPTIONS +# The script is fully interactive and will prompt for all choices. +# No command-line arguments are required. +# +# FEATURES +# - Auto-detects ISOs in /var/isos/, /media/, /mnt/, and USB drives +# - Detects and can mount unmounted USB devices +# - Cleans up previous update configuration before applying new updates +# - Creates temporary repo pointing to mounted ISO +# - Checks if reboot is required after updates +# - Optional cleanup of ISO, mount, and repo files when finished +# +# PATHS USED +# ISO Search: /var/isos/, /run/media/, /media/, /mnt/ +# Mount Point: /media/rhel-patches +# Repo File: /etc/yum.repos.d/rhel-patches.repo +# +# REQUIREMENTS +# - Root or sudo access +# - RHEL 8.10 system +# - Sufficient disk space (~35GB for full ISO if copying locally) +# +# AUTHOR +# Cybersecurity Team +# +# LAST UPDATED +# January 2026 # -# ISO: Full_Latest_RHEL8_x86_64_patches_2026-01-13.iso -# Mount Point: /media/JanPatch -# Repo File: /etc/yum.repos.d/JanPatch.repo #=============================================================================== # Colors for output @@ -19,10 +53,13 @@ BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration -ISO_NAME="Full_Latest_RHEL8_x86_64_patches_2026-01-13.iso" -ISO_PATH="/var/isos/${ISO_NAME}" -MOUNT_POINT="/media/JanPatch" -REPO_FILE="/etc/yum.repos.d/JanPatch.repo" +ISO_PATTERN_FULL="Full_Latest_RHEL8_x86_64_patches_*.iso" +ISO_PATTERN_INCREMENTAL="Incremental_Latest_RHEL8_X86_64_patches_*.iso" +ISO_NAME="" # Will be set when ISO is found/selected +ISO_PATH="" # Will be set when ISO is found/selected +ISO_DIR="/var/isos" +MOUNT_POINT="/media/rhel-patches" +REPO_FILE="/etc/yum.repos.d/rhel-patches.repo" # Global variables for tracking FOUND_ISO_LOCATIONS=() @@ -87,6 +124,62 @@ check_root() { # ISO Detection Functions #------------------------------------------------------------------------------- +check_previous_update() { + # Check if there's a previous update still mounted/configured + local needs_cleanup=false + + if mountpoint -q "$MOUNT_POINT" 2>/dev/null; then + needs_cleanup=true + fi + + if [[ -f "$REPO_FILE" ]]; then + needs_cleanup=true + fi + + if [[ "$needs_cleanup" == true ]]; then + print_header "Previous Update Detected" + echo "A previous update configuration was found:" + echo "" + + if mountpoint -q "$MOUNT_POINT" 2>/dev/null; then + echo " - ISO mounted at: ${MOUNT_POINT}" + fi + + if [[ -f "$REPO_FILE" ]]; then + echo " - Repo file exists: ${REPO_FILE}" + fi + + echo "" + + if confirm_action "Would you like to clean up the previous update before continuing?"; then + print_info "Cleaning up previous update..." + + # Disable repo if it exists + if [[ -f "$REPO_FILE" ]]; then + dnf config-manager --set-disabled dvd-rhel-patches 2>/dev/null + rm -f "$REPO_FILE" + print_success "Removed old repo file." + fi + + # Unmount if mounted + if mountpoint -q "$MOUNT_POINT" 2>/dev/null; then + umount "$MOUNT_POINT" + print_success "Unmounted previous ISO." + fi + + # Clean DNF cache + dnf clean all &>/dev/null + + echo "" + print_success "Previous update cleaned up." + else + print_info "Keeping previous configuration. The script will overwrite as needed." + fi + + pause_continue + fi +} + detect_external_media() { # Find mounted external media (USB drives, external disks) # Looks in common mount locations for removable media @@ -96,22 +189,29 @@ detect_external_media() { "/run/media" "/media" "/mnt" + "$ISO_DIR" ) - print_info "Scanning for external media..." + print_info "Scanning for RHEL patch ISOs (Full and Incremental)..." echo "" for base_path in "${search_paths[@]}"; do if [[ -d "$base_path" ]]; then - # Find the ISO file recursively in media locations + # Find Full ISO files while IFS= read -r -d '' file; do found_locations+=("$file") - done < <(find "$base_path" -maxdepth 3 -name "$ISO_NAME" -type f -print0 2>/dev/null) + done < <(find "$base_path" -maxdepth 3 -name "$ISO_PATTERN_FULL" -type f -print0 2>/dev/null) + + # Find Incremental ISO files + while IFS= read -r -d '' file; do + found_locations+=("$file") + done < <(find "$base_path" -maxdepth 3 -name "$ISO_PATTERN_INCREMENTAL" -type f -print0 2>/dev/null) fi done - # Return results via global variable - FOUND_ISO_LOCATIONS=("${found_locations[@]}") + # Sort by filename (newest date typically last) + IFS=$'\n' FOUND_ISO_LOCATIONS=($(sort -u <<< "${found_locations[*]}")); unset IFS +} } detect_unmounted_usb() { @@ -151,21 +251,25 @@ show_iso_search_menu() { local option_paths=() local count=1 - echo "Where would you like to load the ISO from?" + echo "Found the following RHEL patch ISO files:" echo "" - # Option: Default location if exists - if [[ -f "$ISO_PATH" ]]; then - echo " ${count}) Default location: ${ISO_PATH}" - options+=("default") - option_paths+=("$ISO_PATH") - ((count++)) - fi - - # Options: Found on external media + # Options: Found ISO files for location in "${FOUND_ISO_LOCATIONS[@]}"; do - echo " ${count}) External media: ${location}" - options+=("external") + local filename=$(basename "$location") + local dir=$(dirname "$location") + local iso_type="Unknown" + + # Determine ISO type + if [[ "$filename" == Full_* ]]; then + iso_type="Full" + elif [[ "$filename" == Incremental_* ]]; then + iso_type="Incremental" + fi + + echo " ${count}) [${iso_type}] ${filename}" + echo " Location: ${dir}" + options+=("found") option_paths+=("$location") ((count++)) done @@ -208,8 +312,9 @@ show_iso_search_menu() { local chosen_path="${option_paths[$idx]}" case "$chosen_option" in - "default"|"external") + "found") ISO_PATH="$chosen_path" + ISO_NAME=$(basename "$ISO_PATH") return 0 ;; "mount_usb") @@ -220,6 +325,7 @@ show_iso_search_menu() { read -p "Enter full path to ISO file: " custom_path if [[ -f "$custom_path" ]]; then ISO_PATH="$custom_path" + ISO_NAME=$(basename "$ISO_PATH") return 0 else print_error "File not found: ${custom_path}" @@ -244,27 +350,29 @@ mount_usb_device() { if mount "$device" "$mount_dir"; then print_success "Mounted ${device} to ${mount_dir}" - # Search for ISO on mounted device - local found_iso=$(find "$mount_dir" -maxdepth 2 -name "$ISO_NAME" -type f 2>/dev/null | head -1) + # Search for ISO on mounted device using both patterns + local found_iso=$(find "$mount_dir" -maxdepth 2 \( -name "$ISO_PATTERN_FULL" -o -name "$ISO_PATTERN_INCREMENTAL" \) -type f 2>/dev/null | head -1) if [[ -n "$found_iso" ]]; then print_success "Found ISO: ${found_iso}" + ISO_NAME=$(basename "$found_iso") - if confirm_action "Copy ISO to ${ISO_PATH}? (This will take several minutes for 30GB)"; then + if confirm_action "Copy ISO to ${ISO_DIR}/${ISO_NAME}? (This will take several minutes for large ISOs)"; then print_info "Copying ISO... This may take a while." # Ensure target directory exists - mkdir -p "$(dirname "$ISO_PATH")" + mkdir -p "$ISO_DIR" # Copy with progress using rsync if available, otherwise cp if command -v rsync &>/dev/null; then - rsync -ah --progress "$found_iso" "$ISO_PATH" + rsync -ah --progress "$found_iso" "${ISO_DIR}/${ISO_NAME}" else - cp -v "$found_iso" "$ISO_PATH" + cp -v "$found_iso" "${ISO_DIR}/${ISO_NAME}" fi - if [[ -f "$ISO_PATH" ]]; then + if [[ -f "${ISO_DIR}/${ISO_NAME}" ]]; then print_success "ISO copied successfully." + ISO_PATH="${ISO_DIR}/${ISO_NAME}" umount "$mount_dir" rmdir "$mount_dir" return 0 @@ -279,7 +387,11 @@ mount_usb_device() { return 0 fi else - print_error "ISO file not found on ${device}" + print_error "No RHEL patch ISO found on ${device}" + echo "Looking for files matching:" + echo " - ${ISO_PATTERN_FULL}" + echo " - ${ISO_PATTERN_INCREMENTAL}" + echo "" echo "Files on device:" ls -la "$mount_dir" | head -10 fi @@ -301,14 +413,17 @@ mount_usb_device() { show_welcome() { clear print_header "RHEL 8.10 Offline Update Script" - echo "This script will guide you through applying updates from the ISO file:" + echo "This script will guide you through applying updates from a patch ISO." echo "" - echo " ISO File: ${ISO_NAME}" - echo " Mount Point: ${MOUNT_POINT}" - echo " Repo File: ${REPO_FILE}" + echo " Supported ISOs:" + echo " - Full: ${ISO_PATTERN_FULL}" + echo " - Incremental: ${ISO_PATTERN_INCREMENTAL}" + echo "" + echo " Mount Point: ${MOUNT_POINT}" + echo " Repo File: ${REPO_FILE}" echo "" echo "Steps this script will perform:" - echo " 1. Verify the ISO file exists" + echo " 1. Search for and select the ISO file" echo " 2. Create mount point and mount the ISO" echo " 3. Create the local repository configuration" echo " 4. Refresh the package cache" @@ -326,47 +441,56 @@ show_welcome() { step1_verify_iso() { print_header "Step 1: Locate ISO File" - print_step "1" "Searching for ISO file..." + print_step "1" "Searching for RHEL patch ISO files..." - # Detect external media with ISO + # Detect ISOs in all locations detect_external_media detect_unmounted_usb - # Check if ISO exists in default location - local iso_found=false - if [[ -f "$ISO_PATH" ]]; then - iso_found=true - fi - - # Check if found on external media + # Check if any ISOs were found if [[ ${#FOUND_ISO_LOCATIONS[@]} -gt 0 ]]; then - iso_found=true - fi - - # Show what we found - if [[ "$iso_found" == true ]] || [[ ${#UNMOUNTED_USB_DEVICES[@]} -gt 0 ]]; then - # If only one option (default location) and no USB, use it directly - if [[ -f "$ISO_PATH" ]] && [[ ${#FOUND_ISO_LOCATIONS[@]} -eq 0 ]] && [[ ${#UNMOUNTED_USB_DEVICES[@]} -eq 0 ]]; then - print_success "ISO file found: ${ISO_PATH}" + # If only one ISO found, confirm and use it + if [[ ${#FOUND_ISO_LOCATIONS[@]} -eq 1 ]] && [[ ${#UNMOUNTED_USB_DEVICES[@]} -eq 0 ]]; then + ISO_PATH="${FOUND_ISO_LOCATIONS[0]}" + ISO_NAME=$(basename "$ISO_PATH") + print_success "Found ISO: ${ISO_NAME}" + print_info "Location: $(dirname "$ISO_PATH")" + local size=$(du -h "$ISO_PATH" | cut -f1) print_info "File size: ${size}" + + if ! confirm_action "Use this ISO?"; then + if ! show_iso_search_menu; then + exit 1 + fi + fi else - # Multiple options available - show menu + # Multiple options - show menu if ! show_iso_search_menu; then print_error "Failed to locate ISO file." exit 1 fi - print_success "Using ISO: ${ISO_PATH}" + fi + + print_success "Selected: ${ISO_NAME}" + + elif [[ ${#UNMOUNTED_USB_DEVICES[@]} -gt 0 ]]; then + # No ISOs found but unmounted USB detected + print_info "No ISO files found, but unmounted USB devices detected." + if ! show_iso_search_menu; then + exit 1 fi else # Nothing found anywhere - print_error "ISO file not found." + print_error "No RHEL patch ISO files found." echo "" - echo "The script searched for: ${ISO_NAME}" + echo "The script searched for:" + echo " - ${ISO_PATTERN_FULL}" + echo " - ${ISO_PATTERN_INCREMENTAL}" echo "" echo "Locations checked:" - echo " - ${ISO_PATH}" + echo " - ${ISO_DIR}/" echo " - /run/media/*/ (mounted USB drives)" echo " - /media/*/" echo " - /mnt/*/" @@ -376,17 +500,15 @@ step1_verify_iso() { read -p "Enter full path to ISO file: " custom_path if [[ -f "$custom_path" ]]; then ISO_PATH="$custom_path" - print_success "Using ISO: ${ISO_PATH}" + ISO_NAME=$(basename "$ISO_PATH") + print_success "Using ISO: ${ISO_NAME}" else print_error "File not found: ${custom_path}" exit 1 fi else echo "" - echo "Please copy the ISO to /var/isos/ and run this script again." - echo "" - echo "Example from USB drive:" - echo " cp /run/media/\$(whoami)/USBDRIVE/${ISO_NAME} /var/isos/" + echo "Please copy the ISO to ${ISO_DIR}/ and run this script again." exit 1 fi fi @@ -460,10 +582,10 @@ step3_create_repo() { fi # Create the repo file - cat > "$REPO_FILE" << 'EOF' + cat > "$REPO_FILE" << EOF [dvd-rhel-patches] name=DVD for RHEL Patches -baseurl=file:///media/JanPatch +baseurl=file://${MOUNT_POINT} enabled=1 gpgcheck=0 EOF @@ -611,10 +733,10 @@ step8_cleanup() { fi fi - # Delete ISO (only if it's in /var/isos, not on USB) - if [[ -f "/var/isos/$ISO_NAME" ]]; then - if confirm_action "Delete the ISO file (/var/isos/${ISO_NAME})? This will free up ~30GB."; then - rm -f "/var/isos/$ISO_NAME" + # Delete ISO (only if it's in ISO_DIR, not on USB) + if [[ -n "$ISO_NAME" ]] && [[ -f "${ISO_DIR}/${ISO_NAME}" ]]; then + if confirm_action "Delete the ISO file (${ISO_DIR}/${ISO_NAME})? This will free up ~30GB."; then + rm -f "${ISO_DIR}/${ISO_NAME}" print_success "ISO file deleted." fi fi @@ -650,6 +772,7 @@ show_complete() { main() { check_root show_welcome + check_previous_update step1_verify_iso step2_mount_iso step3_create_repo @@ -662,4 +785,4 @@ main() { } # Run main function -main +main \ No newline at end of file