Question

Un collègue m'a déjà dit que la dernière option lorsque tout ne pouvait pas déboguer sous Linux était d'utiliser strace .

J’ai essayé d’apprendre les bases scientifiques de cet étrange outil, mais je ne suis pas un gourou de l’administration système et je n’ai pas vraiment obtenu de résultats.

Alors,

  • De quoi s'agit-il exactement et que fait-il?
  • Comment et dans quels cas faut-il l'utiliser?
  • Comment la sortie doit-elle être comprise et traitée?

En bref, en termes simples , comment cela fonctionne-t-il?

Était-ce utile?

La solution

Présentation de Strace
strace peut être vu comme un débogueur léger. Il permet à un programmeur / utilisateur de savoir 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 si vous ne possédez pas de code source ou si vous ne voulez pas être dérangé pour le parcourir.
Aussi, utile pour votre propre code si vous n'avez pas envie d'ouvrir GDB, mais êtes simplement intéressé à comprendre l'interaction externe.

Une bonne petite introduction
L’autre jour, j’ai rencontré cette introduction à strace: strace hello world

Autres conseils

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

Il est très utile d'avoir une connaissance pratique de C, car ici, les appels système correspondraient plus précisément aux appels standard de la bibliothèque C.

Supposons 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>

à écrire dans 'out_file'.

Toutes les sorties strace iront sur stderr (attention, son volume même demande souvent une redirection vers un fichier). Dans les cas les plus simples, votre programme abandonnera avec une erreur et vous pourrez voir où se trouvent ses dernières interactions avec le système d’exploitation dans la sortie strace.

Plus d'informations devraient être disponibles avec:

man strace

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 utiliser beaucoup.

Néanmoins, si votre problème concerne des fichiers, des chemins ou des valeurs d’environnement, exécuter strace sur le programme posant problème, puis rediriger la sortie vers un fichier, puis insérer ce fichier dans la chaîne path / file / env peut vous aider à mieux comprendre votre programme. réellement tentez de le faire, par opposition à ce que vous espériez.

Strace est un outil d’investigation des systèmes de production dans lequel 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 l'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 effectués. Ceci est particulièrement utile si vous étudiez une application client / serveur ou une application qui interagit avec une base de données
  • Recherche pourquoi un programme est lent. 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 permis de déterminer pourquoi le système de fichiers entraînait un ralentissement.

Pour un exemple d'analyse utilisant strace, consultez ma réponse à cette question. .

J'utilise strace tout le temps pour résoudre les problèmes d'autorisation. La technique est la suivante:

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

gnome-calculator correspond à la commande à exécuter.

strace -tfp PID surveillera les appels système du processus PID, nous pourrons ainsi déboguer / surveiller le statut de notre processus / programme.

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. Ceci est très important, car il vous permet de voir non seulement qu'un programme a échoué, mais POURQUOI un programme a échoué. Habituellement, c'est simplement parce que le codage moche ne permet pas de saisir tous les résultats possibles d'un programme. D'autres fois, il s'agit simplement de chemins codés en dur vers les fichiers. Sans effort, vous devinez ce qui ne va pas, où et comment. Avec strace, vous obtenez une ventilation d'un appel système, généralement, le simple fait de regarder une valeur de retour en dit long.

Le profilage est un autre usage. Vous pouvez l'utiliser pour chronométrer l'exécution de chaque appel système individuellement ou globalement. Cela ne suffira peut-être pas à résoudre vos problèmes, mais au moins, cela réduira considérablement la liste des suspects potentiels. Si vous voyez beaucoup de paires fopen / close sur un même fichier, vous ouvrez et fermez probablement inutilement les fichiers à chaque exécution d'une boucle, au lieu de l'ouvrir et de la fermer en dehors d'une boucle.

Ltrace est le cousin proche de Strace, également très utile. Vous devez apprendre à différencier l'endroit où se trouve votre goulot d'étranglement. Si une exécution totale est de 8 secondes et que vous ne consacrez que 0,05 seconde aux appels système, le traçage du programme ne vous fera pas beaucoup de bien, le problème provient de votre code, qui est généralement un problème de logique, ou le programme a réellement besoin prendre ce temps pour courir.

Le plus gros problème de strace / ltrace est leur lecture. Si vous ne savez pas comment les appels sont passés, ou du moins les noms d'appels système / fonctions, il vous sera difficile de déchiffrer le sens. Savoir ce que les fonctions renvoient peut également être très utile, en particulier pour différents codes d'erreur. Bien qu'il soit difficile à déchiffrer, ils renvoient parfois vraiment une perle de savoir; une fois que j’ai vu une situation où j’ai manqué d’inodes, mais pas d’espace libre, tous les utilitaires habituels ne me donnaient aucun avertissement, je ne pouvais tout simplement pas créer un nouveau fichier. La lecture du code d’erreur de la sortie de strace m’a orienté dans la bonne direction.

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

Pour ce faire, il vous indique le système d'exploitation utilisé par votre application et les paramètres qu'elle appelle.

Ainsi, par exemple, vous voyez quels fichiers votre programme essaie d'ouvrir et vous avez réussi l'appel.

Vous pouvez résoudre 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 avoir installée, strace vous dira où l’application recherche ce fichier.

