strace sur Linux est l’outil de référence pour comprendre ce qu’un processus fait au niveau du noyau. Quand un programme échoue silencieusement, se bloque ou se comporte de façon inattendue, strace révèle avec précision les appels système en cours — ouvertures de fichiers, connexions réseau, allocations mémoire et gestion des signaux. Ce guide aborde l’utilisation pratique de strace, du traçage de base aux techniques de débogage en production, avec des scénarios concrets illustrant comment diagnostiquer les problèmes que vous rencontrez réellement.
Prérequis
- Un système Linux (toute distribution — strace fonctionne sur toutes)
- Accès root ou
sudo(requis pour tracer des processus appartenant à d’autres utilisateurs) - Compréhension basique des processus Linux et des descripteurs de fichiers
- strace installé (couvert dans la section d’installation ci-dessous)
Installer strace sur Linux
strace est disponible dans les dépôts de paquets de toutes les distributions majeures. Il est peut-être déjà installé sur votre système.
# Debian / Ubuntu
sudo apt install strace
# RHEL / CentOS / Fedora
sudo dnf install strace
# Arch Linux
sudo pacman -S strace
# Alpine Linux
sudo apk add strace
# Vérifier la version installée
strace --version
Sur les images de conteneurs minimales (Alpine, distroless), strace est généralement absent. Installez-le temporairement pour le débogage, puis retirez-le des images de production.
Tracer une Commande dès son Démarrage
L’utilisation la plus simple de strace consiste à le placer devant n’importe quelle commande :
strace ls /tmp
Cette commande affiche chaque appel système que ls effectue, de execve() jusqu’à exit_group(). La sortie est dirigée vers stderr, de sorte que la sortie normale de la commande s’affiche toujours sur stdout.
Lire la sortie de strace
Chaque ligne suit ce format :
syscall_name(arguments...) = valeur_retour
Par exemple :
openat(AT_FDCWD, "/tmp", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
getdents64(3, [{d_ino=2, d_off=1, d_type=DT_DIR, d_name="."},...], 32768) = 480
close(3) = 0
Cela indique que ls a ouvert /tmp en tant que descripteur de fichier 3, a lu les entrées du répertoire, puis l’a fermé. Une valeur de retour de -1 signifie que l’appel a échoué, et strace affiche l’errno correspondant :
openat(AT_FDCWD, "/etc/shadow", O_RDONLY) = -1 EACCES (Permission denied)
Cette seule ligne révèle souvent pourquoi un programme échoue — inutile de lire le code source ou d’ajouter des logs de débogage.
Options utiles au démarrage
# Suivre les processus enfants (fork/clone)
strace -f ./my_app
# Afficher les horodatages de chaque syscall
strace -t ls /tmp
# Afficher le temps relatif entre les syscalls (pour trouver les blocages)
strace -r ls /tmp
# Afficher les arguments de type chaîne en entier (par défaut tronqués à 32 cars)
strace -s 256 ./my_app
# Écrire la sortie dans un fichier plutôt que sur stderr
strace -o /tmp/trace.log ls /tmp
Attacher strace à un Processus en Cours d’Exécution
Il n’est pas nécessaire de redémarrer un processus pour le tracer. Attachez-vous à n’importe quel processus en cours par son PID :
# Trouver le PID
pidof nginx
# ou
ps aux | grep my_app
# S'attacher au processus
sudo strace -p 12345
# S'attacher et suivre tous les threads/enfants
sudo strace -fp 12345
Appuyez sur Ctrl+C pour vous détacher. Le processus tracé continue de s’exécuter normalement — strace ne le tue pas lors du détachement.
Scénario concret : Déboguer une application bloquée
Vous avez une application web en production qui cesse parfois de répondre aux requêtes. Les logs ne montrent rien. Plutôt que de redémarrer à l’aveugle :
# Trouver le PID du worker bloqué
sudo strace -fp $(pidof my_app) -e trace=network,file -s 256 -o /tmp/hang_trace.log
Envoyez une requête de test, puis examinez la trace :
grep -E 'futex|poll|select|epoll_wait' /tmp/hang_trace.log | tail -20
Si vous voyez le processus bloqué dans futex(FUTEX_WAIT) — il attend un verrou mutex (interblocage). S’il est bloqué dans connect() ou poll() avec un long délai — il attend un service amont qui ne répond pas.
Filtrer les Appels Système avec strace
Les traces complètes sont bruyantes. Utilisez -e trace= pour vous concentrer sur ce qui compte :
# Opérations sur les fichiers uniquement (open, read, write, close, stat, etc.)
strace -e trace=file ls /tmp
# Opérations réseau uniquement (socket, connect, send, recv, etc.)
strace -e trace=network curl https://example.com
# Gestion des processus (fork, clone, execve, wait, exit)
strace -e trace=process bash -c "ls | grep foo"
# Opérations mémoire (mmap, mprotect, brk)
strace -e trace=memory ./my_app
# Syscalls spécifiques par nom
strace -e trace=openat,read,write cat /etc/hostname
# Négation — tout tracer SAUF ces appels
strace -e trace=!mmap,mprotect,brk ./my_app
Filtrer par valeur de retour
Trouver uniquement les appels système en échec — extrêmement utile pour le débogage :
# Afficher uniquement les appels ayant retourné une erreur
strace -Z ./my_app
# Afficher uniquement les appels réussis
strace -z ./my_app
L’option -Z (strace 5.2+) change la donne pour le débogage en production. Au lieu de parcourir des milliers d’appels réussis, vous ne voyez que les échecs.
Analyse des Performances avec strace
Résumé des appels système
L’option -c produit un résumé statistique plutôt qu’une trace en direct :
strace -c ls /tmp
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
25.00 0.000045 5 9 mmap
19.44 0.000035 5 7 close
16.67 0.000030 5 6 openat
11.11 0.000020 4 5 fstat
8.33 0.000015 5 3 mprotect
5.56 0.000010 3 3 read
...
------ ----------- ----------- --------- --------- ----------------
100.00 0.000180 4 42 2 total
Cela indique quels appels système consomment le plus de temps. Si read ou write domine, votre processus est limité par les E/S. Si futex domine, vous avez de la contention sur les verrous.
Chronométrer les appels individuels
# Temps réel par syscall
strace -T ./my_app
# Combiné : horodatages + durée
strace -tT ./my_app
L’option -T ajoute la durée entre chevrons :
openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY) = 3 <0.000024>
read(3, "nameserver 8.8.8.8\n", 4096) = 19 <0.000011>
connect(4, {sa_family=AF_INET, sin_port=htons(443)}, 16) = -1 EINPROGRESS <0.000089>
Ce connect() qui prend 89 microsecondes, c’est normal. Si vous le voyez prendre plus de 5 secondes, votre DNS ou votre service amont est le goulot d’étranglement.
Comparaison de strace avec les Outils de Traçage Alternatifs
| Fonctionnalité | strace | ltrace | perf trace | bpftrace |
|---|---|---|---|---|
| Trace | Syscalls noyau | Appels bibliothèques | Syscalls noyau | Noyau + espace utilisateur |
| Surcharge | Élevée (10-100x) | Élevée | Faible (~5%) | Très faible (~2%) |
| Attache à un PID actif | Oui | Oui | Oui | Oui |
| Filtre par syscall | Oui (-e trace=) | Oui (-e) | Oui (—filter) | Oui (scripts personnalisés) |
| Résumé statistique | Oui (-c) | Oui (-c) | Oui (—summary) | Scripts personnalisés |
| Version noyau requise | Toute | Toute | 3.7+ | 4.9+ (eBPF) |
| Sûr en production | Utilisation brève | Utilisation brève | Oui | Oui |
| Idéal pour | Diagnostic rapide | Problèmes de bibliothèques | Profilage faible surcharge | Logique de traçage complexe |
Règle pratique : Utilisez strace pour un diagnostic rapide (attachez, trouvez le problème, détachez). Passez à perf trace ou bpftrace pour une surveillance continue en production où la surcharge est importante.
Patterns de Débogage courants avec strace
Pattern 1 : Trouver pourquoi un programme ne trouve pas un fichier
strace -e trace=openat,stat,access ./my_app 2>&1 | grep -i "no such file\|enoent\|eacces"
Cela affiche instantanément chaque fichier que le programme tente d’ouvrir sans succès. Courant pour les problèmes de fichiers de configuration, de bibliothèques partagées manquantes ou de chemins incorrects.
Pattern 2 : Trouver quels fichiers de configuration un programme lit
strace -e trace=openat ./my_app 2>&1 | grep -v ENOENT | grep '= [0-9]'
Cela filtre pour n’afficher que les ouvertures de fichiers réussies — vous montrant exactement quels fichiers de configuration, bibliothèques et fichiers de données le programme utilise réellement.
Pattern 3 : Déboguer les problèmes de résolution DNS
strace -e trace=network -s 256 curl https://example.com 2>&1 | grep -E 'connect|sendto|recvfrom'
Vous verrez la requête DNS aller vers les serveurs de noms de /etc/resolv.conf, la réponse, puis la connexion HTTPS effective. Si la requête DNS prend des secondes, vous avez trouvé votre source de latence.
Pattern 4 : Trouver pourquoi un service échoue au démarrage
sudo strace -f -o /tmp/service_trace.log systemctl start my_service
# Puis chercher les erreurs dans la trace
grep '= -1' /tmp/service_trace.log | grep -v 'ENOENT.*locale\|ENOENT.*lib' | head -30
Le grep filtre les erreurs “fichier introuvable” sans gravité provenant du sondage des paramètres régionaux et des bibliothèques (ce qui est normal), ne vous laissant que les vrais échecs.
Pattern 5 : Surveiller les écritures de fichiers en temps réel
sudo strace -fp $(pidof my_app) -e trace=write -s 1024 2>&1 | grep 'write([0-9]*,'
Observez chaque octet que le processus écrit sur n’importe quel descripteur de fichier — utile pour déboguer les problèmes de journalisation ou les modifications de fichiers inattendues.
Pièges et Cas Particuliers
Tracer des binaires setuid : strace ne peut pas s’attacher aux programmes setuid à moins de lancer strace lui-même en tant que root. Le noyau supprime les permissions ptrace pour des raisons de sécurité.
Applications multi-threadées : Utilisez toujours -f (suivre les forks) avec les applications multi-threadées. Sans cela, vous ne voyez que les syscalls du thread principal et manquez les threads de travail où le vrai problème se situe.
Environnements conteneurisés : Dans les conteneurs Docker, strace nécessite la capacité SYS_PTRACE. Lancez avec --cap-add=SYS_PTRACE ou utilisez --privileged pour le débogage :
docker run --cap-add=SYS_PTRACE my_image strace ./my_app
Dans Kubernetes, ajoutez la capacité au contexte de sécurité de votre pod :
securityContext:
capabilities:
add: ["SYS_PTRACE"]
L’impact sur les performances est réel : strace intercepte chaque appel système via ptrace, ce qui nécessite deux changements de contexte par appel. Un processus effectuant 100 000 syscalls/seconde sera considérablement ralenti. Ne laissez jamais strace attaché à un processus de production plus longtemps que nécessaire pour capturer le problème.
strace -c masque les appels lents individuels : Le résumé -c affiche des moyennes. Un processus peut effectuer 10 000 appels read() rapides et un read() de 30 secondes — la moyenne semble correcte. Utilisez -C (majuscule) pour obtenir à la fois le résumé et la trace en direct afin de détecter les valeurs aberrantes.
Résolution de Problèmes
”Operation not permitted” lors de l’attachement
# Vérifier la portée ptrace (Ubuntu/Debian)
cat /proc/sys/kernel/yama/ptrace_scope
Si la valeur est 1 (par défaut sur Ubuntu), vous ne pouvez tracer que vos propres processus. Pour autoriser temporairement le traçage de n’importe quel processus :
# Temporaire — se réinitialise au redémarrage
sudo sysctl kernel.yama.ptrace_scope=0
# Ou simplement utiliser sudo avec strace
sudo strace -p 12345
La sortie de trace est écrasante
# Combiner les filtres : uniquement les opérations fichier en échec avec chronométrage
strace -Z -e trace=file -T -s 256 ./my_app 2>&1 | head -50
Besoin de tracer un processus de courte durée
Pour les processus qui démarrent et se terminent rapidement (comme les tâches cron) :
# Encapsuler la commande
strace -f -o /tmp/cron_trace.log /path/to/cron_script.sh
# Ou tracer le parent qui le lance
sudo strace -fp $(pidof crond) -o /tmp/cron_trace.log
Résumé
- strace trace les appels système noyau — utilisez-le quand un processus échoue silencieusement, se bloque ou se comporte mal et que les logs ne donnent aucun indice
- Attachez-vous aux processus en cours d’exécution avec
strace -p PIDsans les redémarrer — ajoutez-fpour les applications multi-threadées - Filtrez avec
-e trace=pour vous concentrer sur les opérations fichier, réseau, processus ou mémoire plutôt que de vous noyer dans le bruit - Utilisez
-Zpour n’afficher que les appels en échec — le moyen le plus rapide de trouver pourquoi quelque chose est cassé - Utilisez
-cpour les résumés de performance — identifiez quels appels système consomment le plus de temps - La surcharge de performance est significative — attachez-vous brièvement en production, puis détachez-vous. Pour un traçage soutenu, utilisez
perf traceoubpftrace - Les conteneurs ont besoin de la capacité SYS_PTRACE — ajoutez-la explicitement dans Docker ou Kubernetes