/dev/nvme0 (contrôleur char device) : crw------- root root → root only
/dev/nvme0n1 (namespace block device): brw-rw---- root disk → groupe disk OK
L'agent tourne avec DynamicUser+SupplementaryGroups=disk → a accès au
block device nvme0n1 mais pas au char device nvme0. Les 3 versions
précédentes (v0.1.8-v0.1.10) tentaient toutes d'ouvrir le contrôleur.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
split('n').next() sur "nvme0n1" retourne "" (chaîne vide avant le premier 'n')
→ smartctl -a -j /dev/ (chemin invalide, échec silencieux, aucun SMART collecté)
Correction : rfind('n') trouve le dernier séparateur namespace (nvme0[n]1)
et n[..pos] donne le nom du contrôleur correct (nvme0, nvme10, etc.)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- get_local_ip: construit d'abord la liste des IPs physiques (getifaddrs
avec IFF_POINTOPOINT exclu + type=1 ARPHRD_ETHER requis), puis vérifie
que l'IP choisie par le UDP-connect-trick en fait partie → évite de
retourner une IP VPN même quand le trafic y est routé
- is_physical: remplace le filtrage par préfixe de nom par type kernel
/sys/class/net/<iface>/type == 1 (Ethernet/WiFi) ; exclut WireGuard
(type 65534), tunnels et autres interfaces virtuelles nommées librement
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- /sys/block expose nvme0n1 (namespace), mais smartctl a besoin du contrôleur
nvme0 → déduplication via HashSet pour éviter les doublons nvme0n1/nvme0
- smartctl -j → smartctl -a -j pour inclure nvme_smart_health_information_log
(sans -a, le log de santé NVMe n'est pas dans la sortie JSON)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>