# Bug #9 : Collecte RĂ©seau - Erreur jq Invalid JSON - 2025-12-14 ## 🐛 SymptĂŽmes Lors de l'exĂ©cution du benchmark sur **elitedesk** (Intel Core i7-6700), le script crash Ă  l'Ă©tape 6 : ``` [6/8] Collecte des informations rĂ©seau jq: invalid JSON text passed to --argjson Use jq --help for help with command-line options, or see the jq manpage, or online docs at https://jqlang.github.io/jq ``` **Machine affectĂ©e** : elitedesk (HP EliteDesk 800 G2) **CPU** : Intel Core i7-6700 **OS** : Debian 13 (trixie) avec kernel Proxmox 6.17.2-1-pve --- ## 🔍 Analyse du Bug ### Ligne ProblĂ©matique **Fichier** : [scripts/bench.sh](scripts/bench.sh#L661-L663) ```bash # Ancienne version (ligne 661) network_array=$(echo "$network_array" | jq --argjson net "$net_json" '. + [$net]') ``` ### Cause Racine #1 : Regex jq test() Le problĂšme initial venait de la **construction du JSON** pour `wake_on_lan` : ```bash wake_on_lan: ( if $wol == "" then null else ( $wol|test("true";"i") ) end ) ``` **ProblĂšme** : La fonction jq `test()` avec regex **peut Ă©chouer** si `$wol` contient caractĂšres spĂ©ciaux. ### Cause Racine #2 : Parsing ethtool (DĂ©couvert sur elitedesk) **SymptĂŽmes** : - `speed="1000Mb/s"` au lieu de `"1000"` → jq `.tonumber?` Ă©choue - `wol="pumbg\ng"` (avec retour chariot) → pollution du JSON **Origine** : ```bash # Ligne 633 - Pattern AWK ne retire pas correctement "Mb/s" spd=$(echo "$e" | awk -F: '/Speed:/ {gsub(/ Mb\/s/,"",$2); gsub(/^[ \t]+/,"",$2); print $2}') # Retourne: "1000Mb/s" ❌ au lieu de "1000" ✅ # Ligne 636 - Wake-on-LAN contient des retours chariot wol=$(echo "$e" | awk -F: '/Wake-on:/ {gsub(/^[ \t]+/,"",$2); print $2}') # Retourne: "pumbg\ng" ❌ au lieu de "pumbg" ✅ ``` **Impact** : `jq --argjson net "$net_json"` Ă©choue car `net_json` contient du JSON invalide ### Reproduction du Bug ```bash # Simulation de l'erreur wol_supported="" # ou une valeur inattendue jq -n --arg wol "$wol_supported" '{wake_on_lan: ( if $wol == "" then null else ( $wol|test("true";"i") ) end )}' # Peut retourner une erreur jq selon la valeur de $wol ``` --- ## ✅ Solution AppliquĂ©e ### Approche : Conversion Bash → JSON BoolĂ©en Au lieu d'utiliser une regex jq complexe, on **convertit la valeur en bash** avant de passer Ă  jq : **Fichier** : [scripts/bench.sh](scripts/bench.sh#L628-L678) ```bash # CORRECTION #1 : Extraction propre de la vitesse (seulement le nombre) local speed="" wol_supported="" if [[ "$type" = "ethernet" && -x /usr/sbin/ethtool ]]; then local e e=$(sudo ethtool "$iface" 2>/dev/null || true) local spd # Extraire seulement le nombre de la vitesse (enlever "Mb/s") spd=$(echo "$e" | awk -F: '/Speed:/ {gsub(/^[ \t]+/,"",$2); print $2}' | grep -oE '[0-9]+' | head -1) [[ -n "$spd" ]] && speed="$spd" local wol # Extraire Wake-on-LAN et nettoyer (enlever retours chariot) wol=$(echo "$e" | awk -F: '/Wake-on:/ {gsub(/^[ \t]+/,"",$2); print $2}' | tr -d '\n' | head -1) if [[ -n "$wol" && "$wol" != "d" ]]; then wol_supported="true" elif [[ -n "$wol" ]]; then wol_supported="false" fi fi # CORRECTION #2 : Convertir wol_supported en boolĂ©en ou null pour jq local wol_json="null" if [[ "$wol_supported" == "true" ]]; then wol_json="true" elif [[ "$wol_supported" == "false" ]]; then wol_json="false" fi # CORRECTION #3 : GĂ©nĂ©ration JSON avec valeurs propres local net_json net_json=$(jq -n \ --arg name "$iface" \ --arg type "$type" \ --arg mac "$mac" \ --arg ip "${ip_addr:-}" \ --arg speed "$speed" \ --argjson wol "$wol_json" \ # ← Utilise --argjson au lieu de --arg '{ name: $name, type: $type, mac: $mac, ip_address: ( $ip | select(. != "") ), speed_mbps: ( ( $speed | tonumber? ) // null ), # ← $speed contient "1000" pas "1000Mb/s" wake_on_lan: $wol # ← Pas de test() regex ici }' 2>/dev/null || echo '{}') # CORRECTION #4 : Validation JSON avant ajout if [[ "$net_json" != "{}" ]] && echo "$net_json" | jq empty 2>/dev/null; then network_array=$(echo "$network_array" | jq --argjson net "$net_json" '. + [$net]') else log_warn "Interface $iface: JSON invalide, ignorĂ©e" fi ``` ### Avantages de Cette Solution 1. ✅ **SimplicitĂ©** : Conversion directe en bash (plus lisible) 2. ✅ **Robustesse** : `--argjson` avec valeur boolĂ©enne pure (true/false/null) 3. ✅ **Validation** : VĂ©rifie que `net_json` est valide avant utilisation 4. ✅ **Fallback** : Si jq Ă©choue, retourne `'{}'` et log un warning 5. ✅ **CompatibilitĂ©** : Fonctionne avec tous types de cartes rĂ©seau --- ## đŸ§Ș Tests de Validation ### Test 1 : Interface Ethernet Standard ```bash iface="eno1" mac="18:c0:4d:b5:65:74" ip_addr="10.0.1.109" speed="1000" wol_supported="true" # RĂ©sultat attendu { "name": "eno1", "type": "ethernet", "mac": "18:c0:4d:b5:65:74", "ip_address": "10.0.1.109", "speed_mbps": 1000, "wake_on_lan": true } ``` ### Test 2 : Interface sans WoL ```bash wol_supported="" # Non dĂ©tectĂ© # RĂ©sultat attendu { "wake_on_lan": null } ``` ### Test 3 : Interface WiFi ```bash iface="wlan0" type="wifi" mac="aa:bb:cc:dd:ee:ff" wol_supported="false" # RĂ©sultat attendu { "name": "wlan0", "type": "wifi", "mac": "aa:bb:cc:dd:ee:ff", "wake_on_lan": false } ``` ### Test 4 : CaractĂšres SpĂ©ciaux (Edge Case) ```bash # MĂȘme avec des valeurs bizarres, ne doit pas crash wol_supported="g" # Valeur inattendue de ethtool # RĂ©sultat { "wake_on_lan": null # GĂ©rĂ© correctement } ``` --- ## 📊 Impact ### Avant Correction - ❌ **Crash** sur certaines machines (elitedesk) - ❌ **Benchmark incomplet** (arrĂȘt Ă  l'Ă©tape 6/8) - ❌ **Pas de donnĂ©es rĂ©seau** collectĂ©es ### AprĂšs Correction - ✅ **Pas de crash** sur toutes les machines testĂ©es - ✅ **Benchmark complet** (8/8 Ă©tapes) - ✅ **DonnĂ©es rĂ©seau** correctement collectĂ©es - ✅ **Warning informatif** si JSON invalide (au lieu d'un crash) --- ## 🔧 CompatibilitĂ© ### Machines TestĂ©es | Machine | CPU | OS | RĂ©seau | Statut | |---------|-----|----|---------| -------| | **aorus** | Ryzen 9 5900X | Debian 13 | eno1 (ethernet) | ✅ OK | | **elitedesk** | Intel i7-6700 | Debian 13 PVE | Interface ethernet | ✅ **CORRIGÉ** | ### Types d'Interfaces SupportĂ©es - ✅ Ethernet (`eth0`, `eno1`, `enp*`) - ✅ WiFi (`wlan0`, `wl*`) - ✅ Interfaces virtuelles (ignorĂ©es : `lo`, `docker`, `br-`, `veth`) --- ## 🎓 Leçons Apprises ### ProblĂšme avec jq `test()` Regex **Ne pas faire** : ```bash # ❌ Peut crash si $var contient caractĂšres spĂ©ciaux jq -n --arg var "$value" '{field: ($var|test("pattern"))}' ``` **Faire plutĂŽt** : ```bash # ✅ Conversion en bash + passage via --argjson local json_value="null" [[ "$value" == "pattern" ]] && json_value="true" jq -n --argjson field "$json_value" '{field: $field}' ``` ### Toujours Valider le JSON GĂ©nĂ©rĂ© ```bash # ✅ Validation avant utilisation if echo "$json" | jq empty 2>/dev/null; then # JSON valide, on peut l'utiliser array=$(echo "$array" | jq --argjson item "$json" '. + [$item]') else # JSON invalide, log un warning log_warn "JSON invalide, ignorĂ©" fi ``` ### Fallback Robuste ```bash # ✅ Toujours prĂ©voir un fallback json=$(jq -n ... 2>/dev/null || echo '{}') ``` --- ## 📝 Fichiers ModifiĂ©s ### Scripts Bash **[scripts/bench.sh](scripts/bench.sh)** - **Lignes 644-674** : Refactoring collecte rĂ©seau - L644-650 : Conversion `wol_supported` en JSON boolĂ©en - L659 : Utilisation `--argjson` au lieu de regex - L669-674 : Validation JSON avant ajout --- ## ✅ Statut Final **Bug #9** : ✅ **CORRIGÉ** - **Impact** : Bloquant (crash sur certaines machines) - **PrioritĂ©** : Haute - **ComplexitĂ©** : Moyenne - **Solution** : Conversion bash + validation JSON - **Tests** : 2 machines (aorus + elitedesk) --- **Document créé le** : 2025-12-14 Ă  10h30 **Version script** : 1.2.1 (aprĂšs correction) **Machines affectĂ©es** : elitedesk (HP EliteDesk 800 G2) **Status** : ✅ CorrigĂ© et testĂ©