web-dev-qa-db-fra.com

Comment utiliser strace?

Un collègue m'a dit une fois 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 le résultat devrait-il être compris et traité?

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

261
e-satis

Vue d'ensemble 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 cela, il surveille les appels et les signaux du système.

Utilisations
Idéal si vous n'avez pas de code source ou si vous ne voulez pas être dérangé pour le parcourir.
En outre, utile pour votre propre code si vous ne souhaitez pas ouvrir GDB, mais êtes simplement intéressé à comprendre les interactions externes.

Une bonne petite introduction
Je suis tombé sur cette introduction pour utiliser strace l’autre jour: strace hello world

178
John Mulder

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

Il est très utile d’avoir une connaissance pratique de C, car les appels système correspondraient plus précisément aux 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>

é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
61
bltxd

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 qui pose problème et rediriger la sortie vers un fichier, puis insérer ce fichier dans votre chaîne path/file/env peut vous aider à voir ce que votre programme est en fait essayer de faire, par opposition à ce que vous espériez.

34
Asaf Bartov

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 est devenu insensible. 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.
  • Rechercher 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, voir ma réponse à cette question .

17
terson

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

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

gnome-calculator est la commande à exécuter.

15
Jeff Sheffield

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

7
Leslie Zhu

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 ne s'agit que de chemins codés en dur vers les fichiers. Sans effort, vous devez deviner 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 seul 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 avec 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 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.

6
Marcin

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 consiste à déboguer des conditions de concurrence pendant la création de fichiers temporaires. 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 bon pour le débogage des accidents. Vous pouvez trouver cet article (mon article) sur strace et les plantages de débogage utile.

4
mohit

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 appelé par votre application et les paramètres qu’elle appelle.

Ainsi, par exemple, vous voyez les fichiers que votre programme essaie d'ouvrir et vous réussissez si l'appel échoue.

Vous pouvez résoudre toutes sortes de problèmes avec cet outil. Par exemple, si l'application déclare ne pas pouvoir trouver la bibliothèque sur laquelle vous savez que vous avez installé, strace vous dira où l'application cherche ce fichier.

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

4
Luka Marinko

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 le monde hello Linux x86_64 Assembly autoportant (sans 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 courez:

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

Sortie attendue:

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 maintenant:

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 minime, chaque caractère de la sortie est évident:

  • execve ligne: montre comment strace a exécuté hello.out, y compris les arguments de la CLI et l'environnement, comme indiqué à l'adresse man execve

  • write ligne: affiche l'appel système d'écriture que nous avons effectué. 6 est la longueur de la chaîne "hello\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 ligne: affiche l'appel système de sortie que nous avons effectué. Il n'y a pas de valeur de retour, puisque le programme a arrêté!

Exemples plus complexes

Bien sûr, l’application de strace permet de savoir quels appels système sont réellement effectués par des programmes complexes afin de 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, , souvent issus de POSIX .

En interne, les wrappers glibc utilisent inline Assembly plus ou moins comme ceci: Comment appeler un appel système via sysenter in inline assembly?

Le prochain exemple que vous devriez étudier est un monde POSIX write hello:

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-ci, vous constaterez que glibc effectue une série d'appels système avant main pour configurer un environnement Nice pour main.

En effet, nous n’utilisons plus de programme autonome, mais plutôt un programme glibc plus courant, permettant la fonctionnalité libc.

Ensuite, à chaque fin, strace.log contient:

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

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 est équivalent à exit (2), sauf qu'il met fin non seulement au thread appelant, mais à tous les threads du groupe de threads du processus appelant.

Et voici un autre exemple où j’ai étudié l’appel système dlopen utilisé: 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.

J'ai aimé certaines des réponses où il est écrit 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.

$>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, il existe ltrace qui trace les fonctions.

$>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 strace, mais il s’agit probablement d’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 correspond effectivement au 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 (le "suivi"), et examiner et modifier la mémoire et les registres du suivi. Il est principalement utilisé pour implémenter le débogage des points d'arrêt et le suivi des appels système.

Remarque 2: Il existe différents paramètres que vous pouvez utiliser 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>&1 | grep etc pour comprendre que les fichiers de configuration sont référencés lors de l'exécution de la commande.

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. enter image description here

1
prosti