Retour à l'accueil

widget qtile : prédiction d'espace disque

Widget DiskSpaceAlert pour qtile prédit l'épuisement de l'espace disque par régression linéaire. Filtre les FS virtuels, utilise l'historique en deque, distingue les menaces actives et stabilisantes. Code complet sans dépendances.

widget qtile prédit la fin de /tmp à l'avance
Advertisement 728x90

Prédire l'épuisement de l'espace disque dans qtile avec un widget personnalisé

Les développeurs de qtile peuvent intégrer le widget DiskSpaceAlert pour anticiper l'épuisement de l'espace disque à l’aide d’une régression linéaire. Il analyse les tendances de l’espace libre sur les systèmes de fichiers réels — en excluant les systèmes virtuels — et déclenche une alerte lorsque la limite zéro est atteinte dans les 24 heures. Le widget hérite de InLoopPollText, qui interroge toutes les 5 secondes via /proc/mounts et os.statvfs, en utilisant un deque pour conserver les données historiques.

Le code fonctionne sans dépendance externe, ce qui le rend idéal pour les environnements de bureau sans Prometheus. La première alerte s’est déclenchée sur /tmp (ext2 sur zram, 16 Go) : des logs en arrière-plan ont rempli la partition, provoquant une panne silencieuse d’un outil Bash.

Filtrer les points de montage

Le widget ignore les systèmes de fichiers virtuels et les chemins système, se concentrant uniquement sur les disques physiques. Des constantes définissent les exclusions :

Google AdInline article slot
DISK_SPACE_SKIP_FS = {
    'sysfs', 'proc', 'devtmpfs', 'devpts', 'tmpfs', 'securityfs',
    'cgroup', 'cgroup2', 'pstore', 'debugfs', 'hugetlbfs', 'mqueue',
    'configfs', 'fusectl', 'efivarfs', 'binfmt_misc', 'autofs',
    'fuse.portal', 'nsfs', 'tracefs', 'bpf', 'ramfs', 'rpc_pipefs',
    'nfsd', 'overlay', 'fuse.gvfsd-fuse',
}
DISK_SPACE_SKIP_PREFIXES = ('/sys/', '/proc/', '/dev/', '/run/')

La fonction get_mountpoints lit /proc/mounts, en ignorant les entrées par type de système de fichiers ou préfixe de chemin. Pour tmpfs sur zram, le filtre n’est pas appliqué — permettant ainsi de détecter des scénarios critiques.

def get_mountpoints(self):
    mounts = []
    try:
        with open('/proc/mounts') as f:
            for line in f:
                parts = line.split()
                if len(parts) < 3:
                    continue
                mountpoint, fstype = parts[1], parts[2]
                if fstype in DISK_SPACE_SKIP_FS:
                    continue
                if any(mountpoint.startswith(p)
                       for p in DISK_SPACE_SKIP_PREFIXES):
                    continue
                mounts.append(mountpoint)
    except OSError:
        pass
    return mounts

Régression linéaire pour la prédiction

La prédiction utilise la méthode des moindres carrés ordinaires (OLS) sans NumPy. Elle modélise l’espace libre selon y(t) = a·t + b, calculant le temps jusqu’à y=0. Les formules sont :

  • a = (n∑(t_i y_i) - ∑t_i ∑y_i) / (n∑t_i² - (∑t_i)²)
  • b = (∑y_i - a ∑t_i) / n

Temps restant : -b / a moins la durée écoulée. Si la pente ≥ 0 ou seconds_left ≤ 0, retourne None.

Google AdInline article slot
@staticmethod
def _predict_exhaustion(history, now):
    n = len(history)
    t = [h[0] - history[0][0] for h in history]
    y = [h[1] for h in history]
    sum_t = sum(t)
    sum_y = sum(y)
    sum_tt = sum(ti * ti for ti in t)
    sum_ty = sum(ti * yi for ti, yi in zip(t, y))
    denom = n * sum_tt - sum_t * sum_t
    if denom == 0:
        return None
    slope = (n * sum_ty - sum_t * sum_y) / denom
    intercept = (sum_y - slope * sum_t) / n
    if slope >= 0:
        return None
    time_to_zero = -intercept / slope
    elapsed = now - history[0][0]
    seconds_left = time_to_zero - elapsed
    if seconds_left > 0:
        return seconds_left / 3600
    return None

Une fenêtre glissante de maxlen=120 (10 minutes à intervalles de 5 secondes) atténue les bruits causés par les fichiers temporaires.

Indication de couleur et logique d’alerte

Deux niveaux d’alerte :

  • Rouge (#FF0000) : consommation active (espace libre en baisse au cours des 30 dernières secondes) ou moins de 10 % disponible.
  • Orange (#FF8800) : épuisement prévu dans les 24 heures, mais la tendance s’est stabilisée.

La méthode _set_color met à jour self.foreground et self.layout.colour efficacement, évitant les redessins inutiles. Texte de l’étiquette : DISK /tmp : 8%libre, 2h restantes.

Google AdInline article slot
def _set_color(self, color):
    self.foreground = color
    if self.layout:
        self.layout.colour = color

L'historique est vidé pour les systèmes de fichiers démontés.

— Editorial Team

Advertisement 728x90

Lire ensuite