Comment utiliser strace?


273

Un collègue m'a dit une fois que la dernière option lorsque tout n'a pas réussi à déboguer sous Linux était d'utiliser strace .

J'ai essayé d'apprendre la science derrière cet outil étrange, mais je ne suis pas un gourou de l'administration système et je n'ai pas vraiment obtenu de résultats.

Alors,

  • Qu'est-ce que c'est exactement et que fait-il?
  • Comment et dans quels cas faut-il l'utiliser?
  • Comment comprendre et traiter le résultat?

En bref, en termes simples , comment ça marche?


2
strace -p <pid> vous dira ce qui se passe en ce moment avec votre programme ..... rapide et facile que GDB
ernesto

1
Personnellement, je trouve cela man stracetrès facile à lire et utile. (PS ne connaissait pas Strace avant hier et pas un expert Linux)
Alexander Malakhov

1
"strace est un traceur d'appels système" - il vous montre simplement quelles fonctions du noyau sont appelées (avec leurs arguments) suite à votre programme.
Pithikos

Réponses:


184

Présentation de Strace
strace peut être considéré comme un débogueur léger. Il permet à un programmeur / utilisateur de découvrir rapidement comment un programme interagit avec le système d'exploitation. Pour ce faire, il surveille les appels et les signaux du système.

Utilisations
Idéal lorsque vous n'avez pas de code source ou que vous ne voulez pas vous embêter à le parcourir.
Aussi, utile pour votre propre code si vous n'avez pas envie d'ouvrir GDB, mais que vous souhaitez simplement comprendre l'interaction externe.

Une bonne petite introduction
J'ai rencontré cette intro pour utiliser Strace l'autre jour: Strace Hello World


Que se passe-t-il si vous utilisez quelque chose en dessous du calque que strace surveille?
Pacerier

Dans ce cas @Pacerier check ltrace stackoverflow.com/a/52012215/5884955
prosti

C'est idéal pour déboguer des programmes de bas niveau qui existent uniquement / principalement pour effectuer des appels système intéressants, ou expérimenter de nouvelles options pour les appels système pour voir ce que fait votre système d'exploitation. Cela évite essentiellement d'écrire du code de journalisation / vérification des erreurs pour des expériences ponctuelles. (Ou si vous écrivez en asm ou quelque chose où il y a de fortes chances que vous ayez accidentellement passé les mauvais arguments ou même le numéro d'appel.) Strace est beaucoup plus rapide que GDB car il recherche les codes errno pour vous, par exemple -EFAULT(oups, lecture seule tampon) ou -ENOENT(oups, exécuté à partir du mauvais répertoire où le chemin relatif ne fonctionnait pas).)
Peter Cordes

62

En termes simples, strace trace tous les appels système émis par un programme avec leurs codes retour. Pensez à des choses telles que les opérations de fichier / socket et beaucoup plus obscures.

Il est très utile si vous avez une connaissance pratique de C car ici les appels système représenteraient plus précisément les appels de bibliothèque C standard.

Disons que votre programme est / usr / local / bin / cough. Utilisez simplement:

strace /usr/local/bin/cough <any required argument for cough here>

ou

strace -o <out_file> /usr/local/bin/cough <any required argument for cough here>

pour écrire dans 'out_file'.

Toutes les sorties strace iront à stderr (attention, le volume de celui-ci demande souvent une redirection vers un fichier). Dans les cas les plus simples, votre programme s'interrompra avec une erreur et vous pourrez voir où en sont ses dernières interactions avec l'OS en sortie strace.

Plus d'informations devraient être disponibles avec:

man strace

36

strace répertorie tous les appels système effectués par le processus auquel il est appliqué. Si vous ne savez pas ce que les appels système signifient, vous ne pourrez pas en tirer beaucoup de kilométrage.

Néanmoins, si votre problème concerne des fichiers ou des chemins ou des valeurs d'environnement, l'exécution de strace sur le programme problématique et la redirection de la sortie vers un fichier, puis en accueillant ce fichier pour votre chaîne chemin / fichier / env peut vous aider à voir ce que votre programme tente réellement de faire, contrairement à ce que vous attendiez.


7
Et pour les programmes non triviaux, cela revient souvent à boire dans un tuyau d'incendie, donc vous avez du
pain sur la planche

17
strace <prog_name>pour tracer un programme. strace -o <out_file> <prog_name>à mettre dans un fichier
Jestin Joy

