first commit

This commit is contained in:
robojerk 2025-08-28 11:17:37 -07:00
commit 443558bafc
4 changed files with 1099 additions and 0 deletions

74
QUICK_REFERENCE.md Normal file
View file

@ -0,0 +1,74 @@
# GRUB Repair Quick Reference
## Essential Commands
### 1. System Detection
```bash
sudo ./grub-repair.sh detect
```
### 2. Complete Boot Repair (Recommended)
```bash
sudo ./grub-repair.sh -d /dev/sda -p 1 -b fix-boot
```
### 3. Check Status
```bash
sudo ./grub-repair.sh status
```
### 4. Clean Up
```bash
sudo ./grub-repair.sh clean
```
## Common Scenarios
### Fresh Boot Repair
```bash
# Detect your system first
sudo ./grub-repair.sh detect
# Then repair (replace /dev/sda with your device)
sudo ./grub-repair.sh -d /dev/sda -p 1 -b fix-boot
```
### GRUB Reinstall Only
```bash
# Mount system
sudo ./grub-repair.sh -d /dev/sda -p 1 mount
# Install GRUB
sudo ./grub-repair.sh install-grub
# Update config
sudo ./grub-repair.sh update-grub
# Unmount
sudo ./grub-repair.sh unmount
```
### EFI Partition Check and Repair
```bash
sudo ./grub-repair.sh -d /dev/sda check-efi
```
## Device Identification
- **Find your disk**: `lsblk` or `fdisk -l`
- **EFI partition**: Usually the first partition (e.g., `/dev/sda1`)
- **Root partition**: Usually the second partition (e.g., `/dev/sda2`)
## Safety Tips
- Always use `-b` flag for backup
- Test on non-critical systems first
- Keep live ISO handy for recovery
- Document your partition layout
## Troubleshooting
- **Permission denied**: Use `sudo`
- **Device not found**: Check with `lsblk`
- **Mount fails**: Use `clean` command first
- **Verbose output**: Add `-v` flag

228
README.md Normal file
View file

