bpftrace répond en une ligne à la question « qu'est-ce que ma machine est en train de faire, là, maintenant ? ». C'est l'outil eBPF le plus accessible : vous décrivez ce que vous voulez observer dans un langage court, il produit le programme eBPF, le fait vérifier, le charge et affiche le résultat. Cette page couvre la structure du langage, les types de sondes, l'agrégation de données (compteurs, histogrammes) et les pièges, avec des sorties réelles capturées sur une VM Ubuntu 24.04 (noyau 6.8, bpftrace v0.20.2). Pour l'installation et le tout premier contact, voir écrire son premier programme eBPF.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Décomposer un programme bpftrace : sonde, filtre, action
- Choisir le bon type de sonde parmi les milliers disponibles
- Agréger des événements en compteurs et en histogrammes
- Écrire les one-liners qui répondent aux questions de terrain
- Savoir quand bpftrace suffit et quand il faut un autre outil
La structure d'un programme bpftrace
Section intitulée « La structure d'un programme bpftrace »Tout programme bpftrace, du one-liner au script, suit le même schéma en trois parties :
sonde /filtre optionnel/ { action }- La sonde (probe) est le point de déclenchement : « quand cet événement se produit ».
- Le filtre (entre
/.../) est une condition : n'agir que si elle est vraie. - L'action (entre
{...}) est ce qu'on exécute à chaque déclenchement.
Exemple minimal, déjà vu : afficher chaque programme lancé sur la machine. En Linux, démarrer un programme passe par l'appel système execve.
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_execve { printf("%-16s -> %s\n", comm, str(args->filename)); }'Sortie réelle :
bash -> /usr/bin/unamebash -> /usr/bin/idbash -> /usr/bin/sleepIci la sonde est tracepoint:syscalls:sys_enter_execve, il n'y a pas de filtre, et l'action affiche deux informations. Les variables comm (nom du processus) et args->filename (argument de l'appel) sont fournies par bpftrace.
Les variables intégrées
Section intitulée « Les variables intégrées »bpftrace expose des variables prêtes à l'emploi dans chaque action :
| Variable | Contenu |
|---|---|
comm | Nom du processus courant (16 caractères) |
pid / tid | Numéro du processus / du fil d'exécution |
uid | Identifiant de l'utilisateur |
args | Les arguments de la sonde (ex. args->filename) |
retval | La valeur de retour (sur les sondes de sortie) |
nsecs | Horodatage en nanosecondes |
Choisir sa sonde
Section intitulée « Choisir sa sonde »Une sonde désigne où et quand votre action se déclenche. bpftrace en expose un nombre considérable : sur la VM de test, sudo bpftrace -l en dénombre 120 223. Les grandes familles :
tracepoint: un point d'observation stable, garanti par les développeurs du noyau. À préférer quand il existe, car il ne change pas d'une version à l'autre. Exemple :tracepoint:syscalls:sys_enter_openat.kprobe/kretprobe: l'entrée / la sortie de n'importe quelle fonction du noyau. Très puissant, mais lié aux noms internes du noyau, qui peuvent changer. Exemple :kretprobe:vfs_read.uprobe/uretprobe: l'entrée / la sortie d'une fonction d'un programme en espace utilisateur, pas seulement du noyau.interval/profile: un déclenchement périodique (toutes les N secondes, ou à intervalle d'échantillonnage), utile pour les résumés et le profilage.
Pour découvrir les sondes d'un domaine, filtrez la liste :
sudo bpftrace -l 'tracepoint:syscalls:sys_enter_exec*'tracepoint:syscalls:sys_enter_execvetracepoint:syscalls:sys_enter_execveatAgréger : compter et distribuer
Section intitulée « Agréger : compter et distribuer »Afficher chaque événement devient vite illisible sous charge. La force de bpftrace, c'est d'agréger dans des maps, des variables spéciales préfixées par @. Le noyau accumule, et bpftrace n'affiche le résumé qu'à la fin.
Compter les événements
Section intitulée « Compter les événements »Combien d'appels système chaque programme passe-t-il ? On indexe une map par comm et on incrémente un compteur. La sonde interval:s:5 { exit(); } arrête la mesure au bout de cinq secondes.
sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); } interval:s:5 { exit(); }'Sortie réelle (triée par bpftrace, du moins au plus fréquent) :
@[systemd-journal]: 5@[gmain]: 6@[multipathd]: 31@[bpftrace]: 115@[bash]: 3424@[sleep]: 3584@[cat]: 3872@[ls]: 4736@[id]: 7040En une commande, vous savez quels processus sollicitent le plus le noyau. count() est une fonction d'agrégation ; le noyau maintient un compteur par clé, sans renvoyer chaque événement à l'espace utilisateur.
Distribuer en histogramme
Section intitulée « Distribuer en histogramme »Pour une grandeur numérique, un histogramme vaut mille lignes. Quelle est la taille des lectures de fichiers ? On accroche la sortie de vfs_read (la fonction noyau derrière les lectures) et on range retval (le nombre d'octets lus) dans un histogramme avec hist().
sudo bpftrace -e 'kretprobe:vfs_read /retval>0/ { @octets = hist(retval); } interval:s:5 { exit(); }'Sortie réelle :
@octets:[4, 8) 42 |@@@@ |[8, 16) 1 | |[16, 32) 21 |@@ |[256, 512) 42 |@@@@ |[512, 1K) 504 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|[1K, 2K) 21 |@@ |[2K, 4K) 84 |@@@@@@@@ |Chaque ligne est un intervalle de tailles ([512, 1K) = de 512 à 1024 octets), suivi du nombre de lectures et d'une barre proportionnelle. On lit d'un coup d'œil que l'écrasante majorité des lectures fait entre 512 et 1024 octets. Le filtre /retval>0/ écarte les lectures vides ou en erreur.
Un exemple de terrain : qui ouvre quels fichiers
Section intitulée « Un exemple de terrain : qui ouvre quels fichiers »Les deux briques (sonde + action) répondent à une question courante en diagnostic : quel processus touche à quels fichiers ? On trace l'ouverture de fichiers via openat.
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%-14s %s\n", comm, str(args->filename)); }'Sortie réelle :
bash /dev/nullcat /etc/ld.so.cachecat /lib/x86_64-linux-gnu/libc.so.6cat /usr/share/locale/locale.aliascat /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cacheSans installer d'agent ni modifier cat, vous voyez chaque bibliothèque et chaque fichier qu'il ouvre. C'est le genre d'observation qui remplace des heures de strace ciblé, à l'échelle de toute la machine.
Tracer une fonction en espace utilisateur (uprobe)
Section intitulée « Tracer une fonction en espace utilisateur (uprobe) »Jusqu'ici on a observé le noyau. Une uprobe (user probe) fait la même chose sur une fonction d'un programme en espace utilisateur : on s'accroche à une fonction précise d'un binaire, sans en avoir le code source ni le modifier. Utile pour comprendre le comportement d'une application ou d'une bibliothèque.
Prenons un petit programme qui appelle une fonction calcule() en boucle. On trace cette fonction et son premier argument (arg0) :
sudo bpftrace -e 'uprobe:/tmp/prog:calcule { printf("calcule() appelee avec arg=%d\n", arg0); }'Sortie réelle capturée sur la VM :
calcule() appelee avec arg=6calcule() appelee avec arg=7calcule() appelee avec arg=8calcule() appelee avec arg=9La sonde uprobe:/tmp/prog:calcule désigne le binaire puis la fonction. On peut aussi cibler une bibliothèque partagée (par exemple une fonction de la libc) pour observer toutes les applications qui l'utilisent. C'est le pendant, côté espace utilisateur, des kprobes du noyau.
Les outils prêts à l'emploi
Section intitulée « Les outils prêts à l'emploi »Vous n'êtes pas obligé de tout écrire. La communauté maintient une large collection de scripts bpftrace (.bt) et l'écosystème BCC livre des dizaines d'outils packagés (execsnoop, opensnoop, biolatency, tcplife...), installés avec le paquet bpfcc-tools. Ils sont écrits par les mêmes personnes que bpftrace et couvrent la plupart des besoins courants. Reportez-vous à BCC et libbpf pour les utiliser.
Quand bpftrace n'est pas le bon outil
Section intitulée « Quand bpftrace n'est pas le bon outil »bpftrace excelle en investigation ponctuelle : une question, une commande, une réponse, puis on arrête. Il n'est pas conçu pour tourner en permanence comme un service de supervision.
- Pour du profilage continu (voir en permanence où le CPU est consommé, avec un historique), passez à un collecteur dédié comme Parca ou Pyroscope.
- Pour corréler les événements à Kubernetes (quel pod, quel conteneur), un outil comme Inspektor Gadget est plus adapté : voir Inspektor Gadget.
Sécurité et points de vigilance
Section intitulée « Sécurité et points de vigilance »- Opération privilégiée. bpftrace charge des programmes eBPF : il exige
rootou les capacitésCAP_BPFetCAP_PERFMON. Réservez son usage aux administrateurs. - Observation, pas modification. Les sondes de traçage lisent l'état du système ; elles ne le modifient pas. Le risque n'est pas la casse, mais la fuite d'information : une sonde peut révéler des chemins de fichiers, des arguments de commande, des données sensibles. Traitez ses sorties comme des journaux sensibles.
- Coût sous forte charge. Une sonde sur un événement très fréquent (chaque appel système) ajoute un surcoût. En production, filtrez tôt et préférez l'agrégation à l'affichage ligne à ligne.
kproben'est pas stable. Un script basé surkprobe:vfs_readpeut cesser de fonctionner si le noyau renomme la fonction. Préférez untracepointquand il existe.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
ERROR: Could not resolve symbol | Sonde kprobe sur une fonction absente du noyau | Vérifier le nom avec bpftrace -l, ou utiliser un tracepoint |
| Aucune sortie | Aucun événement, ou filtre trop restrictif | Provoquer l'activité, relâcher le filtre |
Permission denied | Lancé sans privilège | sudo, ou CAP_BPF + CAP_PERFMON |
| Sortie tronquée / caractères manquants | Chaîne plus longue que le tampon | Augmenter avec str(ptr, taille) |
| Surcoût visible sur la machine | Sonde sur un événement trop fréquent | Filtrer, agréger, cibler un PID |
À retenir
Section intitulée « À retenir »- Un programme bpftrace, c'est une sonde, un filtre optionnel, une action.
- Les tracepoints sont stables et à préférer ; les kprobes sont plus puissantes mais liées aux noms internes du noyau.
- L'agrégation dans des maps
@(aveccount(),hist()) évite de noyer l'espace utilisateur sous les événements. - Un histogramme répond en une commande à « quelle est la distribution de... ».
- bpftrace est fait pour l'investigation ponctuelle, pas pour tourner en service permanent.
- C'est une opération privilégiée dont les sorties peuvent être sensibles.