8
strace prog 2> & 1 | grep ^ open \ (
eisbaw

10
Ou tout simplement: strace -e open myprogOU pour tous les appels sys liés aux fichiers:strace -e file myprog
Amit Naidu

17

Strace se démarque comme un outil pour étudier les systèmes de production où vous ne pouvez pas vous permettre d'exécuter ces programmes sous un débogueur. En particulier, nous avons utilisé strace dans les deux situations suivantes:

  • Le programme foo semble être dans une impasse et ne répond plus. Cela pourrait être une cible pour gdb; cependant, nous n'avons pas toujours eu le code source ou nous avons parfois eu affaire à des langages de script qui n'étaient pas simples à exécuter sous un débogueur. Dans ce cas, vous exécutez strace sur un programme déjà en cours d'exécution et vous obtiendrez la liste des appels système en cours. Ceci est particulièrement utile si vous étudiez une application client / serveur ou une application qui interagit avec une base de données
  • Enquêter sur la lenteur d'un programme. En particulier, nous venions de passer à un nouveau système de fichiers distribué et le nouveau débit du système était très lent. Vous pouvez spécifier strace avec l'option '-T' qui vous indiquera combien de temps a été consacré à chaque appel système. Cela a aidé à déterminer pourquoi le système de fichiers ralentissait les choses.

Pour un exemple d'analyse à l'aide de strace, voir ma réponse à cette question .


15

J'utilise strace tout le temps pour déboguer les problèmes d'autorisation. La technique va comme ceci:

$ strace -e trace=open,stat,read,write gnome-calculator

gnome-calculatorest la commande que vous souhaitez exécuter.


8

strace -tfp PID surveillera les appels système du processus PID, ainsi nous pouvons déboguer / surveiller l'état de notre processus / programme.


6

Strace peut être utilisé comme outil de débogage ou comme profileur primitif.

En tant que débogueur, vous pouvez voir comment les appels système donnés ont été appelés, exécutés et ce qu'ils renvoient. C'est très important, car cela vous permet de voir non seulement qu'un programme a échoué, mais POURQUOI un programme a échoué. Habituellement, c'est simplement le résultat d'un codage moche qui n'attrape pas tous les résultats possibles d'un programme. D'autres fois, ce ne sont que des chemins codés en dur vers des fichiers. Sans effort, vous devinez ce qui s'est mal passé, où et comment. Avec strace, vous obtenez une ventilation d'un appel système, généralement en regardant simplement une valeur de retour vous en dit beaucoup.

Le profilage est une autre utilisation. Vous pouvez l'utiliser pour chronométrer l'exécution de chaque syscall individuellement ou en tant qu'agrégat. Bien que cela ne soit pas suffisant pour résoudre vos problèmes, cela réduira au moins considérablement la liste des suspects potentiels. Si vous voyez beaucoup de paires fopen / close sur un seul fichier, vous ouvrez et fermez inutilement des fichiers à chaque exécution d'une boucle, au lieu de l'ouvrir et de le fermer en dehors d'une boucle.

Ltrace est le proche cousin de strace, également très utile. Vous devez apprendre à différencier où se trouve votre goulot d'étranglement. Si une exécution totale est de 8 secondes et que vous ne dépensez que 0,05 s en appels système, alors le stracing du programme ne vous fera pas beaucoup de bien, le problème est dans votre code, qui est généralement un problème de logique, ou le programme a réellement besoin de prendre autant de temps à courir.

Le plus gros problème avec strace / ltrace est la lecture de leur sortie. Si vous ne savez pas comment les appels sont effectués, ou au moins les noms des appels système / fonctions, il sera difficile de déchiffrer la signification. Savoir ce que les fonctions renvoient peut également être très bénéfique, en particulier pour différents codes d'erreur. Bien que ce soit difficile à déchiffrer, ils retournent parfois vraiment une perle de connaissances; une fois que j'ai vu une situation où j'ai manqué d'inodes, mais pas d'espace libre, donc tous les utilitaires habituels ne m'ont donné aucun avertissement, je ne pouvais tout simplement pas créer un nouveau fichier. La lecture du code d'erreur à partir de la sortie de strace m'a indiqué la bonne direction.


4

Strace est un outil qui vous indique comment votre application interagit avec votre système d'exploitation.

Pour ce faire, il vous indique quel système d'exploitation appelle votre application et avec quels paramètres il les appelle.

Ainsi, par exemple, vous voyez quels fichiers votre programme essaie d'ouvrir et la météo de l'appel réussit.

Vous pouvez déboguer toutes sortes de problèmes avec cet outil. Par exemple, si l'application indique qu'elle ne peut pas trouver la bibliothèque que vous savez que vous avez installée, votre strace vous dira où l'application recherche ce fichier.

Et ce n'est là qu'une partie de l'iceberg.


c'est très précis.
prosti

4

strace est un bon outil pour apprendre comment votre programme effectue divers appels système (demandes au noyau) et signale également ceux qui ont échoué ainsi que la valeur d'erreur associée à cet échec. Tous les échecs ne sont pas des bogues. Par exemple, un code qui essaie de rechercher un fichier peut obtenir une erreur ENOENT (aucun fichier ou répertoire), mais cela peut être un scénario acceptable dans la logique du code.

Un bon cas d'utilisation de strace consiste à déboguer les conditions de concurrence lors de la création de fichiers temporaires. Par exemple, un programme qui peut créer des fichiers en ajoutant l'ID de processus (PID) à une chaîne prédéterminée peut rencontrer des problèmes dans des scénarios multithreads. [Un PID + TID (identifiant de processus + identifiant de thread) ou un meilleur appel système tel que mkstemp corrigera ce problème].

Il est également bon pour déboguer les plantages. Vous pouvez trouver cet (mon) article sur strace et le débogage des plantages utile.


4

Exemple exécutable minimal

Si un concept n'est pas clair, il y a un exemple plus simple que vous n'avez pas vu qui l'explique.

Dans ce cas, cet exemple est le monde bonjour de l'assemblage Linux x86_64 (pas de libc):

bonjour.S

.text
.global _start
_start:
    /* write */
    mov $1, %rax    /* syscall number */
    mov $1, %rdi    /* stdout */
    mov $msg, %rsi  /* buffer */
    mov $len, %rdx  /* buffer len */
    syscall

    /* exit */
    mov $60, %rax   /* exit status */
    mov $0, %rdi    /* syscall number */
    syscall
msg:
    .ascii "hello\n"
len = . - msg

GitHub en amont .

Assemblez et exécutez:

as -o hello.o hello.S
ld -o hello.out hello.o
./hello.out

Produit les résultats attendus:

hello

Maintenant, utilisons strace sur cet exemple:

env -i ASDF=qwer strace -o strace.log -s999 -v ./hello.out arg0 arg1
cat strace.log

Nous utilisons:

strace.log contient désormais:

execve("./hello.out", ["./hello.out", "arg0", "arg1"], ["ASDF=qwer"]) = 0
write(1, "hello\n", 6)                  = 6
exit(0)                                 = ?
+++ exited with 0 +++

Avec un exemple aussi minimal, chaque caractère de la sortie est évident:

  • execveligne: montre comment straceexécuté hello.out, y compris les arguments CLI et l'environnement comme documenté àman execve

  • writeligne: affiche l'appel système d'écriture que nous avons effectué. 6est la longueur de la chaîne "hello\n".

    = 6est la valeur de retour de l'appel système, qui, comme indiqué dans, man 2 writeest le nombre d'octets écrits.

  • exitligne: affiche l'appel système de sortie que nous avons effectué. Il n'y a pas de valeur de retour, car le programme quitte!

Exemples plus complexes

L'application de strace est bien sûr de voir quels appels système les programmes complexes font réellement pour aider à déboguer / optimiser votre programme.

Notamment, la plupart des appels système que vous êtes susceptible de rencontrer sous Linux ont des wrappers glibc, dont beaucoup proviennent de POSIX .

En interne, les wrappers glibc utilisent un assemblage en ligne plus ou moins comme ceci: Comment appeler un appel système via sysenter dans un assemblage en ligne?

L'exemple suivant que vous devriez étudier est un writemonde bonjour POSIX :

principal c

#define _XOPEN_SOURCE 700
#include <unistd.h>

int main(void) {
    char *msg = "hello\n";
    write(1, msg, 6);
    return 0;
}

Compiler et exécuter:

gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out

Cette fois, vous verrez qu'un tas d'appels système sont effectués par glibc avant mainde configurer un environnement agréable pour main.

C'est parce que nous n'utilisons pas maintenant un programme autonome, mais plutôt un programme glibc plus commun, qui permet la fonctionnalité libc.

Ensuite, à chaque extrémité, strace.logcontient:

write(1, "hello\n", 6)                  = 6
exit_group(0)                           = ?
+++ exited with 0 +++

Nous concluons donc que la writefonction POSIX utilise, surprise !, l' writeappel système Linux .

On observe également que cela return 0conduit à un exit_groupappel au lieu de exit. Ha, je ne connaissais pas celui-ci! C'est pourquoi stracec'est si cool. man exit_groupexplique ensuite:

Cet appel système est équivalent à exit (2), sauf qu'il termine non seulement le thread appelant, mais tous les threads du groupe de threads du processus appelant.

Et voici un autre exemple où j'ai étudié quel appel système dlopenutilise: /unix/226524/what-system-call-is-used-to-load-libraries-in-linux/462710#462710

Testé dans Ubuntu 16.04, GCC 6.4.0, noyau Linux 4.4.0.


2

Voici quelques exemples de la façon dont j'utilise strace pour creuser dans des sites Web. J'espère que cela vous sera utile.

Vérifiez le temps de premier octet comme ceci:

time php index.php > timeTrace.txt

Voyez quel pourcentage d'actions fait quoi. Beaucoup lstatet fstatpourrait être une indication qu'il est temps de vider le cache:

strace -s 200 -c php index.php > traceLstat.txt

Sorties a trace.txtpour que vous puissiez voir exactement quels appels sont effectués.

strace -Tt -o Fulltrace.txt php index.php

Utilisez cette option pour vérifier si quelque chose a entre .1à .9une seconde à la charge:

cat Fulltrace.txt | grep "[<]0.[1-9]" > traceSlowest.txt

Voyez quels fichiers ou répertoires manquants se sont retrouvés dans le strace. Cela produira beaucoup de choses impliquant notre système - les seuls bits pertinents impliquent les fichiers du client:

strace -vv php index.php 2>&1 | sed -n '/= -1/p' > traceFailures.txt

1

J'ai aimé certaines des réponses où il lit stracevérifie comment vous interagissez avec votre système d'exploitation.

C'est exactement ce que nous pouvons voir. Le système appelle. Si vous comparez straceet ltracela différence est plus évidente.

$>strace -c cd
Desktop  Documents  Downloads  examples.desktop  Music  Pictures  Public  Templates  Videos
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         7           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0        11           close
  0.00    0.000000           0        10           fstat
  0.00    0.000000           0        17           mmap
  0.00    0.000000           0        12           mprotect
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         2           rt_sigaction
  0.00    0.000000           0         1           rt_sigprocmask
  0.00    0.000000           0         2           ioctl
  0.00    0.000000           0         8         8 access
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         2           getdents
  0.00    0.000000           0         2         2 statfs
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         9           openat
  0.00    0.000000           0         1           set_robust_list
  0.00    0.000000           0         1           prlimit64
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                    93        10 total

D'un autre côté, il existe ltracedes fonctions de trace.

$>ltrace -c cd
Desktop  Documents  Downloads  examples.desktop  Music  Pictures  Public  Templates  Videos
% time     seconds  usecs/call     calls      function
------ ----------- ----------- --------- --------------------
 15.52    0.004946         329        15 memcpy
 13.34    0.004249          94        45 __ctype_get_mb_cur_max
 12.87    0.004099        2049         2 fclose
 12.12    0.003861          83        46 strlen
 10.96    0.003491         109        32 __errno_location
 10.37    0.003303         117        28 readdir
  8.41    0.002679         133        20 strcoll
  5.62    0.001791         111        16 __overflow
  3.24    0.001032         114         9 fwrite_unlocked
  1.26    0.000400         100         4 __freading
  1.17    0.000372          41         9 getenv
  0.70    0.000222         111         2 fflush
  0.67    0.000214         107         2 __fpending
  0.64    0.000203         101         2 fileno
  0.62    0.000196         196         1 closedir
  0.43    0.000138         138         1 setlocale
  0.36    0.000114         114         1 _setjmp
  0.31    0.000098          98         1 realloc
  0.25    0.000080          80         1 bindtextdomain
  0.21    0.000068          68         1 opendir
  0.19    0.000062          62         1 strrchr
  0.18    0.000056          56         1 isatty
  0.16    0.000051          51         1 ioctl
  0.15    0.000047          47         1 getopt_long
  0.14    0.000045          45         1 textdomain
  0.13    0.000042          42         1 __cxa_atexit
------ ----------- ----------- --------- --------------------
100.00    0.031859                   244 total

Bien que j'ai vérifié les manuels plusieurs fois, je n'ai pas trouvé l'origine du nom, stracemais il s'agit probablement d'une trace des appels système, car cela est évident.

Il y a trois notes plus importantes à dire strace.

Remarque 1: ces deux fonctions straceet ltraceutilisent l'appel système ptrace. Donc ptrace, l'appel système est efficace strace.

L'appel système ptrace () fournit un moyen par lequel un processus (le "traceur") peut observer et contrôler l'exécution d'un autre processus (le "tracee"), et examiner et modifier la mémoire et les registres du tracee. Il est principalement utilisé pour implémenter le débogage des points d'arrêt et le suivi des appels système.

Remarque 2: vous pouvez utiliser différents paramètres strace, car ils stracepeuvent être très détaillés. J'aime expérimenter -cce qui est comme un résumé des choses. En fonction de, -cvous pouvez sélectionner un appel système comme celui -e trace=openoù vous ne verrez que cet appel. Cela peut être intéressant si vous examinez quels fichiers seront ouverts lors de la commande que vous tracez. Et bien sûr, vous pouvez utiliser le grepdans le même but, mais notez que vous devez rediriger comme ceci 2>&1 | grep etcpour comprendre que les fichiers de configuration sont référencés lorsque la commande a été émise.

Note 3: Je trouve cette note très importante. Vous n'êtes pas limité à une architecture spécifique. stracevous épatera, car il peut tracer des binaires de différentes architectures. entrez la description de l'image ici

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.