From 338f6b87ee9b1e78357bde6bb742b8093b5422b2 Mon Sep 17 00:00:00 2001 From: nocode Date: Sat, 4 Jul 2026 12:56:51 +0200 Subject: [PATCH] feat(recovery): add fws-recovery script for system repair from live environment Add a comprehensive system recovery tool that: - Detects FWS installations on disks including LVM volumes - Mounts target root filesystem with /boot and ESP partitions - Provides interactive menu for common repair operations: - GRUB reinstallation (UEFI and BIOS support) - Initramfs regeneration via mkinitcpio - Pacman database repair and system updates - Interactive chroot shell for manual intervention The script handles automatic LVM activation, filesystem detection via os-release, and proper cleanup on exit. --- .../airootfs/usr/local/bin/fws-recovery | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100755 configs/releng/airootfs/usr/local/bin/fws-recovery diff --git a/configs/releng/airootfs/usr/local/bin/fws-recovery b/configs/releng/airootfs/usr/local/bin/fws-recovery new file mode 100755 index 0000000..1f1e0b9 --- /dev/null +++ b/configs/releng/airootfs/usr/local/bin/fws-recovery @@ -0,0 +1,138 @@ +#!/bin/bash +# ============================================================================ +# FWS — réparation d'une installation existante depuis le live (« point de +# restauration à la Windows »). Lancé par l'entrée de boot « Réparer FWS » +# (paramètre noyau fws.recovery=1 → hook dans /root/.zprofile) ou à la main. +# +# Étapes : détecte les installations FWS sur les disques (LVM compris), +# monte la cible + /boot + ESP (fstab), puis menu : réinstaller GRUB, +# régénérer l'initramfs, réparer pacman, shell chroot. +# arch-chroot (arch-install-scripts, présent sur le live) gère les binds. +# ============================================================================ +set -u +say() { printf '\n\033[1;34m==> %s\033[0m\n' "$*"; } +warn() { printf '\033[1;33m ⚠ %s\033[0m\n' "$*"; } +MNT=/mnt/fws-recovery + +[ "$(id -u)" -eq 0 ] || { echo "root requis"; exit 1; } + +cleanup() { + umount -R "$MNT" 2>/dev/null +} +trap cleanup EXIT + +say "Recherche des installations FWS…" +# Réactive un éventuel LVM (partitionnement auto d'Anaconda : / sur LVM). +vgscan --mknodes >/dev/null 2>&1 +vgchange -ay >/dev/null 2>&1 +udevadm settle --timeout=10 >/dev/null 2>&1 + +mkdir -p "$MNT" +CANDIDATES=() +while read -r dev; do + [ -b "$dev" ] || continue + mount -o ro "$dev" "$MNT" 2>/dev/null || continue + if [ -f "$MNT/etc/os-release" ] && [ -d "$MNT/boot" ] \ + && grep -qiE '^(ID|NAME)=.*fws' "$MNT/etc/os-release" 2>/dev/null; then + name="$(. "$MNT/etc/os-release" 2>/dev/null; echo "${PRETTY_NAME:-FWS}")" + CANDIDATES+=("$dev|$name") + fi + umount "$MNT" 2>/dev/null +done < <(lsblk -rpno NAME,TYPE | awk '$2=="part"||$2=="lvm"{print $1}') + +if [ "${#CANDIDATES[@]}" -eq 0 ]; then + warn "Aucune installation FWS trouvée sur les disques." + warn "Disques visibles :" + lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS + read -rp "Entrée pour ouvrir un shell (exit pour redémarrer). " _ + bash + exit 0 +fi + +echo +i=1 +for c in "${CANDIDATES[@]}"; do + echo " $i) ${c%%|*} — ${c##*|}" + i=$((i+1)) +done +read -rp "Installation à réparer [1] : " pick +pick="${pick:-1}" +ROOTDEV="${CANDIDATES[$((pick-1))]%%|*}" || exit 1 + +say "Montage de $ROOTDEV…" +mount "$ROOTDEV" "$MNT" || { warn "montage impossible"; exit 1; } +# /boot et l'ESP depuis le fstab de la cible (montage par la source UUID/dev). +for mp in /boot /boot/efi; do + src="$(awk -v mp="$mp" '$2==mp && $1!~/^#/{print $1; exit}' "$MNT/etc/fstab" 2>/dev/null)" + [ -n "$src" ] || continue + mount "$(findfs "$src" 2>/dev/null || echo "$src")" "$MNT$mp" 2>/dev/null \ + && echo " $mp monté" || warn "$mp non monté (continuer quand même)" +done + +fix_grub() { + say "Réinstallation de GRUB…" + if [ -d /sys/firmware/efi ]; then + arch-chroot "$MNT" grub-install --target=x86_64-efi \ + --efi-directory=/boot/efi --bootloader-id=FWS --recheck || true + arch-chroot "$MNT" grub-install --target=x86_64-efi \ + --efi-directory=/boot/efi --bootloader-id=FWS --removable --recheck + else + local rootsrc disk + rootsrc="$ROOTDEV" + disk="$(lsblk -spno NAME,TYPE "$rootsrc" 2>/dev/null \ + | awk '$2=="disk"{print $1; exit}' | grep -oE '/dev/[a-z0-9]+')" + [ -n "$disk" ] || { warn "disque BIOS introuvable"; return 1; } + arch-chroot "$MNT" grub-install --target=i386-pc --recheck "$disk" + fi + arch-chroot "$MNT" grub-mkconfig -o /boot/grub/grub.cfg +} + +fix_initramfs() { + say "Régénération de l'initramfs (mkinitcpio -P)…" + arch-chroot "$MNT" mkinitcpio -P +} + +fix_pacman() { + say "Réparation de pacman…" + rm -f "$MNT/var/lib/pacman/db.lck" && echo " verrou db.lck retiré (s'il existait)" + arch-chroot "$MNT" pacman-key --init + arch-chroot "$MNT" pacman-key --populate archlinux + read -rp " Lancer aussi une mise à jour complète (réseau requis) ? [o/N] " _u + case "$_u" in o|O|oui) + cp -f /etc/resolv.conf "$MNT/etc/resolv.conf" 2>/dev/null + arch-chroot "$MNT" pacman -Syu ;; + esac +} + +while :; do + cat <<'MENU' + + ╔════════════════════════════════════════════════════════╗ + ║ FWS — Réparation du système ║ + ╠════════════════════════════════════════════════════════╣ + ║ 1) Réinstaller GRUB (le système ne démarre plus) ║ + ║ 2) Régénérer l'initramfs (mkinitcpio -P) ║ + ║ 3) Réparer pacman (verrou, clés, mise à jour) ║ + ║ 4) Tout réparer (2 puis 1) ║ + ║ 5) Ouvrir un shell DANS le système (chroot) ║ + ║ q) Quitter et redémarrer ║ + ╚════════════════════════════════════════════════════════╝ +MENU + read -rp " Choix : " choice + case "$choice" in + 1) fix_grub ;; + 2) fix_initramfs ;; + 3) fix_pacman ;; + 4) fix_initramfs && fix_grub ;; + 5) say "Shell chroot — « exit » pour revenir au menu." + arch-chroot "$MNT" /bin/bash ;; + q|Q) break ;; + *) warn "choix inconnu" ;; + esac +done + +cleanup +trap - EXIT +say "Réparation terminée." +read -rp "Redémarrer maintenant ? [O/n] " _r +case "$_r" in n|N) bash ;; *) systemctl reboot ;; esac