2
This commit is contained in:
153
backend.py
153
backend.py
@@ -2060,6 +2060,80 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str,
|
|||||||
grub_install_success = False
|
grub_install_success = False
|
||||||
install_errors = []
|
install_errors = []
|
||||||
|
|
||||||
|
# ===== 清空并重建 GRUB 环境(针对严重损坏的系统)=====
|
||||||
|
# 这个步骤在 UEFI 和 BIOS 模式下都需要
|
||||||
|
log_step("清空并重建 GRUB 环境")
|
||||||
|
|
||||||
|
# 确定正确的 GRUB 目录名
|
||||||
|
if distro_type in ["centos", "rhel", "fedora", "rocky", "almalinux", "opensuse"]:
|
||||||
|
grub_dir_name = "grub2"
|
||||||
|
else:
|
||||||
|
grub_dir_name = "grub"
|
||||||
|
|
||||||
|
# 1. 检查并恢复 GRUB 模块(从系统包中)
|
||||||
|
log_info("检查 GRUB EFI 模块...")
|
||||||
|
grub_modules_dir = os.path.join(mount_point, f"usr/lib/grub/x86_64-efi")
|
||||||
|
boot_grub_mods = os.path.join(mount_point, "boot", grub_dir_name, "x86_64-efi")
|
||||||
|
|
||||||
|
if os.path.exists(grub_modules_dir):
|
||||||
|
log_info(f"✓ 系统模块目录: {grub_modules_dir}")
|
||||||
|
# 确保 /boot/grub2/x86_64-efi 存在且包含模块
|
||||||
|
if not os.path.exists(boot_grub_mods) or len(os.listdir(boot_grub_mods)) < 10:
|
||||||
|
log_info("复制 GRUB 模块到 /boot...")
|
||||||
|
try:
|
||||||
|
import shutil
|
||||||
|
if os.path.exists(boot_grub_mods):
|
||||||
|
shutil.rmtree(boot_grub_mods)
|
||||||
|
shutil.copytree(grub_modules_dir, boot_grub_mods)
|
||||||
|
mod_count = len(os.listdir(boot_grub_mods))
|
||||||
|
log_success(f"✓ 复制 {mod_count} 个模块到 {boot_grub_mods}")
|
||||||
|
except Exception as e:
|
||||||
|
log_warning(f"复制模块失败: {e}")
|
||||||
|
|
||||||
|
# 2. 清空 /boot/grub* 目录中的配置和临时文件(保留模块和字体)
|
||||||
|
boot_grub_paths = [
|
||||||
|
os.path.join(mount_point, "boot", "grub"),
|
||||||
|
os.path.join(mount_point, "boot", "grub2"),
|
||||||
|
]
|
||||||
|
for grub_path in boot_grub_paths:
|
||||||
|
if os.path.exists(grub_path):
|
||||||
|
log_info(f"清理目录: {grub_path}")
|
||||||
|
try:
|
||||||
|
# 只删除配置文件和临时文件,保留 x86_64-efi 目录和字体
|
||||||
|
preserve_dirs = {"x86_64-efi", "i386-pc", "fonts", "locale"}
|
||||||
|
for item in os.listdir(grub_path):
|
||||||
|
if item in preserve_dirs:
|
||||||
|
continue
|
||||||
|
item_path = os.path.join(grub_path, item)
|
||||||
|
if os.path.isfile(item_path) or os.path.islink(item_path):
|
||||||
|
os.unlink(item_path)
|
||||||
|
log_debug(f" 删除文件: {item}")
|
||||||
|
elif os.path.isdir(item_path):
|
||||||
|
import shutil
|
||||||
|
shutil.rmtree(item_path)
|
||||||
|
log_debug(f" 删除目录: {item}")
|
||||||
|
log_success(f"✓ 已清理: {grub_path}")
|
||||||
|
except Exception as e:
|
||||||
|
log_warning(f"清理失败: {e}")
|
||||||
|
|
||||||
|
# 3. 创建 grubenv 文件(普通文件,不是符号链接)
|
||||||
|
# GRUB2 要求环境块精确为 4096 字节(一个扇区)
|
||||||
|
grubenv_path = os.path.join(mount_point, "boot", grub_dir_name, "grubenv")
|
||||||
|
try:
|
||||||
|
# 构建 4096 字节的 grubenv 内容
|
||||||
|
header = "# GRUB Environment Block\n"
|
||||||
|
saved_entry = "saved_entry=\n"
|
||||||
|
# 计算需要填充的字节数(4096 - header - saved_entry - 结尾的 #)
|
||||||
|
padding_size = 4096 - len(header) - len(saved_entry) - 1
|
||||||
|
content = header + saved_entry + "#" * padding_size
|
||||||
|
with open(grubenv_path, 'w') as f:
|
||||||
|
f.write(content)
|
||||||
|
log_success(f"✓ 创建 grubenv ({os.path.getsize(grubenv_path)} 字节): {grubenv_path}")
|
||||||
|
except Exception as e:
|
||||||
|
log_warning(f"创建 grubenv 失败: {e}")
|
||||||
|
|
||||||
|
log_success("✓ GRUB 环境重建完成")
|
||||||
|
|
||||||
# ===== UEFI 安装 =====
|
# ===== UEFI 安装 =====
|
||||||
if is_uefi or install_hybrid:
|
if is_uefi or install_hybrid:
|
||||||
log_step("安装 UEFI GRUB")
|
log_step("安装 UEFI GRUB")
|
||||||
@@ -2076,62 +2150,10 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str,
|
|||||||
else:
|
else:
|
||||||
log_warning(f"✗ EFI 目录不存在: {efi_check_path}")
|
log_warning(f"✗ EFI 目录不存在: {efi_check_path}")
|
||||||
|
|
||||||
# ===== 清空并重建 GRUB 环境(针对严重损坏的系统)=====
|
# ===== 清空 EFI 分区并重建(UEFI 模式特有)=====
|
||||||
log_step("清空并重建 GRUB 环境")
|
log_step("清空 EFI 分区并重建")
|
||||||
|
|
||||||
# 确定正确的 GRUB 目录名
|
# 1. 清空 EFI 分区中的 GRUB 相关目录
|
||||||
if distro_type in ["centos", "rhel", "fedora", "rocky", "almalinux", "opensuse"]:
|
|
||||||
grub_dir_name = "grub2"
|
|
||||||
else:
|
|
||||||
grub_dir_name = "grub"
|
|
||||||
|
|
||||||
# 1. 检查并恢复 GRUB 模块(从系统包中)
|
|
||||||
log_info("检查 GRUB EFI 模块...")
|
|
||||||
grub_modules_dir = os.path.join(mount_point, f"usr/lib/grub/x86_64-efi")
|
|
||||||
boot_grub_mods = os.path.join(mount_point, "boot", grub_dir_name, "x86_64-efi")
|
|
||||||
|
|
||||||
if os.path.exists(grub_modules_dir):
|
|
||||||
log_info(f"✓ 系统模块目录: {grub_modules_dir}")
|
|
||||||
# 确保 /boot/grub2/x86_64-efi 存在且包含模块
|
|
||||||
if not os.path.exists(boot_grub_mods) or len(os.listdir(boot_grub_mods)) < 10:
|
|
||||||
log_info("复制 GRUB 模块到 /boot...")
|
|
||||||
try:
|
|
||||||
import shutil
|
|
||||||
if os.path.exists(boot_grub_mods):
|
|
||||||
shutil.rmtree(boot_grub_mods)
|
|
||||||
shutil.copytree(grub_modules_dir, boot_grub_mods)
|
|
||||||
mod_count = len(os.listdir(boot_grub_mods))
|
|
||||||
log_success(f"✓ 复制 {mod_count} 个模块到 {boot_grub_mods}")
|
|
||||||
except Exception as e:
|
|
||||||
log_warning(f"复制模块失败: {e}")
|
|
||||||
|
|
||||||
# 2. 清空 /boot/grub* 目录中的配置和临时文件(保留模块和字体)
|
|
||||||
boot_grub_paths = [
|
|
||||||
os.path.join(mount_point, "boot", "grub"),
|
|
||||||
os.path.join(mount_point, "boot", "grub2"),
|
|
||||||
]
|
|
||||||
for grub_path in boot_grub_paths:
|
|
||||||
if os.path.exists(grub_path):
|
|
||||||
log_info(f"清理目录: {grub_path}")
|
|
||||||
try:
|
|
||||||
# 只删除配置文件和临时文件,保留 x86_64-efi 目录和字体
|
|
||||||
preserve_dirs = {"x86_64-efi", "i386-pc", "fonts", "locale"}
|
|
||||||
for item in os.listdir(grub_path):
|
|
||||||
if item in preserve_dirs:
|
|
||||||
continue
|
|
||||||
item_path = os.path.join(grub_path, item)
|
|
||||||
if os.path.isfile(item_path) or os.path.islink(item_path):
|
|
||||||
os.unlink(item_path)
|
|
||||||
log_debug(f" 删除文件: {item}")
|
|
||||||
elif os.path.isdir(item_path):
|
|
||||||
import shutil
|
|
||||||
shutil.rmtree(item_path)
|
|
||||||
log_debug(f" 删除目录: {item}")
|
|
||||||
log_success(f"✓ 已清理: {grub_path}")
|
|
||||||
except Exception as e:
|
|
||||||
log_warning(f"清理失败: {e}")
|
|
||||||
|
|
||||||
# 2. 清空 EFI 分区中的 GRUB 相关目录
|
|
||||||
efi_cleanup_dirs = ["GRUB", "grub", "Boot", "boot", "centos", "redhat", "fedora"]
|
efi_cleanup_dirs = ["GRUB", "grub", "Boot", "boot", "centos", "redhat", "fedora"]
|
||||||
for efi_dir in efi_cleanup_dirs:
|
for efi_dir in efi_cleanup_dirs:
|
||||||
efi_dir_path = os.path.join(mount_point, "boot/efi/EFI", efi_dir)
|
efi_dir_path = os.path.join(mount_point, "boot/efi/EFI", efi_dir)
|
||||||
@@ -2144,10 +2166,9 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str,
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
log_warning(f"删除失败: {e}")
|
log_warning(f"删除失败: {e}")
|
||||||
|
|
||||||
# 3. 重建目录结构
|
# 2. 重建 EFI 目录结构
|
||||||
log_info("重建 GRUB 目录结构...")
|
log_info("重建 EFI 目录结构...")
|
||||||
dirs_to_create = [
|
dirs_to_create = [
|
||||||
os.path.join(mount_point, "boot", grub_dir_name),
|
|
||||||
os.path.join(mount_point, "boot/efi/EFI", efi_bootloader_id),
|
os.path.join(mount_point, "boot/efi/EFI", efi_bootloader_id),
|
||||||
os.path.join(mount_point, "boot/efi/EFI", "Boot"),
|
os.path.join(mount_point, "boot/efi/EFI", "Boot"),
|
||||||
]
|
]
|
||||||
@@ -2158,22 +2179,6 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str,
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
log_warning(f"创建目录失败: {e}")
|
log_warning(f"创建目录失败: {e}")
|
||||||
|
|
||||||
# 4. 创建 grubenv 文件(普通文件,不是符号链接)
|
|
||||||
# GRUB2 要求环境块精确为 4096 字节(一个扇区)
|
|
||||||
grubenv_path = os.path.join(mount_point, "boot", grub_dir_name, "grubenv")
|
|
||||||
try:
|
|
||||||
# 构建 4096 字节的 grubenv 内容
|
|
||||||
header = "# GRUB Environment Block\n"
|
|
||||||
saved_entry = "saved_entry=\n"
|
|
||||||
# 计算需要填充的字节数(4096 - header - saved_entry - 结尾的 #)
|
|
||||||
padding_size = 4096 - len(header) - len(saved_entry) - 1
|
|
||||||
content = header + saved_entry + "#" * padding_size
|
|
||||||
with open(grubenv_path, 'w') as f:
|
|
||||||
f.write(content)
|
|
||||||
log_success(f"✓ 创建 grubenv ({os.path.getsize(grubenv_path)} 字节): {grubenv_path}")
|
|
||||||
except Exception as e:
|
|
||||||
log_warning(f"创建 grubenv 失败: {e}")
|
|
||||||
|
|
||||||
log_success("✓ GRUB 环境重建完成")
|
log_success("✓ GRUB 环境重建完成")
|
||||||
|
|
||||||
# 5. 为独立 /boot 分区创建 EFI 辅助 grub.cfg
|
# 5. 为独立 /boot 分区创建 EFI 辅助 grub.cfg
|
||||||
|
|||||||
Reference in New Issue
Block a user