Et ce n’est que la partie visible de l’iceberg.

strace est un bon outil pour apprendre comment votre programme effectue différents appels système (demandes au noyau) et indique également ceux qui ont échoué, ainsi que la valeur d'erreur associée à cet échec. Tous les échecs ne sont pas des bugs. Par exemple, un code qui tente de rechercher un fichier peut générer une erreur ENOENT (aucun fichier ou répertoire de ce type), mais cela peut constituer un scénario acceptable dans la logique du code.

Un bon cas d'utilisation de strace est de déboguer les conditions de concurrence pendant la création de fichier temporaire. Par exemple, un programme susceptible de créer des fichiers en ajoutant l'ID de processus (PID) à une chaîne prédéfinie peut être confronté à des problèmes dans des scénarios multithreads. [Un PID + TID (ID de processus + ID de thread) ou un meilleur appel système tel que mkstemp résoudra ce problème].

C’est également utile pour le débogage des collisions. Vous pouvez trouver cet (mon) article sur les accidents de strace et de débogage . utile.

J'ai aimé certaines des réponses où il lit strace vérifie votre interaction avec votre système d'exploitation.

C’est exactement ce que nous pouvons voir. Le système appelle. Si vous comparez strace et ltrace , la différence est plus évidente.

<*>gt;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
gt;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'autre part, ltrace trace les fonctions.

<*>

Bien que j’ai vérifié les manuels plusieurs fois, je n’ai pas trouvé l’origine du nom strace , mais c’est probablement une trace d’appel système, car elle est évidente.

Il y a trois notes plus importantes à dire à propos de strace .

Remarque 1: Ces deux fonctions strace et ltrace utilisent l'appel système ptrace . Ainsi, l’appel système ptrace est effectivement le fonctionnement de 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          (la "tracee"), et examiner et changer la mémoire de la trace et          registres. Il est principalement utilisé pour implémenter le débogage des points d'arrêt          et suivi des appels système.

Remarque 2: Vous pouvez utiliser différents paramètres avec strace , car strace peut être très détaillé. J'aime expérimenter avec -c , qui est comme un résumé des choses. En fonction de -c , vous pouvez sélectionner un appel système tel que -e trace = open où vous ne verrez que cet appel. Cela peut être intéressant si vous examinez les fichiers qui seront ouverts lors de la commande que vous tracez. Et bien sûr, vous pouvez utiliser grep dans le même but, mais notez que vous devez rediriger comme ceci 2 > & amp; 1 | grep etc pour 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. strace vous épatera, car il peut tracer des binaires de différentes architectures. entrer la description de l'image ici

Exemple minimal exécutable

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

Dans ce cas, cet exemple est l'assembly Linux x86_64 indépendant (pas de libc) hello world:

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 
as -o hello.o hello.S
ld -o hello.out hello.o
./hello.out
, %rdi /* syscall number */ syscall msg: .ascii "hello\n" len = . - msg

https://unix.stackexchange.com/questions/48994/how-to-run-a-program-in-a--clean-environment-in-bash

  • -s999 -v pour afficher des informations plus complètes sur les journaux
  • strace.log contient maintenant:

    #define _XOPEN_SOURCE 700
    #include <unistd.h>
    
    int main(void) {
        char *msg = "hello\n";
        write(1, msg, 6);
        return 0;
    }
    

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

    • execve : indique comment strace est exécuté hello.out , y compris les arguments et l'environnement CLI décrits dans man execve

    • Ligne
    • write : affiche l'appel système en écriture que nous avons effectué. 6 est la longueur de la chaîne " bonjour \ n ".

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

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

    Exemples plus complexes

    L’application de strace permet bien sûr de connaître les appels système que des programmes complexes effectuent réellement pour vous 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, beaucoup d’entre eux de POSIX .

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

    L'exemple suivant que vous devriez étudier est un write hello world POSIX:

    main.c

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

    Compiler et exécuter:

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

    Cette fois, vous constaterez que glibc effectue avant le principal un ensemble d’appels système permettant de créer un environnement agréable pour le principal.

    Cela s'explique par le fait que nous n'utilisons plus de programme autonome, mais un programme glibc plus commun, permettant la fonctionnalité libc.

    Ensuite, à chaque extrémité, strace.log contient:

    <*>

    Nous concluons donc que la fonction write POSIX utilise, surprise !, l'appel système Linux write .

    Nous observons également que return 0 conduit à un appel exit_group au lieu de exit . Ha, je ne savais pas à propos de celui-ci! C'est pourquoi strace est si cool. man exit_group explique ensuite:

      

    Cet appel système équivaut à exit (2), sauf qu'il met fin non seulement au thread appelant, mais à tous les threads du groupe de threads du processus d'appel.

    Et voici un autre exemple où j'ai étudié le système utilisé par l'appel système dlopen : https://unix.stackexchange.com/questions/226524/what-system-call-is-used-to-load-libraries-in- linux / 462710 # 462710

    Testé sous Ubuntu 16.04, GCC 6.4.0, Noyau Linux 4.4.0.

    Licencié sous: CC-BY-SA avec attribution
    Non affilié à StackOverflow
    scroll top