Ma Publicité

Soutenez la Création

Aidez-moi à partager du contenu exclusif.

Soutenir

Comments

Nouveau Drop

Boutique Officielle

Soutenez le blog monblog-sa-abasse et découvrez nos vêtements & accessoires exclusifs en édition limitée.

Découvrir la collection
Paiement Sécurisé
Livraison Monde

Mémoire qui fuit : diagnostiquer un service systemd

Mémoire qui fuit : diagnostiquer un service systemd

Ça commence presque toujours pareil. Une alerte Prometheus un peu vague, un serveur qui « respire mal », et puis un top qui te met mal à l’aise. Un process qui grimpe, grimpe, grimpe. Et tu te dis. Bon. Encore une fuite mémoire.

Sauf que quand c’est un service systemd, tu as souvent deux problèmes au lieu d’un. Pour t'aider dans ce genre de situation, je t'invite à consulter cet article sur diagnostiquer un service systemd qui te fournira un parcours concret pour identifier les problèmes.

  1. comprendre si c’est vraiment une fuite, ou juste du cache, de l’allocateur, un pic temporaire, un truc normal.
  2. isoler la responsabilité. Le binaire ? une lib ? une config ? un comportement qui s’emballe ? un cgroup mal limité ?

Avant de « sortir les gros outils », je veux savoir si c’est une fuite au sens strict. Pour cela, il est essentiel de vérifier la mémoire au niveau système. Voici quelques commandes utiles :

  • bash free -h
  • vmstat 1
  • sar -r 1 10

Deux choses à regarder calmement :

  • la mémoire disponible (available) plutôt que free
  • la swap. Si ça swap et que ça continue de monter, on est dans le dur.

En cas de besoin d'approfondir tes compétences en Linux pour mieux gérer ce type de situation, je te recommande de jeter un œil sur ces 25 commandes Linux qui sauvent ou encore d'explorer les top 5 certifications Linux qui boostent pour améliorer ton expertise dans ce domaine.

regarder le service dans systemd

bash systemctl status monservice systemctl show monservice -p MainPID -p MemoryCurrent -p MemoryPeak

MemoryCurrent et MemoryPeak sont déjà utiles, mais attention : ça dépend du kernel, de la version systemd, et de la façon dont le service est lancé. On veut recouper.

basculer sur les cgroups

bash systemd-cgls systemd-cgtop

systemd-cgtop est souvent la claque visuelle qui confirme : le cgroup du service prend de plus en plus de RAM, même si le process « principal » n’explique pas tout (threads, workers, forks, sous-processus).


Identifier précisément : quel type de mémoire augmente ?

Toutes les mémoires ne se valent pas. Et surtout, toutes les croissances ne sont pas des fuites.

RSS vs VIRT, et les pièges

top ou htop montrent VIRT, RES (RSS), parfois SHR. La plupart du temps :

  • si VIRT grimpe, ce n’est pas forcément grave
  • si RES grimpe en continu et ne redescend jamais, là on parle

Je vérifie avec ps :

bash ps -o pid,ppid,cmd,rss,vsz,%mem --sort=-rss -p $(pidof monservice | tr ' ' ',')

Mais surtout, je vais voir /proc.

bash PID=$(systemctl show -p MainPID --value monservice) cat /proc/$PID/status | egrep 'VmRSS|VmSize|RssAnon|RssFile|RssShmem'

  • RssAnon qui augmente beaucoup : allocations privées (souvent heap)
  • RssFile : mmap de fichiers, caches, libs, parfois normal
  • RssShmem : partagé, shm, tmpfs, attention aux segments qui grossissent

pmap pour découper

bash pmap -x $PID | tail -n 20 pmap -x $PID | sort -k3 -n | tail -n 30

Tu veux repérer des gros segments « anonymous », ou des mappings qui grossissent. Typiquement.


Mesurer au bon endroit : systemd, cgroups v2, et métriques

Sur des distros récentes, tu es souvent en cgroups v2. Donc tu as des compteurs propres.

lire les stats mémoire du cgroup

bash CG=$(systemctl show -p ControlGroup --value monservice) cat /sys/fs/cgroup$CG/memory.current cat /sys/fs/cgroup$CG/memory.peak 2>/dev/null || true cat /sys/fs/cgroup$CG/memory.stat | head -n 30

Dans memory.stat, tu peux voir des infos très parlantes, selon le kernel :

  • anon
  • file
  • slab
  • sock
  • shmem

Si sock monte. Ce n’est pas « de la RAM perdue » par magie. Ça sent les buffers réseau, des sockets pas fermées, ou une charge anormale.


Mettre un garde-fou : limiter, journaliser, redémarrer proprement

Même avant d’avoir trouvé la cause, je veux empêcher le serveur de mourir. systemd est parfait pour ça.

Dans un override :

