Comment tracer les appels système effectués par un processus avec Strace sur Linux
Il y a des moments où il est utile d'inspecter ce que fait une application en cours d'exécution sous le capot, et quel système appelle qu'il effectue pendant son exécution. Pour accomplir une telle tâche sur Linux, nous pouvons utiliser l'utilitaire strace . Dans cet article, nous verrons comment l'installer et nous apprendrons son utilisation de base.
Dans ce tutoriel, vous apprendrez :
- Comment installer Strace
- Comment utiliser Strace pour tracer les appels système faits par un processus
- Comment filtrer les spécificités des appels système
- Comment s'attacher à un processus déjà en cours d'exécution
- Comment générer un résumé d'appel système
Comment tracer les appels système effectués par un processus avec Strace sur Linux
Exigences et conventions logicielles utilisées
Installation
Bien qu'il ne soit pas installé par défaut, l'utilitaire strace est disponible dans les référentiels officiels de toutes les principales distributions Linux; Cela signifie que nous pouvons l'installer très facilement en utilisant notre gestionnaire de packages préféré.
Si nous courons sur Fedora (ou toute autre distribution dans la famille Red Hat), par exemple, nous devons utiliser dnf :
$ sudo dnf install strace
Si nous sommes plus à l'aise d'utiliser Debian ou des distributions basées sur Debian telles que Ubuntu ou Linux Mint, nous pouvons utiliser apt pour obtenir le même résultat:
$ sudo apt install strace
Si Arch Linux est notre distribution de choix, nous pouvons utiliser pacman pour installer l'application, qui est disponible dans le référentiel extra :
$ sudo pacman -S strace
Avec le logiciel installé, nous pouvons avancer et voir quelques exemples de son utilisation.
Présentation de Strace
Comme nous l'avons déjà dit, Strace est un outil utilisé pour garder une trace des appels système effectués par un processus en cours et les signaux reçus par celui-ci. Les appels système sont l'interface fondamentale entre une application et le noyau Linux; Lorsque nous utilisons strace , le nom des appels effectués par un processus, ainsi que leurs arguments et valeurs de retour sont affichés sur stderr (descripteur de fichier d'erreur standard).
Voyons une utilisation de base de strace , afin de se familiariser avec sa sortie. Dans son utilisation la plus élémentaire, nous appelons Strace suivi du programme que nous voulons exécuter et du comportement que nous voulons analyser. Pour le bien de cet exemple, nous ne copierons que un fichier à l'aide de la commande cp :
$ strace cp ~/.bashrc bashrc
La sortie de la commande est assez longue, et bien sûr, nous ne pouvons pas l'analyser en détail; Voyons juste la première ligne. Chaque ligne de la sortie strace contient:
- Le nom d'appel système
- Les arguments transmis à l'appel du système entre parenthèses
- La valeur de retour d'appel système
Le premier appel système que nous pouvons voir dans la sortie est EXECVE . Cet appel est utilisé pour exécuter un programme avec un tableau d'arguments spécifié. Le premier argument accepté par execv est le chemin du fichier que nous voulons exécuter; Le second est un éventail de chaînes qui représente les arguments qui seront transmis au programme (le premier argument, par convention, étant le nom du programme lui-même).
Dans notre cas, comme prévu, le binaire appelé est /usr/bin/cp , et le tableau d'arguments transmis à l'appel est: le nom du programme (CP), la source et Les chemins de destination:
execve("/usr/bin/cp", ["cp", "/home/egdoc/.bashrc", "bashrc"], 0x7fff53d4e4c0 /* 46 vars */) = 0
La notation /* 46 vars */ signifie que 46 variables où hérité du processus d'appel (dans la fonction execv L'environnement est tiré du ENVIRON //// Code> variable). Enfin, nous avons la valeur de retour , qui dans ce cas est de fonction renvoie une valeur uniquement si une erreur se produit ). 0 (en fait la famille exec
Filtrage uniquement les appels système spécifiques
Lorsque vous utilisez Strace , nous pouvons parfois vouloir suivre uniquement les appels du système spécifiques effectués par un processus. Dans ces situations, nous pouvons utiliser l'option -e suivie d'une expression qui indique quels appels système doivent être tracés. Supposons que nous exécutions la même commande que nous avons utilisée dans l'exemple précédent, mais nous voulons que les appels système lisent s'affichent dans la sortie, nous exécuterons:
$ strace -e read cp ~/.bashrc bashrc
Comme prévu, seuls les appels lisent sont signalés:
La sortie de la commande "Strace -e Read Cp ~/.Bashrc Bashrc" ="Font-Size: hheRit;"> L'appel système prend trois arguments: le premier est un
Attacher Strace sur un processus de course
Jusqu'à présent, nous avons invoqué Strace qui lui a transmis la commande à exécuter et de garder la trace de; Et si nous voulons retracer un processus existant et déjà en cours d'exécution? Dans ce cas, nous devons invoquer strace avec l'option -p (ou - joignez ) et passez la pid (ID de processus) du processus auquel nous voulons le fixer.
Pour trouver le PID d'un programme, parmi les autres solutions, nous pouvons utiliser l'utilitaire pidof . Pour le bien de cet exemple, nous attacherons Strace à une instance en cours d'exécution de gnome-terminal-server :
$ pidof gnome-terminal-server
121316
La commande pidof a renvoyé 121316 , qui est le PID du serveur gnome-terminal. Sachant cela, nous pouvons attacher strace au processus:
$ strace -p 121316
La commande ci-dessus renverra initialement quelque chose comme:
La sortie de la commande «Strace -P 121316» La sortie ci-dessus (tronquée) sera mise à jour «à la volée» lorsque les appels système sont effectués. Pour «détacher» strace Nous pouvons simplement appuyer sur Ctrl + c sur le clavier; Nous serons informés de le "détachement", mais le processus tracé continuera à fonctionner:
strace: Process 121316 detached
Signaux de traçage
Grâce à strace , nous pouvons également observer lorsqu'un processus reçoit un signal et comment il y réagit. Laissez-moi le démontrer. Tout d'abord, nous lançons un processus de longue date en tant que top , qui est un moniteur de processus:
$ top
Nous lui attachons strace , après avoir obtenu son pid, qui dans ce cas est 44825 :
$ strace -p 44825
À ce stade, strace commence à suivre les appels du système effectués par top , mais aussi les signaux reçus par lui. Pour le prouver, nous envoyons un sigterm à PID 44825 :
$ kill 44825
Comme prévu, l'événement est signalé dans la sortie Strace :
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=44888, si_uid=1000} ---
Dans la sortie ci-dessus, si_signo est le nombre de signaux livrés (SIGTERM=15), si_code contient un code qui identifie la cause du signal (si_user=0): en Ce cas le signal a été généré par un processus utilisateur. Les champs si_pid et si_uid rapportent respectivement le pid du processus d'envoi et son uid .
Enregistrer la sortie de Strace dans un fichier
Si nous utilisons l'option -o (abréviation de - ouput ) Lors du lancement strace , nous pouvons rediriger sa sortie vers un fichier, en passant un Chemin comme argument, par exemple:
$ strace -p 121316 -o strace_output
strace: Process 121316 attached
Le fichier strace_output sera créé et la sortie de strace sera écrite à l'intérieur. Pour regarder la mise à jour dans le fichier, nous pouvons utiliser le queue : Normalement, cette commande lit les 10 dernières lignes d'un fichier et sort, mais si nous l'appelons avec le -f Option (abréviation de - Suivez ) Nous pouvons observer que le nouveau contenu est annexé:
$ tail -f strace_output
Imprimez un résumé des appels du système
L'utilitaire strace est livré avec une fonctionnalité très utile: la possibilité de générer un résumé de tous les appels système passés par un processus spécifié. Si nous voulons générer un tel rapport, tout ce que nous avons à faire est d'invoquer le programme avec l'option -c ou - Résumé uniquement . Prenons comme exemple la commande cp que nous avons utilisée auparavant:
$ strace -c cp ~/.bashrc bashrc
La commande ci-dessus générera ce rapport:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
25.71 0.000298 7 38 13 openat
19.24 0.000223 4 51 mmap
11.48 0.000133 4 28 close
9.92 0.000115 57 2 1 newfstatat
7.94 0.000092 10 9 mprotect
6.99 0.000081 3 25 fstat
2.85 0.000033 3 11 read
2.76 0.000032 16 2 munmap
2.50 0.000029 14 2 statfs
1.90 0.000022 22 1 write
1.55 0.000018 2 8 pread64
1.38 0.000016 8 2 1 access
1.04 0.000012 4 3 brk
0.78 0.000009 4 2 rt_sigaction
0.60 0.000007 7 1 futex
0.52 0.000006 3 2 1 arch_prctl
0.43 0.000005 5 1 rt_sigprocmask
0.43 0.000005 5 1 set_tid_address
0.43 0.000005 5 1 fadvise64
0.43 0.000005 5 1 set_robust_list
0.43 0.000005 5 1 prlimit64
0.26 0.000003 3 1 1 stat
0.26 0.000003 3 1 1 lseek
0.17 0.000002 2 1 geteuid
0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 0.001159 5 196 18 total
Comme vous pouvez le voir, puisque nous avons généré un résumé, la sortie normale de strace n'est pas affichée. Si nous voulons générer le résumé mais toujours obtenir la sortie régulière du programme, nous devons utiliser l'option -c à la place, qui est la forme courte de - résumé .
Conclusions
Dans ce didacticiel, nous avons appris à installer et à utiliser Strace , une belle utilité utile à des fins de débogage et plus généralement pour garder une trace des appels système effectués par un processus. Nous avons vu comment la sortie de strace est organisée, comment lancer un programme et garder une trace des appels du système, comment attacher strace à un processus déjà en cours d'exécution et comment Les signaux reçus par un processus sont informés; Enfin, nous avons vu comment générer un résumé de tous les appels passés par un processus. Ici, nous avons à peine rayé la surface de ce que nous pouvons faire avec strace : Si vous voulez en savoir plus, le conseil est, comme toujours, de lire le manuel!