@ -0,0 +1,228 @@
# GRUB and EFI Repair Script
A comprehensive command-line tool designed to repair GRUB bootloader and EFI boot entries from a live ISO environment. This script is specifically crafted for system administrators and users who need to recover a system that won't boot due to corrupted or missing boot configuration.
## Features
- **Live ISO Detection**: Automatically detects if running from a live ISO environment
- **System Detection**: Identifies available disks, partitions, and bootable systems
- **Safe Mounting**: Properly mounts target systems with all necessary bind mounts
- **GRUB Installation**: Installs/reinstalls GRUB bootloader with proper EFI support
- **Configuration Updates**: Updates GRUB configuration to detect all installed kernels
- **EFI Repair**: Repairs EFI partition and boot entries
- **Backup Creation**: Creates backups before making changes
- **Comprehensive Logging**: Logs all operations for troubleshooting
- **Safe Cleanup**: Properly unmounts and cleans up after operations
## Prerequisites
- **Root Access**: Script must be run as root (use `sudo`)
- **Live ISO Environment**: Designed to run from a live Linux ISO
- **Target System**: An installed Linux system with GRUB bootloader
- **Basic Knowledge**: Understanding of disk partitions and Linux boot process
## Installation
1. Download the script to your live ISO environment
2. Make it executable:
```bash
chmod +x grub-repair.sh
```
3. Run with sudo:
```bash
sudo ./grub-repair.sh [OPTIONS] COMMAND
```
## Usage
### Basic Commands
```bash
# Show help
sudo ./grub-repair.sh --help
# Detect available systems
sudo ./grub-repair.sh detect
# Show current status
sudo ./grub-repair.sh status
# Clean up and unmount
sudo ./grub-repair.sh clean
```
### System Operations
```bash
# Mount a system (e.g., /dev/sda1)
sudo ./grub-repair.sh -d /dev/sda -p 1 mount
# Unmount current system
sudo ./grub-repair.sh unmount
# Create backup of current configuration
sudo ./grub-repair.sh backup
```
### GRUB Operations
```bash
# Install/reinstall GRUB
sudo ./grub-repair.sh install-grub
# Update GRUB configuration
sudo ./grub-repair.sh update-grub
# Check and repair EFI partition
sudo ./grub-repair.sh -d /dev/sda check-efi
```
### Complete Repair
```bash
# Complete boot repair with backup
sudo ./grub-repair.sh -d /dev/sda -p 1 -b fix-boot
# Complete repair without backup
sudo ./grub-repair.sh -d /dev/sda -p 1 fix-boot
```
## Command Line Options
| Option | Long Option | Description |
|--------|-------------|-------------|
| `-h` | `--help` | Show help message |
| `-v` | `--verbose` | Enable verbose output |
| `-d` | `--device` | Specify target device (e.g., /dev/sda) |
| `-p` | `--partition` | Specify partition number (default: 1) |
| `-m` | `--mount` | Specify mount point (default: /mnt) |
| `-b` | `--backup` | Create backup before operations |
| `-f` | `--force` | Force operations without confirmation |
| `-l` | `--log` | Specify log file path |
## Commands Reference
### `detect`
Scans and displays all available disks, partitions, and bootable systems.
### `mount`
Mounts the target system with proper bind mounts for chroot operations.
### `unmount`
Safely unmounts all mounted filesystems in the correct order.
### `backup`
Creates a timestamped backup of current GRUB configuration and EFI contents.
### `install-grub`
Installs or reinstalls GRUB bootloader to the target system.
### `update-grub`
Updates GRUB configuration to detect all installed kernels and OS entries.
### `check-efi`
Checks and repairs EFI partition and boot entries.
### `fix-boot`
Performs a complete boot repair sequence (mount + install + update + repair).
### `status`
Shows current status of mounted systems and available configurations.
### `clean`
Cleans up temporary files and unmounts all systems.
## Typical Workflow
1. **Boot from Live ISO**: Start your system from a live Linux ISO
2. **Detect Systems**: Identify your target system:
```bash
sudo ./grub-repair.sh detect
```
3. **Complete Repair**: Perform the repair in one command:
```bash
sudo ./grub-repair.sh -d /dev/sda -p 1 -b fix-boot
```
4. **Reboot**: Restart your system and test the boot
## Troubleshooting
### Common Issues
- **Permission Denied**: Ensure you're running as root with `sudo`
- **Device Not Found**: Verify device names with `lsblk` or `fdisk -l`
- **Mount Failures**: Check if partitions are already mounted elsewhere
- **GRUB Installation Fails**: Verify EFI partition is properly mounted
### Verbose Mode
Enable detailed output for troubleshooting:
```bash
sudo ./grub-repair.sh -v -d /dev/sda -p 1 fix-boot
```
### Log Files
The script creates detailed logs in `/tmp/grub-repair-YYYYMMDD-HHMMSS.log`
## Safety Features
- **Automatic Backups**: Creates backups before making changes
- **Safe Mounting**: Uses proper bind mounts and handles dependencies
- **Cleanup Traps**: Automatically cleans up on script exit
- **Error Handling**: Comprehensive error checking and reporting
- **Live ISO Detection**: Warns if not running from live environment
## Examples
### Scenario 1: Simple GRUB Reinstall
```bash
# Mount system
sudo ./grub-repair.sh -d /dev/sda -p 1 mount
# Install GRUB
sudo ./grub-repair.sh install-grub
# Update configuration
sudo ./grub-repair.sh update-grub
# Unmount
sudo ./grub-repair.sh unmount
```
### Scenario 2: Complete EFI Repair
```bash
# Complete repair with backup
sudo ./grub-repair.sh -d /dev/sda -p 1 -b fix-boot
```
### Scenario 3: Multiple System Recovery
```bash
# Check available systems
sudo ./grub-repair.sh detect
# Repair first system
sudo ./grub-repair.sh -d /dev/sda -p 1 fix-boot
# Clean up
sudo ./grub-repair.sh clean
# Repair second system
sudo ./grub-repair.sh -d /dev/sdb -p 1 fix-boot
```
## Contributing
This script is designed to be robust and user-friendly. If you encounter issues or have suggestions for improvements, please:
1. Test thoroughly in your environment
2. Document the issue or enhancement
3. Provide detailed error messages and system information
## License
This script is provided as-is for educational and recovery purposes. Use at your own risk and always test in a safe environment first.
## Disclaimer
This tool modifies critical boot configuration files. Always create backups and test in a safe environment before using on production systems. The authors are not responsible for data loss or system damage resulting from the use of this script.