bash systemctl edit monservice

Puis :

ini [Service] MemoryMax=800M MemoryHigh=700M Restart=on-failure RestartSec=5

  • MemoryHigh déclenche une pression mémoire (throttling)
  • MemoryMax coupe si ça dépasse, c’est brutal mais ça sauve le node

Ensuite :

bash systemctl daemon-reload systemctl restart monservice

Important : si ton service n’est pas « restart-safe », fais ça en maintenance, ou ajoute un mécanisme de drain.


Activer une trace utile : logs, journald, et ce que systemd peut donner

journalctl côté service

bash journalctl -u monservice -S today journalctl -u monservice -f

Je cherche :

  • erreurs répétées
  • timeouts
  • retries infinis
  • gros payloads loggés par erreur
  • warnings de GC (Java, Go, Node, Python avec libs)
  • stack traces

collecter des infos périodiques

Quand je suis sur une fuite lente, je fais souvent un petit script cron ou systemd timer qui capture des snapshots.

Exemple rapide :

bash PID=$(systemctl show -p MainPID --value monservice) date cat /proc/$PID/status | egrep 'VmRSS|RssAnon|RssFile|Threads' ls -l /proc/$PID/fd | wc -l

Le compteur de FDs est bête, mais tellement révélateur. Si les FDs augmentent en continu, tu as peut-être une fuite de descripteurs, et la mémoire suit (buffers, structures internes).


Repérer une fuite de descripteurs ou de connexions

nombre de fichiers ouverts

bash PID=$(systemctl show -p MainPID --value monservice) ls -l /proc/$PID/fd | head ls -l /proc/$PID/fd | wc -l lsof -p $PID | head lsof -p $PID | wc -l

Si tu vois 10k, 50k, 200k. Là tu tiens quelque chose.

sockets qui s’accumulent

bash ss -pant | grep $PID | head -n 50 ss -pant | grep $PID | wc -l

Beaucoup de connexions en CLOSE-WAIT ou TIME-WAIT ? selon le rôle du service, ça peut être normal, ou pas du tout.


Aller plus loin : profilage mémoire selon le runtime

Là on quitte le « générique », et on adapte au type de service.

Java (Spring, etc.)

Tu regardes la heap, le GC, et tu prends un dump si possible.

  • activer des options GC logs
  • jcmd et jmap
  • heap dump, puis analyse avec Eclipse MAT

Un exemple :

bash jcmd $PID GC.heap_info jcmd $PID VM.native_memory summary

Si c’est la mémoire native qui explose, la heap n’explique pas tout. Et ça arrive.

Go

Si le service expose pprof, c’est royal.

  • go tool pprof
  • profils heap dans le temps
  • comparaison de snapshots

Node.js

Tu peux activer --inspect ou faire des heap snapshots. Et souvent, les fuites viennent d’objets retenus, caches non bornés, promesses, listeners.

Python

tracemalloc, objgraph, ou profilage au niveau app. Mais au niveau OS, surveille aussi les threads, les workers, et les pools.


Diagnostiquer au niveau système : valgrind, perf, et les limites du réel

Quand tu peux reproduire en staging, tu as plus de liberté.

valgrind / memcheck

Oui c’est lent. Très. Mais pour une fuite C ou C++ c’est parfois le seul truc qui te donne une preuve nette.

heaptrack

Souvent plus pratique que valgrind pour une appli Linux.

perf et malloc tracing

Selon glibc, tu peux jouer avec MALLOC_ARENA_MAX, glibc tuning, jemalloc, etc. Mais attention : optimiser l’allocateur peut masquer un problème applicatif. Ça soulage, ça ne guérit pas.


Exemple concret : un service qui « fuit » mais c’est un cache sans limite

Scénario classique.

  • service : API qui met en cache des réponses
  • au début, tout va bien
  • puis le trafic augmente
  • le cache grossit
  • jamais de TTL, ou TTL trop long
  • RAM monte, monte, monte

Ce n’est pas une fuite au sens bug mémoire. C’est une fuite au sens produit. Un cache non borné.

Indices typiques :

  • RssAnon monte progressivement
  • aucune anomalie dans les FDs
  • les pics de charge accélèrent la montée
  • redémarrer « règle » le problème temporairement
  • la mémoire retombe à zéro après restart, puis recommence

Solution :

  • borner le cache (taille max)
  • mettre des TTL raisonnables
  • instrumenter le hit ratio
  • ajouter MemoryMax en sécurité

Images utiles à intégrer dans ton article (et dans ta doc interne)

Je te mets des images sous forme de liens Markdown. Tu peux les laisser telles quelles, ou les remplacer par tes propres captures (c’est même mieux). Elles illustrent bien le diagnostic.

vue cgroups et mémoire

exemple htop pour visualiser RES et tri mémoire

