Como o strace deve ser usado?

273

Um colega me disse uma vez que a última opção quando tudo falhou na depuração no Linux foi usar strace .

Tentei aprender a ciência por trás dessa ferramenta estranha, mas não sou um guru de administração de sistemas e não obtive resultados.

Assim,

  • O que é exatamente e o que faz?
  • Como e em que casos deve ser usado?
  • Como a saída deve ser entendida e processada?

Em resumo, em palavras simples , como essas coisas funcionam?

e-satis
fonte
2
strace -p <pid> irá dizer-lhe o que está acontecendo agora com o seu programa ..... rápido e fácil do que GDB
ernesto
1
Pessoalmente, acho man stracemuito fácil de ler e útil. (PS não sabia sobre strace antes de ontem e não um especialista em Linux)
Alexander Malakhov
1
"strace é um rastreador de chamadas do sistema" - apenas mostra como as funções do kernel estão sendo chamadas (com seus argumentos) como resultado do seu programa.
Pithikos 26/09

Respostas:

184

Visão geral do Strace O
strace pode ser visto como um depurador leve. Ele permite que um programador / usuário descubra rapidamente como um programa está interagindo com o sistema operacional. Isso é feito através do monitoramento de chamadas e sinais do sistema.

Usa
Bom para quando você não tem código-fonte ou não quer ser incomodado por realmente passar por ele.
Além disso, é útil para seu próprio código, se você não deseja abrir o GDB, mas está interessado apenas em entender a interação externa.

Uma boa introdução
a essa introdução para strace use outro dia: strace hello world

John Mulder
fonte
E daí se você usar algo abaixo da camada que monitora os monitores?
Pacerier 19/10/2014
Nesse caso, @Pacerier check ltrace stackoverflow.com/a/52012215/5884955
prosti
É ótimo para depurar programas de baixo nível que existem apenas / principalmente para fazer chamadas interessantes ao sistema ou experimentar novas opções para os syscalls verem o que seu sistema operacional faz. Basicamente, evita o trabalho de escrever código de registro / verificação de erros para experimentos pontuais. (Ou se você estiver escrevendo em asm ou algo onde há uma boa chance de que você passou acidentalmente os argumentos errados ou número de chamada mesmo.) Strace é muito mais rápido do que o GDB porque parece-se errno códigos para você, por exemplo -EFAULT(oops, somente leitura buffer) ou -ENOENT(oops, saiu correndo do diretório errado, onde o caminho relativo não funcionou)).
Peter Cordes
62

Em palavras simples, o strace rastreia todas as chamadas do sistema emitidas por um programa junto com seus códigos de retorno. Pense em coisas como operações de arquivo / soquete e muito mais obscuras.

É mais útil se você tiver algum conhecimento prático de C, pois aqui as chamadas do sistema representariam com mais precisão as chamadas da biblioteca C padrão.

Digamos que seu programa seja / usr / local / bin / tosse. Basta usar:

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>

para escrever em 'out_file'.

Toda saída do strace irá para o stderr (cuidado, o grande volume dela geralmente exige um redirecionamento para um arquivo). Nos casos mais simples, seu programa será interrompido com um erro e você poderá ver onde foram as últimas interações com o SO na saída de rastreamento.

Mais informações devem estar disponíveis em:

man strace
bltxd
fonte
36

O strace lista todas as chamadas do sistema feitas pelo processo ao qual é aplicada. Se você não souber o que significam as chamadas do sistema, não poderá obter muitas milhas com isso.

No entanto, se o seu problema envolver arquivos, caminhos ou valores do ambiente, executar o rastreio no programa problemático e redirecionar a saída para um arquivo e depois cumprimentá-lo pela sua cadeia de caminho / arquivo / env pode ajudá-lo a ver o que seu programa está realmente tentando diferente do que você esperava.

