From c1f462d2093e16ee495164865a79f57afb8350be Mon Sep 17 00:00:00 2001 From: enzo Date: Wed, 13 May 2026 04:10:01 +0200 Subject: [PATCH] fix(os): parse /etc/os-release line-by-line instead of regex - pct exec returns stdout differently than local cat - Line-by-line parsing is more robust across LXC boundaries - Handles quotes correctly --- full_updater/backend/scanner.py | 55 +++++++++++++++------------------ 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/full_updater/backend/scanner.py b/full_updater/backend/scanner.py index 486b9fe..818a35c 100644 --- a/full_updater/backend/scanner.py +++ b/full_updater/backend/scanner.py @@ -140,43 +140,38 @@ def scan_os(target: Target) -> str: """Récupère le nom, la version complète et le codename de l'OS.""" prefix = [] if target.is_host else ["pct", "exec", target.target_id, "--"] - # 1. Lire /etc/os-release + # 1. Lire /etc/os-release et parser ligne par ligne ok, osrel_out, _ = run_cmd(prefix + ["cat", "/etc/os-release"], timeout=30) - version_id = "" - pretty_name = "" - codename = "" + os_data = {} if ok: - # Priorité 1 : DEBIAN_VERSION_FULL (ex: 13.4) - ver_full_match = re.search(r'DEBIAN_VERSION_FULL="?([^"\n]+)"?', osrel_out) - if ver_full_match: - version_id = ver_full_match.group(1).strip() - # Priorité 2 : VERSION (ex: "13 (trixie)") - if not version_id: - ver_match = re.search(r'VERSION="([^"]+)"', osrel_out) - if ver_match: - version_id = ver_match.group(1).strip() - # Priorité 3 : VERSION_ID (ex: "13") - if not version_id: - ver_match = re.search(r'VERSION_ID="([^"]+)"', osrel_out) - if ver_match: - version_id = ver_match.group(1).strip() - # Nom affichable - pretty_match = re.search(r'PRETTY_NAME="([^"]+)"', osrel_out) - if pretty_match: - pretty_name = pretty_match.group(1).strip() - # Codename - code_match = re.search(r'VERSION_CODENAME="?([^"\n]+)"?', osrel_out) - if code_match: - codename = code_match.group(1).strip() + for line in osrel_out.splitlines(): + line = line.strip() + if "=" in line: + key, val = line.split("=", 1) + # Supprimer les guillemets + val = val.strip().strip('"').strip("'") + os_data[key] = val - # 2. Fallback sur /etc/debian_version si tout vide + # 2. Extraire les champs + version_id = os_data.get("DEBIAN_VERSION_FULL", "") + if not version_id: + version_id = os_data.get("VERSION", "") + if not version_id: + version_id = os_data.get("VERSION_ID", "") + + codename = os_data.get("VERSION_CODENAME", "") + pretty_name = os_data.get("PRETTY_NAME", "") + os_name = os_data.get("NAME", "") + + # 3. Fallback sur /etc/debian_version si tout vide if not version_id: ok, ver_out, _ = run_cmd(prefix + ["cat", "/etc/debian_version"], timeout=30) version_id = ver_out.strip() if ok else "" - # 3. Récupérer le nom via lsb_release - ok, name_out, _ = run_cmd(prefix + ["lsb_release", "-is"], timeout=30) - os_name = name_out.strip() if ok else "" + # 4. Fallback sur lsb_release pour le nom + if not os_name: + ok, name_out, _ = run_cmd(prefix + ["lsb_release", "-is"], timeout=30) + os_name = name_out.strip() if ok else "" if not os_name and pretty_name: return pretty_name