2
This commit is contained in:
129
backend.py
129
backend.py
@@ -1971,17 +1971,40 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str,
|
||||
else:
|
||||
grub_dir_name = "grub"
|
||||
|
||||
# 1. 清空 /boot/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}")
|
||||
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)
|
||||
@@ -1990,9 +2013,9 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str,
|
||||
import shutil
|
||||
shutil.rmtree(item_path)
|
||||
log_debug(f" 删除目录: {item}")
|
||||
log_success(f"✓ 已清空: {grub_path}")
|
||||
log_success(f"✓ 已清理: {grub_path}")
|
||||
except Exception as e:
|
||||
log_warning(f"清空失败: {e}")
|
||||
log_warning(f"清理失败: {e}")
|
||||
|
||||
# 2. 清空 EFI 分区中的 GRUB 相关目录
|
||||
efi_cleanup_dirs = ["GRUB", "grub", "Boot", "boot", "centos", "redhat", "fedora"]
|
||||
@@ -2446,7 +2469,101 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str,
|
||||
|
||||
if not success:
|
||||
log_error(f"GRUB 配置文件更新失败: {stderr}")
|
||||
return False, f"GRUB配置文件更新失败: {stderr}"
|
||||
|
||||
# 备选方案:手动创建基本 grub.cfg
|
||||
log_step("尝试手动创建基本 grub.cfg")
|
||||
|
||||
# 获取根分区信息
|
||||
root_part = None
|
||||
root_uuid = None
|
||||
try:
|
||||
# 从 /etc/fstab 获取根分区
|
||||
fstab_path = os.path.join(mount_point, "etc/fstab")
|
||||
if os.path.exists(fstab_path):
|
||||
with open(fstab_path, 'r') as f:
|
||||
for line in f:
|
||||
if line.startswith('#') or not line.strip():
|
||||
continue
|
||||
parts = line.split()
|
||||
if len(parts) >= 2 and parts[1] == '/':
|
||||
root_part = parts[0]
|
||||
break
|
||||
|
||||
# 获取 UUID
|
||||
if root_part and root_part.startswith('UUID='):
|
||||
root_uuid = root_part[5:].strip('"')
|
||||
elif root_part and root_part.startswith('/dev/'):
|
||||
success_uuid, uuid_out, _ = run_command(
|
||||
["sudo", "blkid", "-s", "UUID", "-o", "value", root_part],
|
||||
f"获取 {root_part} 的 UUID",
|
||||
timeout=10
|
||||
)
|
||||
if success_uuid:
|
||||
root_uuid = uuid_out.strip()
|
||||
except Exception as e:
|
||||
log_warning(f"获取根分区信息失败: {e}")
|
||||
|
||||
# 查找内核文件
|
||||
boot_dir = os.path.join(mount_point, "boot")
|
||||
kernel_files = []
|
||||
initramfs_files = []
|
||||
try:
|
||||
for f in os.listdir(boot_dir):
|
||||
if f.startswith('vmlinuz-'):
|
||||
kernel_files.append(f)
|
||||
elif f.startswith('initramfs-') and f.endswith('.img') and 'kdump' not in f:
|
||||
initramfs_files.append(f)
|
||||
kernel_files.sort(reverse=True)
|
||||
initramfs_files.sort(reverse=True)
|
||||
except Exception as e:
|
||||
log_warning(f"查找内核文件失败: {e}")
|
||||
|
||||
if kernel_files and root_uuid:
|
||||
# 创建基本 grub.cfg
|
||||
grub_cfg_content = f"""# Minimal GRUB config generated by BootRepairTool
|
||||
set timeout=5
|
||||
set default=0
|
||||
|
||||
# Load necessary modules
|
||||
insmod part_gpt
|
||||
insmod xfs
|
||||
insmod fat
|
||||
|
||||
# Search for the root partition by UUID
|
||||
search --no-floppy --fs-uuid --set=root {root_uuid}
|
||||
|
||||
menuentry 'CentOS Linux (Auto)' {{
|
||||
load_video
|
||||
set gfxpayload=keep
|
||||
insmod gzio
|
||||
insmod part_gpt
|
||||
insmod xfs
|
||||
linux /{kernel_files[0]} root=UUID={root_uuid} ro
|
||||
initrd /{initramfs_files[0] if initramfs_files else ''}
|
||||
}}
|
||||
|
||||
menuentry 'CentOS Linux (Rescue)' {{
|
||||
load_video
|
||||
set gfxpayload=keep
|
||||
insmod gzio
|
||||
insmod part_gpt
|
||||
insmod xfs
|
||||
linux /{kernel_files[0]} root=UUID={root_uuid} ro rescue
|
||||
initrd /{initramfs_files[0] if initramfs_files else ''}
|
||||
}}
|
||||
"""
|
||||
try:
|
||||
with open(full_config_path, 'w') as f:
|
||||
f.write(grub_cfg_content)
|
||||
log_success(f"✓ 手动创建 grub.cfg: {full_config_path}")
|
||||
log_info(f" 内核: {kernel_files[0]}")
|
||||
log_info(f" UUID: {root_uuid}")
|
||||
success = True
|
||||
except Exception as e:
|
||||
log_error(f"手动创建 grub.cfg 失败: {e}")
|
||||
return False, f"GRUB配置失败: {stderr}"
|
||||
else:
|
||||
return False, f"GRUB配置失败,无法获取内核或UUID"
|
||||
|
||||
log_success("✓ GRUB 配置文件更新成功")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user