diff --git a/__pycache__/backend.cpython-39.pyc b/__pycache__/backend.cpython-39.pyc index 2319b42..117495d 100644 Binary files a/__pycache__/backend.cpython-39.pyc and b/__pycache__/backend.cpython-39.pyc differ diff --git a/backend.py b/backend.py index 6fe8d39..77f7389 100644 --- a/backend.py +++ b/backend.py @@ -1026,63 +1026,76 @@ def _auto_install_grub(mount_point: str, distro_type: str) -> bool: return False +def _get_grub_cmd_path(mount_point: str, distro_type: str) -> Tuple[Optional[str], Optional[str]]: + """ + 查找 GRUB 命令的完整路径。 + 返回: (grub_install_path, grub_mkconfig_path) 或 (None, None) + """ + # 可能的命令名 + install_names = ["grub2-install", "grub-install"] + mkconfig_names = ["grub2-mkconfig", "grub-mkconfig"] + + # 可能的目录 + dirs = ["/usr/sbin", "/sbin", "/usr/bin", "/bin"] + + install_path = None + mkconfig_path = None + + for name in install_names: + for dir_path in dirs: + full_path = os.path.join(mount_point, dir_path.lstrip('/'), name) + if os.path.exists(full_path): + install_path = os.path.join(dir_path, name) + break + if install_path: + break + + for name in mkconfig_names: + for dir_path in dirs: + full_path = os.path.join(mount_point, dir_path.lstrip('/'), name) + if os.path.exists(full_path): + mkconfig_path = os.path.join(dir_path, name) + break + if mkconfig_path: + break + + return install_path, mkconfig_path + + +# 全局变量存储找到的命令路径 +_grub_install_cmd: Optional[str] = None +_grub_mkconfig_cmd: Optional[str] = None + + def check_chroot_environment(mount_point: str, distro_type: str = "unknown") -> Tuple[bool, str]: """ 检查 chroot 环境是否可用。 检测可用的 GRUB 命令及其版本。 如果缺少 GRUB 命令,尝试自动安装。 """ + global _grub_install_cmd, _grub_mkconfig_cmd + log_step("检查 chroot 环境", f"挂载点: {mount_point}") - # 检查关键命令是否存在(在 PATH 中) - critical_commands = ["grub-install", "grub-mkconfig", "update-grub", "grub2-install", "grub2-mkconfig"] - found_commands = [] + # 首先尝试找到命令路径 + install_path, mkconfig_path = _get_grub_cmd_path(mount_point, distro_type) - for cmd in critical_commands: - success, _, _ = run_command(["sudo", "chroot", mount_point, "which", cmd], - f"检查命令 {cmd}", timeout=10) - if success: - found_commands.append(cmd) - log_info(f" ✓ 找到命令: {cmd}") - else: - log_debug(f" ✗ 未找到命令: {cmd}") - - # 如果在 PATH 中未找到,检查常见的sbin路径(某些发行版sbin不在默认PATH中) - if not found_commands: - log_info("在 PATH 中未找到命令,检查 sbin 目录...") - sbin_paths = [ - "/usr/sbin/grub2-install", - "/usr/sbin/grub2-mkconfig", - "/usr/sbin/grub-install", - "/usr/sbin/grub-mkconfig", - "/sbin/grub2-install", - "/sbin/grub2-mkconfig", - ] - - for sbin_path in sbin_paths: - full_path = mount_point + sbin_path - if os.path.exists(full_path): - cmd_name = os.path.basename(sbin_path) - found_commands.append(cmd_name) - log_info(f" ✓ 找到命令: {sbin_path}") - - if not found_commands: - log_warning(f"chroot 环境中未找到关键的 GRUB 命令") - log_info(f"尝试自动安装 GRUB 包...") + if install_path and mkconfig_path: + log_info(f" ✓ 找到 grub-install: {install_path}") + log_info(f" ✓ 找到 grub-mkconfig: {mkconfig_path}") + _grub_install_cmd = install_path + _grub_mkconfig_cmd = mkconfig_path + else: + log_warning("未找到 GRUB 命令,尝试自动安装...") # 尝试自动安装 if _auto_install_grub(mount_point, distro_type): - # 重新检查命令 - log_info("重新检查 GRUB 命令...") - for cmd in critical_commands: - success, _, _ = run_command(["sudo", "chroot", mount_point, "which", cmd], - f"检查命令 {cmd}", timeout=10) - if success: - found_commands.append(cmd) - log_info(f" ✓ 找到命令: {cmd}") - - if found_commands: + # 重新查找 + install_path, mkconfig_path = _get_grub_cmd_path(mount_point, distro_type) + if install_path and mkconfig_path: log_success("✓ 自动安装成功,GRUB 命令已可用") + _grub_install_cmd = install_path + _grub_mkconfig_cmd = mkconfig_path else: log_error("✗ 自动安装后仍未找到 GRUB 命令") return False, "自动安装 GRUB 失败,请手动安装" @@ -1098,9 +1111,8 @@ def check_chroot_environment(mount_point: str, distro_type: str = "unknown") -> log_error(f"=" * 60) return False, "自动安装 GRUB 失败" - # 检查 grub-install 版本(优先使用 grub2-install 如果存在) - grub_cmd = "grub2-install" if "grub2-install" in found_commands else "grub-install" - success, stdout, _ = run_command(["sudo", "chroot", mount_point, grub_cmd, "--version"], + # 检查 grub-install 版本 + success, stdout, _ = run_command(["sudo", "chroot", mount_point, _grub_install_cmd, "--version"], "检查 grub-install 版本", timeout=10) if success: log_info(f"grub-install 版本: {stdout.strip()}") @@ -1234,17 +1246,26 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str, use_fallback: 是否安装 EFI fallback 文件 efi_bootloader_id: EFI 启动项名称 """ + global _grub_install_cmd, _grub_mkconfig_cmd + log_step("修复 GRUB", f"目标磁盘: {target_disk}, UEFI: {is_uefi}, 发行版: {distro_type}") if not is_uefi and not validate_device_path(target_disk): log_error(f"无效的目标磁盘路径: {target_disk}") return False, f"无效的目标磁盘路径: {target_disk}" - # 检查 chroot 环境 + # 检查 chroot 环境(这会设置 _grub_install_cmd 和 _grub_mkconfig_cmd) ok, err = check_chroot_environment(mount_point, distro_type) if not ok: return False, err + # 确保命令路径已设置 + if not _grub_install_cmd or not _grub_mkconfig_cmd: + return False, "无法确定 GRUB 命令路径" + + log_info(f"使用 grub-install: {_grub_install_cmd}") + log_info(f"使用 grub-mkconfig: {_grub_mkconfig_cmd}") + chroot_cmd_prefix = ["sudo", "chroot", mount_point] # 检测 Live 环境 @@ -1281,7 +1302,7 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str, log_warning(f"✗ EFI 目录不存在: {efi_check_path}") grub_install_cmd = chroot_cmd_prefix + [ - "grub-install" if distro_type != "centos" else "grub2-install", + _grub_install_cmd, f"--target={efi_target}", "--efi-directory=/boot/efi", f"--bootloader-id={efi_bootloader_id}", @@ -1292,7 +1313,7 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str, if is_live_env: log_info("Live 环境: 优先使用 --removable 模式") removable_cmd = chroot_cmd_prefix + [ - "grub-install" if distro_type != "centos" else "grub2-install", + _grub_install_cmd, f"--target={efi_target}", "--efi-directory=/boot/efi", "--removable", @@ -1312,6 +1333,7 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str, else: log_warning(f"removable 模式失败,尝试标准模式") + install_errors.append(f"removable 模式: {stderr}") if not grub_install_success: @@ -1333,7 +1355,7 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str, # 第二次尝试: removable 模式 log_info("尝试 2/3: Live环境/可移动模式(--removable)...") removable_cmd = chroot_cmd_prefix + [ - "grub-install" if distro_type != "centos" else "grub2-install", + _grub_install_cmd, f"--target={efi_target}", "--efi-directory=/boot/efi", "--removable", @@ -1376,7 +1398,7 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str, log_step("安装 BIOS GRUB") bios_cmd = chroot_cmd_prefix + [ - "grub-install" if distro_type != "centos" else "grub2-install", + _grub_install_cmd, "--target=i386-pc", "--recheck", "--force", @@ -1436,28 +1458,13 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str, # ===== 更新 GRUB 配置 ===== log_step("更新 GRUB 配置文件") - # 确定正确的命令和路径 - grub_update_cmd = [] - config_path = "" - - # 根据发行版确定命令 - grub_install_bin = "grub-install" - grub_mkconfig_bin = "grub-mkconfig" - - if distro_type == "centos": - grub_install_bin = "grub2-install" - grub_mkconfig_bin = "grub2-mkconfig" - elif distro_type == "fedora": - grub_mkconfig_bin = "grub2-mkconfig" - elif distro_type == "opensuse": - grub_mkconfig_bin = "grub2-mkconfig" - - # 检测配置文件路径 + # 确定配置文件路径 possible_config_paths = [ "/boot/grub/grub.cfg", "/boot/grub2/grub.cfg", ] + config_path = "" for cfg_path in possible_config_paths: full_path = os.path.join(mount_point, cfg_path.lstrip('/')) if os.path.exists(os.path.dirname(full_path)): @@ -1474,9 +1481,9 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str, if success: grub_update_cmd = ["update-grub"] else: - grub_update_cmd = [grub_mkconfig_bin, "-o", config_path] + grub_update_cmd = [_grub_mkconfig_cmd, "-o", config_path] else: - grub_update_cmd = [grub_mkconfig_bin, "-o", config_path] + grub_update_cmd = [_grub_mkconfig_cmd, "-o", config_path] log_info(f"使用命令: {' '.join(grub_update_cmd)}") log_info(f"配置文件路径: {config_path}")