schéma simple mémoire Linux (cache vs used)


Checklist rapide : la méthode que j’utilise, dans l’ordre

Quand je suis pressé, je fais ça.

  1. systemd-cgtop pour confirmer que le cgroup grossit
  2. cat /sys/fs/cgroup/.../memory.stat pour savoir si c’est anon, file, sock, etc.
  3. /proc/$PID/status pour RssAnon vs RssFile
  4. /proc/$PID/fd et ss pour exclure fuite de FDs et sockets
  5. logs applicatifs via journalctl -u pour repérer un pattern
  6. garde-fou MemoryHigh et MemoryMax si risque d’OOM
  7. ensuite seulement, profilage runtime (Java, Go pprof, heap dumps)

C’est bête, mais si tu suis cet ordre, tu perds moins de temps.


Conclusion : obtenir une preuve, pas juste une impression

Le piège avec les « fuites mémoire », c’est que tout le monde a une intuition. Mais l’intuition ne redémarre pas un service proprement, et ne corrige pas un bug.

Ce qu’on veut, c’est une preuve mesurable.

  • quel type de mémoire augmente
  • à quel rythme
  • corrélé à quoi (charge, requêtes, tâches planifiées, files)
  • et quel levier est le plus efficace : fix applicatif, limitation, tuning, ou architecture

Si tu veux, tu peux aussi transformer cet article en procédure interne. Et si tu publies ce genre de retours d’expérience, franchement, ça vaut de l’or pour ton équipe.

Pour d’autres articles à la croisée SysAdmin, productivité, et tech business, passe sur https://monblog-sa-abasse.blogspot.com. J’y ajoute régulièrement des ressources, et je garde un ton très terrain. Comme ici.

Questions fréquemment posées

Comment diagnostiquer une fuite mémoire dans un service systemd ?

Pour diagnostiquer une fuite mémoire dans un service systemd, il faut d'abord vérifier si l'augmentation de mémoire est une fuite réelle ou simplement un cache, un pic temporaire ou un comportement normal. Ensuite, il faut isoler la responsabilité : binaire, bibliothèque, configuration, comportement ou cgroup mal limité. Utilisez des commandes comme 'systemctl status', 'systemd-cgtop' et analysez les métriques cgroup pour identifier précisément la source.

Quelles commandes Linux sont utiles pour vérifier la mémoire système en cas de suspicion de fuite ?

Les commandes utiles pour vérifier la mémoire au niveau système incluent 'free -h' pour voir la mémoire disponible plutôt que libre, 'vmstat 1' et 'sar -r 1 10' pour observer l'évolution sur le temps. Il est important de surveiller la mémoire disponible (available) et l'utilisation du swap afin d'évaluer si le système est en difficulté.

Quelle est la différence entre RSS et VIRT dans les outils comme top ou htop ?

Dans top ou htop, 'VIRT' représente la mémoire virtuelle totale utilisée par le processus, ce qui n'est pas forcément inquiétant s'il augmente. En revanche, 'RSS' (Resident Set Size) indique la mémoire physique réellement utilisée. Une augmentation continue et non décroissante du RSS peut indiquer une fuite mémoire sérieuse.

Comment utiliser les fichiers /proc pour analyser la consommation mémoire d'un service systemd ?

Vous pouvez récupérer le PID principal du service avec 'systemctl show -p MainPID'. Ensuite, examinez les fichiers '/proc/$PID/status' en filtrant les champs comme VmRSS, VmSize, RssAnon (allocations privées), RssFile (mappages fichiers), RssShmem (mémoire partagée). Cela permet d'identifier quel type de mémoire augmente et si cela correspond à une fuite.

Que révèle la commande systemd-cgtop dans le contexte d'une fuite mémoire ?

La commande 'systemd-cgtop' affiche l'utilisation des ressources par cgroups. Elle permet de visualiser si le cgroup associé au service consomme de plus en plus de RAM, même si le processus principal ne semble pas responsable. Cela aide à détecter les fuites liées aux threads, workers ou sous-processus non visibles directement.

Quels indicateurs dans memory.stat peuvent aider à comprendre une fuite mémoire sur cgroups v2 ?

Dans '/sys/fs/cgroup$CG/memory.stat', des compteurs comme 'anon' (mémoire anonyme), 'file' (cache fichier), 'slab', 'sock' (sockets réseau), et 'shmem' (mémoire partagée) donnent des indices sur l'origine de la consommation. Par exemple, une montée importante de 'sock' peut indiquer des buffers réseau accumulés ou des sockets non fermées.

Enregistrer un commentaire

0 Commentaires

Comments

Nouveau Drop

Boutique Officielle

Soutenez le blog monblog-sa-abasse et découvrez nos vêtements & accessoires exclusifs en édition limitée.

Découvrir la collection
Paiement Sécurisé
Livraison Monde