742
grub-repair.sh Executable file
View file

@ -0,0 +1,742 @@
#!/bin/bash
# GRUB and EFI Repair Script
# Designed to run from a live ISO to repair an installed system
# Author: System Administrator
# Version: 1.0
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Global variables
SCRIPT_NAME=$(basename "$0")
MOUNT_POINT="/mnt"
EFI_MOUNT_POINT="/mnt/boot/efi"
GRUB_CFG_PATH="/mnt/boot/grub/grub.cfg"
BACKUP_DIR="/tmp/grub-backup-$(date +%Y%m%d-%H%M%S)"
LOG_FILE=$(mktemp "/tmp/grub-repair-$(date +%Y%m%d-%H%M%S).XXXXXX.log" 2>/dev/null || echo "/tmp/grub-repair-$(date +%Y%m%d-%H%M%S).log")
# Function to print colored output
print_status() {
local color=$1
local message=$2
echo -e "${color}[$(date '+%Y-%m-%d %H:%M:%S')] ${message}${NC}" | tee -a "$LOG_FILE"
}
# Function to print help
show_help() {
cat << EOF
Usage: $SCRIPT_NAME [OPTIONS] COMMAND
GRUB and EFI Repair Script for Live ISO Recovery
OPTIONS:
-h, --help Show this help message
-v, --verbose Enable verbose output
-d, --device DEV Specify target device (e.g., /dev/sda)
-p, --partition N Specify partition number (default: 1)
-m, --mount PATH Specify mount point (default: /mnt)
-b, --backup Create backup before operations
-f, --force Force operations without confirmation
-l, --log FILE Specify log file path
COMMANDS:
detect Detect available disks and partitions
mount Mount target system
unmount Unmount target system
backup Create backup of current GRUB configuration
install-grub Install/reinstall GRUB
update-grub Update GRUB configuration
check-efi Check and repair EFI partition and boot entries
fix-boot Complete boot repair (mount + install + update)
status Show current status and mounted systems
clean Clean up temporary files and unmount
EXAMPLES:
# Detect available systems
$SCRIPT_NAME detect
# Mount system on /dev/sda1
$SCRIPT_NAME -d /dev/sda -p 1 mount
# Complete boot repair with backup
$SCRIPT_NAME -d /dev/sda -p 1 -b fix-boot
# Check and repair EFI only
$SCRIPT_NAME -d /dev/sda check-efi
EOF
}
# Function to check if running as root
check_root() {
if [[ $EUID -ne 0 ]]; then
print_status "$RED" "Error: This script must be run as root (use sudo)"
exit 1
fi
}
# Function to check if running from live ISO
check_live_iso() {
if [[ "$FORCE" == "true" ]]; then
print_status "$YELLOW" "Force mode enabled, skipping live ISO check"
return 0
fi
if ! grep -q "boot=live" /proc/cmdline 2>/dev/null; then
print_status "$YELLOW" "Warning: This doesn't appear to be running from a live ISO"
print_status "$YELLOW" "Continue anyway? (y/N)"
read -r response
if [[ ! "$response" =~ ^[Yy]$ ]]; then
exit 1
fi
fi
}
# Function to detect available disks and partitions
detect_systems() {
print_status "$BLUE" "Detecting available disks and partitions..."
echo "Available disks:"
lsblk -d -o NAME,SIZE,TYPE,MOUNTPOINT
echo -e "\nAvailable partitions:"
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,LABEL
echo -e "\nEFI partitions:"
blkid | grep -i "vfat\|fat32" | grep -i "efi\|boot" || echo "No EFI partitions found"
echo -e "\nLinux partitions:"
blkid | grep -i "ext4\|xfs\|btrfs" || echo "No Linux partitions found"
}
# Function to detect Linux distribution
detect_distribution() {
local mount_point="$1"
# Try to detect distribution from /etc/os-release
if [[ -f "$mount_point/etc/os-release" ]]; then
local distro_name=$(grep "^NAME=" "$mount_point/etc/os-release" | cut -d'"' -f2 | tr '[:upper:]' '[:lower:]')
echo "$distro_name"
return 0
fi
# Fallback: check for distribution-specific files
if [[ -f "$mount_point/etc/debian_version" ]]; then
echo "debian"
return 0
elif [[ -f "$mount_point/etc/redhat-release" ]]; then
echo "fedora"
return 0
elif [[ -f "$mount_point/etc/arch-release" ]]; then
echo "arch"
return 0
elif [[ -f "$mount_point/etc/lsb-release" ]]; then
local distro=$(grep "^DISTRIB_ID=" "$mount_point/etc/lsb-release" | cut -d'=' -f2 | tr '[:upper:]' '[:lower:]')
echo "$distro"
return 0
fi
# Default fallback - will use generic GRUB bootloader ID
echo "generic_grub"
return 1
}
# Function to detect EFI partition
detect_efi_partition() {
local device="$1"
# Get the parent disk name more robustly
local disk
if command -v lsblk >/dev/null 2>&1; then
# Use lsblk to get parent disk (more reliable for NVMe, etc.)
disk=$(lsblk -rno PKNAME "$device" 2>/dev/null | head -1)
# If no parent found, the device might be a disk itself
if [[ -z "$disk" ]]; then
# Check if the device itself is a disk (not a partition)
local device_type=$(lsblk -rno TYPE "$device" 2>/dev/null)
if [[ "$device_type" == "disk" ]]; then
disk="$device"
else
# Fallback: try to extract disk from device path
disk="${device%[0-9]*}"
fi
fi
else
# Fallback: try to extract disk from device path
disk="${device%[0-9]*}"
fi
if [[ -z "$disk" ]]; then
print_status "$YELLOW" "Warning: Could not determine parent disk for $device"
return 1
fi
# Capture blkid output once for efficiency
local blkid_output=$(blkid 2>/dev/null)
# First try to find EFI partition by filesystem type and label
local efi_partition=$(echo "$blkid_output" | grep -i "vfat\|fat32" | grep -i "efi\|boot" | grep "$disk" | head -1 | cut -d: -f1)
if [[ -n "$efi_partition" ]]; then
echo "$efi_partition"
return 0
fi
# Fallback: try common partition numbers (1, 2, 12)
for part_num in 1 2 12; do
local test_partition="${disk}${part_num}"
if [[ -b "$test_partition" ]]; then
local fstype=$(echo "$blkid_output" | grep "$test_partition:" | grep -o 'TYPE="[^"]*"' | cut -d'"' -f2)
if [[ "$fstype" == "vfat" || "$fstype" == "fat32" ]]; then
echo "$test_partition"
return 0
fi
fi
done
# Enhanced fallback: scan all partitions on the disk
if command -v lsblk >/dev/null 2>&1; then
local all_partitions=$(lsblk -rno NAME "$disk" | grep -E "[0-9]+$")
for partition in $all_partitions; do
local full_path="/dev/$partition"
if [[ -b "$full_path" ]]; then
local fstype=$(echo "$blkid_output" | grep "$full_path:" | grep -o 'TYPE="[^"]*"' | cut -d'"' -f2)
if [[ "$fstype" == "vfat" || "$fstype" == "fat32" ]]; then
echo "$full_path"
return 0
fi
fi
done
fi
# If still no EFI partition found, return empty
return 1
}
# Function to mount target system
mount_system() {
local device="$1"
local partition="$2"
if [[ -z "$device" ]]; then
print_status "$RED" "Error: Device not specified. Use -d option."
exit 1
fi
local partition_device="${device}${partition}"
print_status "$BLUE" "Mounting system from $partition_device to $MOUNT_POINT..."
# Check if partition exists
if [[ ! -b "$partition_device" ]]; then
print_status "$RED" "Error: Partition $partition_device does not exist"
exit 1
fi
# Create mount point if it doesn't exist
mkdir -p "$MOUNT_POINT"
# Mount root partition
print_status "$BLUE" "Mounting root partition..."
if ! mount "$partition_device" "$MOUNT_POINT"; then
print_status "$RED" "Error: Failed to mount root partition $partition_device"
exit 1
fi
# Mount necessary filesystems
print_status "$BLUE" "Mounting necessary filesystems..."
# Mount /proc
# Note: We explicitly unmount on failure rather than relying solely on the trap cleanup
# This provides immediate, targeted cleanup and prevents partial mount states
if ! mount --bind /proc "$MOUNT_POINT/proc"; then
print_status "$RED" "Error: Failed to mount /proc"
umount "$MOUNT_POINT"
exit 1
fi
# Mount /sys
if ! mount --bind /sys "$MOUNT_POINT/sys"; then
print_status "$RED" "Error: Failed to mount /sys"
umount "$MOUNT_POINT/proc"
umount "$MOUNT_POINT"
exit 1
fi
# Mount /dev
if ! mount --bind /dev "$MOUNT_POINT/dev"; then
print_status "$RED" "Error: Failed to mount /dev"
umount "$MOUNT_POINT/sys"
umount "$MOUNT_POINT/proc"
umount "$MOUNT_POINT"
exit 1
fi
# Mount /dev/pts
if ! mount --bind /dev/pts "$MOUNT_POINT/dev/pts"; then
print_status "$RED" "Error: Failed to mount /dev/pts"
umount "$MOUNT_POINT/dev"
umount "$MOUNT_POINT/sys"
umount "$MOUNT_POINT/proc"
umount "$MOUNT_POINT"
exit 1
fi
# Mount EFI partition if it exists
local efi_partition=$(detect_efi_partition "$device")
if [[ -n "$efi_partition" && -b "$efi_partition" ]]; then
print_status "$BLUE" "Mounting EFI partition $efi_partition..."
mkdir -p "$EFI_MOUNT_POINT"
mount "$efi_partition" "$EFI_MOUNT_POINT"
else
print_status "$YELLOW" "Warning: EFI partition not found, some operations may fail"
fi
print_status "$GREEN" "System mounted successfully at $MOUNT_POINT"
}
# Function to unmount system
unmount_system() {
print_status "$BLUE" "Unmounting system..."
# Unmount in reverse order
if mountpoint -q "$EFI_MOUNT_POINT"; then
umount "$EFI_MOUNT_POINT"
print_status "$GREEN" "EFI partition unmounted"
fi
if mountpoint -q "$MOUNT_POINT/dev/pts"; then
umount "$MOUNT_POINT/dev/pts"
fi
if mountpoint -q "$MOUNT_POINT/dev"; then
umount "$MOUNT_POINT/dev"
fi
if mountpoint -q "$MOUNT_POINT/sys"; then
umount "$MOUNT_POINT/sys"
fi
if mountpoint -q "$MOUNT_POINT/proc"; then
umount "$MOUNT_POINT/proc"
fi
if mountpoint -q "$MOUNT_POINT"; then
umount "$MOUNT_POINT"
print_status "$GREEN" "Root partition unmounted"
fi
print_status "$GREEN" "System unmounted successfully"
}
# Function to create backup
create_backup() {
print_status "$BLUE" "Creating backup of current GRUB configuration..."
mkdir -p "$BACKUP_DIR"
if [[ -f "$GRUB_CFG_PATH" ]]; then
cp "$GRUB_CFG_PATH" "$BACKUP_DIR/"
print_status "$GREEN" "GRUB config backed up to $BACKUP_DIR"
fi
if [[ -d "$EFI_MOUNT_POINT" ]]; then
cp -r "$EFI_MOUNT_POINT" "$BACKUP_DIR/"
print_status "$GREEN" "EFI directory backed up to $BACKUP_DIR"
fi
print_status "$GREEN" "Backup completed at $BACKUP_DIR"
}
# Function to install GRUB
install_grub() {
print_status "$BLUE" "Installing GRUB..."
# Note: We use mountpoint -q instead of just checking directory existence
# because mountpoint -q verifies the directory is actually mounted, not just exists
if [[ ! -d "$MOUNT_POINT" ]] || ! mountpoint -q "$MOUNT_POINT"; then
print_status "$RED" "Error: System not mounted. Mount first with 'mount' command."
exit 1
fi
# Chroot into the system
print_status "$BLUE" "Chrooting into system to install GRUB..."
# Install GRUB to the mounted system
if chroot "$MOUNT_POINT" grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=grub --recheck; then
print_status "$GREEN" "GRUB installed successfully"
else
print_status "$RED" "Error: GRUB installation failed"
exit 1
fi
}
# Function to update GRUB configuration
update_grub() {
print_status "$BLUE" "Updating GRUB configuration..."
# Note: We use mountpoint -q instead of just checking directory existence
# because mountpoint -q verifies the directory is actually mounted, not just exists
if [[ ! -d "$MOUNT_POINT" ]] || ! mountpoint -q "$MOUNT_POINT"; then
print_status "$RED" "Error: System not mounted. Mount first with 'mount' command."
exit 1
fi
# Update GRUB configuration
if chroot "$MOUNT_POINT" grub-mkconfig -o /boot/grub/grub.cfg; then
print_status "$GREEN" "GRUB configuration updated successfully"
else
print_status "$RED" "Error: GRUB configuration update failed"
exit 1
fi
}
# Function to check EFI partition
check_efi() {
local device="$1"
print_status "$BLUE" "Checking EFI partition..."
if [[ -z "$device" ]]; then
print_status "$RED" "Error: Device not specified. Use -d option."
exit 1
fi
# Detect EFI partition
local efi_partition=$(detect_efi_partition "$device")
if [[ -z "$efi_partition" ]]; then
print_status "$RED" "Error: No EFI partition found on device $device"
exit 1
fi
# Mount EFI partition temporarily
local temp_mount="/tmp/efi-temp"
mkdir -p "$temp_mount"
mount "$efi_partition" "$temp_mount"
# Check EFI contents
print_status "$BLUE" "EFI partition contents:"
ls -la "$temp_mount"
# Check for existing boot entries
if [[ -d "$temp_mount/EFI" ]]; then
print_status "$BLUE" "EFI directory contents:"
find "$temp_mount/EFI" -type f -name "*.efi" 2>/dev/null || echo "No EFI files found"
fi
# Attempt to repair boot entries if efibootmgr is available
if command -v efibootmgr >/dev/null 2>&1; then
print_status "$BLUE" "Attempting to repair EFI boot entries..."
# Get current boot entries
local current_entries=$(efibootmgr | grep -E "^Boot[0-9]+" | wc -l)
print_status "$BLUE" "Current EFI boot entries: $current_entries"
# Try to create a new boot entry for GRUB
local grub_efi_path=""
local grub_efi_name=""
# Search for GRUB EFI binaries in common locations
for grub_path in "EFI/grub/grubx64.efi" "EFI/grub/grub.efi" "EFI/ubuntu/grubx64.efi" "EFI/fedora/grubx64.efi" "EFI/arch/grubx64.efi"; do
if [[ -f "$temp_mount/$grub_path" ]]; then
grub_efi_path="$grub_path"
grub_efi_name=$(basename "$grub_path")
break
fi
done
if [[ -n "$grub_efi_path" ]]; then
print_status "$BLUE" "GRUB EFI file found: $grub_efi_path, attempting to create boot entry..."
# Get the partition number dynamically
local partition_number=$(echo "$efi_partition" | grep -o '[0-9]\+$')
if [[ -n "$partition_number" ]]; then
# Convert path to EFI format (backslashes)
local efi_path=$(echo "$grub_efi_path" | sed 's/\//\\/g')
# Try to detect distribution for better bootloader ID
local bootloader_id="grub"
local bootloader_label="GRUB"
# First try to detect from EFI path
case "$grub_efi_path" in
"EFI/ubuntu/"*)
bootloader_id="ubuntu"
bootloader_label="Ubuntu"
;;
"EFI/fedora/"*)
bootloader_id="fedora"
bootloader_label="Fedora"
;;
"EFI/arch/"*)
bootloader_id="arch"
bootloader_label="Arch Linux"
;;
"EFI/debian/"*)
bootloader_id="debian"
bootloader_label="Debian"
;;
*)
# Try to detect distribution from mounted system if available
if [[ -d "$MOUNT_POINT" ]] && mountpoint -q "$MOUNT_POINT"; then
local detected_distro=$(detect_distribution "$MOUNT_POINT")
case "$detected_distro" in
*ubuntu*)
bootloader_id="ubuntu"
bootloader_label="Ubuntu"
;;
*fedora*|*redhat*|*centos*)
bootloader_id="fedora"
bootloader_label="Fedora/RHEL"
;;
*arch*)
bootloader_id="arch"
bootloader_label="Arch Linux"
;;
*debian*)
bootloader_id="debian"
bootloader_label="Debian"
;;
*)
# Use generic GRUB ID for other distributions
bootloader_id="grub"
bootloader_label="GRUB"
;;
esac
else
# Use generic GRUB ID for other distributions
bootloader_id="grub"
bootloader_label="GRUB"
fi
;;
esac
print_status "$BLUE" "Creating boot entry with ID: $bootloader_id, Label: $bootloader_label"
efibootmgr -c -d "$efi_partition" -p "$partition_number" -l "$efi_path" -L "$bootloader_label" 2>/dev/null || print_status "$YELLOW" "Could not create boot entry for $bootloader_label"
else
print_status "$YELLOW" "Could not determine partition number for $efi_partition"
fi
else
print_status "$YELLOW" "No GRUB EFI binary found in common locations"
fi
else
print_status "$YELLOW" "efibootmgr not available, skipping boot entry repair"
fi
# Unmount temporary mount
umount "$temp_mount"
rmdir "$temp_mount"
print_status "$GREEN" "EFI partition check and repair completed"
}
# Function to show status
show_status() {
print_status "$BLUE" "Current system status:"
echo "Mounted systems:"
# Use direct mountpoint checks for better performance instead of findmnt
# mountpoint -q is more efficient than spawning a new process with findmnt
if mountpoint -q "$MOUNT_POINT"; then
echo "Root system mounted at: $MOUNT_POINT"
fi
if mountpoint -q "$EFI_MOUNT_POINT"; then
echo "EFI system mounted at: $EFI_MOUNT_POINT"
fi
if ! mountpoint -q "$MOUNT_POINT" && ! mountpoint -q "$EFI_MOUNT_POINT"; then
echo "No systems mounted"
fi
echo -e "\nAvailable GRUB configurations:"
find /mnt -name "grub.cfg" 2>/dev/null || echo "No GRUB configs found"
echo -e "\nEFI partition status:"
if mountpoint -q "$EFI_MOUNT_POINT"; then
echo "EFI mounted at: $EFI_MOUNT_POINT"
ls -la "$EFI_MOUNT_POINT" 2>/dev/null || echo "Cannot list EFI contents"
else
echo "EFI not mounted"
fi
echo -e "\nBackup directory:"
if [[ -d "$BACKUP_DIR" ]]; then
echo "Backup available at: $BACKUP_DIR"
ls -la "$BACKUP_DIR"
else
echo "No backup created"
fi
}
# Function to clean up
cleanup() {
print_status "$BLUE" "Cleaning up..."
# Unmount if mounted
if mountpoint -q "$MOUNT_POINT" || mountpoint -q "$EFI_MOUNT_POINT"; then
unmount_system
fi
# Remove temporary mount points
rmdir "$MOUNT_POINT" 2>/dev/null || true
rmdir "$EFI_MOUNT_POINT" 2>/dev/null || true
print_status "$GREEN" "Cleanup completed"
}
# Function to complete boot repair
fix_boot() {
local device="$1"
local partition="$2"
print_status "$BLUE" "Starting complete boot repair..."
# Create backup if requested
if [[ "$CREATE_BACKUP" == "true" ]]; then
create_backup
fi
# Mount system
mount_system "$device" "$partition"
# Install GRUB
install_grub
# Update GRUB configuration
update_grub
# Check and repair EFI
check_efi "$device"
print_status "$GREEN" "Boot repair completed successfully!"
print_status "$BLUE" "You can now reboot your system."
}
# Main script logic
main() {
# Parse command line arguments
local device=""
local partition="1"
local command=""
local CREATE_BACKUP="false"
local FORCE="false"
local VERBOSE="false"
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-v|--verbose)
VERBOSE="true"
shift
;;
-d|--device)
device="$2"
shift 2
;;
-p|--partition)
partition="$2"
shift 2
;;
-m|--mount)
MOUNT_POINT="$2"
EFI_MOUNT_POINT="$MOUNT_POINT/boot/efi"
shift 2
;;
-b|--backup)
CREATE_BACKUP="true"
shift
;;
-f|--force)
FORCE="true"
shift
;;
-l|--log)
LOG_FILE="$2"
shift 2
;;
-*)
print_status "$RED" "Unknown option: $1"
show_help
exit 1
;;
*)
command="$1"
shift
;;
esac
done
# Check if command is provided
if [[ -z "$command" ]]; then
print_status "$RED" "Error: No command specified"
print_status "$RED" "Use '$SCRIPT_NAME --help' to see available commands"
show_help
exit 1
fi
# Check if running as root
check_root
# Check if running from live ISO
check_live_iso
# Set verbose mode
if [[ "$VERBOSE" == "true" ]]; then
set -x
fi
# Execute command
case "$command" in
detect)
detect_systems
;;
mount)
mount_system "$device" "$partition"
;;
unmount)
unmount_system
;;
backup)
create_backup
;;
install-grub)
install_grub
;;
update-grub)
update_grub
;;
check-efi)
check_efi "$device"
;;
fix-boot)
fix_boot "$device" "$partition"
;;
status)
show_status
;;
clean)
cleanup
;;
*)
print_status "$RED" "Error: Unknown command: $command"
show_help
exit 1
;;
esac
}
# Trap to cleanup on exit
trap cleanup EXIT
# Run main function with all arguments
main "$@"

