first commit
This commit is contained in:
commit
443558bafc
4 changed files with 1099 additions and 0 deletions
74
QUICK_REFERENCE.md
Normal file
74
QUICK_REFERENCE.md
Normal 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
228
README.md
Normal 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
742
grub-repair.sh
Executable 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
55
test-script.sh
Executable 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"
|
||||
Loading…
Add table
Add a link
Reference in a new issue