Asaf Bartov
fonte
7
E para programas não-triviais isso muitas vezes é como beber de uma mangueira de incêndio, então você tem seu trabalho cortado para você ir através dos resultados ...
dmckee --- ex-moderador gatinho
17
strace <prog_name>rastrear um programa. strace -o <out_file> <prog_name>colocar fora de arquivo
Jestin Joy
8
strace prog 2> & 1 | grep ^ open \ (
eisbaw
10
Ou apenas: strace -e open myprogOR para todos os sys chamadas relacionadas arquivos:strace -e file myprog
Amit Naidu
17

Strace se destaca como uma ferramenta para investigar sistemas de produção em que você não pode dar ao luxo de executar esses programas em um depurador. Em particular, usamos strace nas duas situações a seguir:

  • O programa foo parece estar em um impasse e deixou de responder. Este poderia ser um alvo para o gdb; no entanto, nem sempre tivemos o código-fonte ou às vezes estávamos lidando com linguagens de script que não eram fáceis de executar em um depurador. Nesse caso, você executa o strace em um programa já em execução e obtém a lista de chamadas do sistema sendo feitas. Isso é particularmente útil se você estiver investigando um aplicativo cliente / servidor ou um aplicativo que interaja com um banco de dados
  • Investigando por que um programa é lento. Em particular, tínhamos acabado de mudar para um novo sistema de arquivos distribuídos e a nova taxa de transferência do sistema era muito lenta. Você pode especificar o rastreio com a opção '-T', que informará quanto tempo foi gasto em cada chamada do sistema. Isso ajudou a determinar por que o sistema de arquivos estava causando lentidão nas coisas.

Para um exemplo de análise usando strace, veja minha resposta a esta pergunta .

terson
fonte
15

Uso strace o tempo todo para depurar problemas de permissão. A técnica é assim:

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

Onde gnome-calculatorestá o comando que você deseja executar.

Jeff Sheffield
fonte
8

O strace -tfp PID monitorará as chamadas de sistema do processo PID, para que possamos depurar / monitorar o status do processo / programa.

Leslie Zhu
fonte
6

Strace pode ser usado como uma ferramenta de depuração ou como um gerador de perfil primitivo.

Como depurador, você pode ver como determinadas chamadas do sistema foram chamadas, executadas e o que elas retornam. Isso é muito importante, pois permite ver não apenas que um programa falhou, mas POR QUE um programa falhou. Geralmente, é apenas o resultado de uma péssima codificação, que não captura todos os resultados possíveis de um programa. Outras vezes, são apenas caminhos codificados para os arquivos. Sem traços, você adivinha o que deu errado, onde e como. Com o strace, você obtém um detalhamento de um syscall, geralmente apenas observar um valor de retorno diz muito.

A criação de perfil é outro uso. Você pode usá-lo para cronometrar a execução de cada syscalls individualmente ou como um agregado. Embora isso possa não ser suficiente para solucionar seus problemas, ele diminuirá bastante a lista de possíveis suspeitos. Se você vir muitos pares de abrir / fechar em um único arquivo, provavelmente abrirá e fechará desnecessariamente arquivos a cada execução de um loop, em vez de abrir e fechá-lo fora de um loop.

Ltrace é primo íntimo de Strace, também muito útil. Você deve aprender a diferenciar onde está o seu gargalo. Se uma execução total é de 8 segundos e você gasta apenas 0,05seg em chamadas do sistema, rastrear o programa não será muito bom, o problema está no seu código, que geralmente é um problema de lógica ou o programa realmente precisa levar tanto tempo para correr.

O maior problema com strace / ltrace é ler a saída deles. Se você não souber como as chamadas são feitas, ou pelo menos os nomes de syscalls / functions, será difícil decifrar o significado. Saber o que as funções retornam também pode ser muito benéfico, especialmente para diferentes códigos de erro. Embora seja difícil decifrar, às vezes eles realmente retornam uma pérola de conhecimento; Depois que vi uma situação em que fiquei sem inodes, mas não com espaço livre, todos os utilitários comuns não me deram nenhum aviso, simplesmente não consegui criar um novo arquivo. A leitura do código de erro da saída do strace me apontou na direção certa.

Marcin
fonte
4

Strace é uma ferramenta que informa como o aplicativo interage com o sistema operacional.

Isso é feito, informando como o sistema operacional chama seu aplicativo e com quais parâmetros ele os chama.

Por exemplo, você vê quais arquivos o seu programa tenta abrir e aguarda a chamada com êxito.

Você pode depurar todos os tipos de problemas com esta ferramenta. Por exemplo, se o aplicativo disser que não consegue encontrar a biblioteca que você sabe que instalou, o strace dirá onde o aplicativo está procurando esse arquivo.

E isso é apenas uma ponta do iceberg.

Luka Marinko
fonte
isso é muito preciso.
Prosti19
4

O strace é uma boa ferramenta para aprender como o seu programa faz várias chamadas do sistema (solicitações ao kernel) e também relata as que falharam, juntamente com o valor do erro associado a essa falha. Nem todas as falhas são erros. Por exemplo, um código que está tentando procurar um arquivo pode receber um erro ENOENT (sem esse arquivo ou diretório), mas esse pode ser um cenário aceitável na lógica do código.

Um bom caso de uso do strace é depurar condições de corrida durante a criação temporária de arquivos. Por exemplo, um programa que pode estar criando arquivos anexando o ID do processo (PID) a alguma sequência predeterminada pode enfrentar problemas em cenários com vários segmentos. [Um PID + TID (identificação do processo + identificação da thread) ou uma chamada de sistema melhor, como mkstemp, corrigirá isso].

Também é bom para falhas de depuração. Você pode encontrar este (meu) artigo sobre falhas de strace e depuração úteis.

mohit
fonte
4

Exemplo mínimo executável

Se um conceito não estiver claro, há um exemplo mais simples que você ainda não viu que o explica.

Nesse caso, esse exemplo é o hello world independente do assembly Linux x86_64:

ola.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 upstream .

Montar e executar:

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

Produz o esperado:

hello

Agora vamos usar strace nesse exemplo:

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

Nós usamos:

strace.log agora contém:

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

Com um exemplo tão minimalista, todos os caracteres da saída são evidentes:

  • execveline: mostra como é straceexecutado hello.out, incluindo argumentos e ambiente da CLI, conforme documentado emman execve

  • writelinha: mostra a chamada do sistema de gravação que fizemos. 6é o comprimento da string "hello\n".

    = 6é o valor de retorno da chamada do sistema, que conforme documentado man 2 writeé o número de bytes gravados.

  • exitline: mostra a chamada do sistema de saída que fizemos. Não há valor de retorno, pois o programa foi encerrado!

Exemplos mais complexos

A aplicação do strace é, obviamente, para ver quais chamadas do sistema os programas complexos estão realmente fazendo para ajudar a depurar / otimizar seu programa.

Notavelmente, a maioria das chamadas de sistema que você provavelmente encontrará no Linux possui wrappers glibc, muitas delas do POSIX .

Internamente, os wrappers glibc usam montagem inline mais ou menos assim: Como chamar uma chamada de sistema via sysenter na montagem inline?

O próximo exemplo que você deve estudar é um writehello world POSIX :

main.c

#define _XOPEN_SOURCE 700
#include <unistd.h>

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

Compile e execute:

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

Desta vez, você verá que várias chamadas de sistema estão sendo feitas pela glibc antes mainpara configurar um ambiente agradável para main.

Isso ocorre porque agora não estamos usando um programa independente, mas um programa glibc mais comum, que permite a funcionalidade libc.

Então, em cada extremidade, strace.logcontém:

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

Portanto, concluímos que a writefunção POSIX usa, surpresa !, a writechamada de sistema Linux .

Também observamos que return 0leva a uma exit_groupchamada em vez de exit. Ha, eu não sabia sobre este! É por straceisso que é tão legal. man exit_groupentão explica:

Essa chamada do sistema é equivalente à exit (2), exceto que ela finaliza não apenas o encadeamento de chamada, mas todos os encadeamentos no grupo de encadeamentos do processo de chamada.

E aqui está outro exemplo em que estudei qual chamada de sistema dlopenusa: /unix/226524/what-system-call-is-used-to-load-libraries-in-linux/462710#462710

Testado no Ubuntu 16.04, GCC 6.4.0, kernel do Linux 4.4.0.

Ciro Santilli adicionou uma nova foto
fonte
2

Aqui estão alguns exemplos de como uso o strace para acessar sites. Espero que isso seja útil.

Verifique a hora do primeiro byte da seguinte forma:

time php index.php > timeTrace.txt

Veja qual porcentagem de ações está fazendo o que. Muitos lstate fstatpodem ser uma indicação de que é hora de limpar o cache:

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

Saída trace.txtpara que você possa ver exatamente quais chamadas estão sendo feitas.

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

Usar isso para verificar se alguma coisa levou entre .1a .9de um segundo para carregar:

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

Veja quais arquivos ou diretórios ausentes foram capturados no strace. Isso produzirá muitas coisas envolvendo nosso sistema - os únicos bits relevantes envolvem os arquivos do cliente:

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

Eu gostei de algumas respostas onde se lê strace verificando como você interage com seu sistema operacional.

É exatamente isso que podemos ver. O sistema chama. Se você comparar stracee ltracea diferença é mais óbvia.

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

Por outro lado, há ltraceque rastreia funções.

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

Embora tenha verificado os manuais várias vezes, não encontrei a origem do nome strace mas é provável o rastreamento de chamadas do sistema, pois isso é óbvio.

Existem três notas maiores para dizer sobre strace .

Nota 1: Ambas as funções stracee ltraceestão usando a chamada do sistema ptrace. Portanto ptrace, a chamada do sistema é efetivamente como stracefunciona.

A chamada do sistema ptrace () fornece um meio pelo qual um processo (o "rastreador") pode observar e controlar a execução de outro processo (o "rastreador"), além de examinar e alterar a memória e os registros do rastreador. É usado principalmente para implementar a depuração do ponto de interrupção e o rastreamento de chamadas do sistema.

Nota 2: Existem diferentes parâmetros com os quais você pode usar strace, pois stracepodem ser muito detalhados. Eu gosto de experimentar o -cque é como um resumo das coisas. Com base em -cvocê pode selecionar uma chamada de sistema como a -e trace=openque você verá apenas essa chamada. Isso pode ser interessante se você estiver examinando quais arquivos serão abertos durante o comando que você está rastreando. E, é claro, você pode usar o grepmesmo objetivo, mas observe que precisa redirecionar assim 2>&1 | grep etcpara entender que os arquivos de configuração são referenciados quando o comando foi emitido.

Nota 3: Acho esta nota muito importante. Você não está limitado a uma arquitetura específica. stracevai impressionar você, pois ele pode rastrear binários de diferentes arquiteturas. insira a descrição da imagem aqui

prosti
fonte