55
test-script.sh Executable file
View file

@ -0,0 +1,55 @@
#!/bin/bash
# Test script for GRUB repair script
# This script tests basic functionality without actually mounting systems
echo "Testing GRUB repair script..."
# Test help functionality
echo "Testing help command..."
./grub-repair.sh --help > /dev/null
if [ $? -eq 0 ]; then
echo "✓ Help command works"
else
echo "✗ Help command failed"
fi
# Test detect command (should work without root)
echo "Testing detect command..."
./grub-repair.sh detect > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "✓ Detect command works"
else
echo "✗ Detect command failed (expected without root)"
fi
# Test invalid command
echo "Testing invalid command..."
./grub-repair.sh invalid-command > /dev/null 2>&1
if [ $? -eq 1 ]; then
echo "✓ Invalid command handling works"
else
echo "✗ Invalid command handling failed"
fi
# Test script syntax
echo "Testing script syntax..."
bash -n grub-repair.sh
if [ $? -eq 0 ]; then
echo "✓ Script syntax is valid"
else
echo "✗ Script syntax errors found"
fi
# Test script permissions
if [ -x grub-repair.sh ]; then
echo "✓ Script is executable"
else
echo "✗ Script is not executable"
fi
echo "Basic tests completed!"
echo ""
echo "To run full tests (requires root):"
echo "sudo ./grub-repair.sh detect"
echo "sudo ./grub-repair.sh --help"