O strace no Linux é a ferramenta definitiva para entender o que um processo está fazendo no nível do kernel. Quando um programa falha silenciosamente, trava ou se comporta de forma inesperada, o strace revela exatamente quais chamadas de sistema estão sendo feitas — aberturas de arquivo, conexões de rede, alocações de memória e tratamento de sinais. Este guia cobre o uso prático do strace, desde rastreamentos básicos até técnicas de depuração em produção, com cenários do mundo real que demonstram como diagnosticar os problemas que você realmente encontra.

Pré-requisitos

  • Um sistema Linux (qualquer distribuição — o strace funciona em todas elas)
  • Acesso root ou sudo (necessário para rastrear processos pertencentes a outros usuários)
  • Conhecimento básico de processos Linux e descritores de arquivo
  • strace instalado (coberto na seção de instalação abaixo)

Instalando o strace no Linux

O strace está disponível no repositório de pacotes de todas as principais distribuições. Ele já pode estar instalado no seu sistema.

# Debian / Ubuntu
sudo apt install strace

# RHEL / CentOS / Fedora
sudo dnf install strace

# Arch Linux
sudo pacman -S strace

# Alpine Linux
sudo apk add strace

# Verificar a versão instalada
strace --version

Em imagens de container mínimas (Alpine, distroless), o strace geralmente não está presente. Instale-o temporariamente para depuração e remova das imagens de produção depois.

Rastreando um Comando desde o Início

O uso mais simples do strace é executá-lo na frente de qualquer comando:

strace ls /tmp

Isso imprime cada chamada de sistema que o ls faz, desde execve() até exit_group(). A saída vai para stderr, então a saída normal do comando ainda aparece no stdout.

Lendo a Saída do strace

Cada linha segue este formato:

syscall_name(arguments...) = return_value

Por exemplo:

openat(AT_FDCWD, "/tmp", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
getdents64(3, [{d_ino=2, d_off=1, d_type=DT_DIR, d_name="."},...], 32768) = 480
close(3)                                = 0

Isso mostra: o ls abriu /tmp como descritor de arquivo 3, leu as entradas do diretório e então o fechou. Um valor de retorno -1 significa que a chamada falhou, e o strace exibe o errno:

openat(AT_FDCWD, "/etc/shadow", O_RDONLY) = -1 EACCES (Permission denied)

Essa única linha frequentemente revela por que um programa falha — sem necessidade de ler o código-fonte ou adicionar logs de depuração.

Flags Úteis na Inicialização

# Seguir processos filhos (fork/clone)
strace -f ./my_app

# Imprimir timestamps para cada syscall
strace -t ls /tmp

# Imprimir tempo relativo entre syscalls (encontrar travamentos)
strace -r ls /tmp

# Imprimir argumentos de string completos (padrão trunca em 32 chars)
strace -s 256 ./my_app

# Gravar saída em arquivo em vez de stderr
strace -o /tmp/trace.log ls /tmp

Conectando o strace a um Processo em Execução

Você não precisa reiniciar um processo para rastreá-lo. Conecte-se a qualquer processo em execução pelo PID:

# Encontrar o PID
pidof nginx
# ou
ps aux | grep my_app

# Conectar ao processo
sudo strace -p 12345

# Conectar e seguir todas as threads/filhos
sudo strace -fp 12345

Pressione Ctrl+C para desconectar. O processo rastreado continua rodando normalmente — o strace não o encerra ao desconectar.

Cenário Real: Depurando uma Aplicação Travada

Você tem uma aplicação web em produção que ocasionalmente para de responder a requisições. Os logs não mostram nada. Em vez de reiniciar às cegas:

# Encontrar o PID do worker travado
sudo strace -fp $(pidof my_app) -e trace=network,file -s 256 -o /tmp/hang_trace.log

Envie uma requisição de teste e verifique o trace:

grep -E 'futex|poll|select|epoll_wait' /tmp/hang_trace.log | tail -20

Se o processo estiver preso em futex(FUTEX_WAIT) — ele está aguardando um mutex lock (deadlock). Se preso em connect() ou poll() com um timeout longo — está esperando por um serviço upstream que não está respondendo.

Filtrando Chamadas de Sistema com strace

Traces completos são ruidosos. Use -e trace= para focar no que importa:

# Apenas operações de arquivo (open, read, write, close, stat, etc.)
strace -e trace=file ls /tmp

# Apenas operações de rede (socket, connect, send, recv, etc.)
strace -e trace=network curl https://example.com

# Gerenciamento de processos (fork, clone, execve, wait, exit)
strace -e trace=process bash -c "ls | grep foo"

# Operações de memória (mmap, mprotect, brk)
strace -e trace=memory ./my_app

# Syscalls específicas por nome
strace -e trace=openat,read,write cat /etc/hostname

# Negação — rastrear tudo EXCETO estas
strace -e trace=!mmap,mprotect,brk ./my_app

Filtrando por Valor de Retorno

Encontre apenas as chamadas de sistema que falharam — extremamente útil para depuração:

# Mostrar apenas chamadas que retornaram erro
strace -Z ./my_app

# Mostrar apenas chamadas bem-sucedidas
strace -z ./my_app

O flag -Z (strace 5.2+) é uma mudança de jogo para depuração em produção. Em vez de vasculhar milhares de chamadas bem-sucedidas, você vê apenas as falhas.

Análise de Desempenho com strace

Resumo de Chamadas de Sistema

O flag -c produz um resumo estatístico em vez de um trace em tempo real:

strace -c ls /tmp
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 25.00    0.000045           5         9           mmap
 19.44    0.000035           5         7           close
 16.67    0.000030           5         6           openat
 11.11    0.000020           4         5           fstat
  8.33    0.000015           5         3           mprotect
  5.56    0.000010           3         3           read
  ...
------ ----------- ----------- --------- --------- ----------------
100.00    0.000180           4        42         2 total

Isso mostra quais chamadas de sistema consomem mais tempo. Se read ou write domina, você tem um processo limitado por I/O. Se futex domina, você tem contenção de lock.

Temporização de Chamadas Individuais

# Tempo de relógio de parede por syscall
strace -T ./my_app

# Combinado: timestamps + duração
strace -tT ./my_app

O flag -T acrescenta a duração entre colchetes angulares:

openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY) = 3 <0.000024>
read(3, "nameserver 8.8.8.8\n", 4096)  = 19 <0.000011>
connect(4, {sa_family=AF_INET, sin_port=htons(443)}, 16) = -1 EINPROGRESS <0.000089>

Esse connect() levando 89 microssegundos está ótimo. Se você vê ele levando mais de 5 segundos, seu DNS ou serviço upstream é o gargalo.

Comparando strace com Ferramentas Alternativas de Rastreamento

Recursostraceltraceperf tracebpftrace
RastreiaSyscalls do kernelChamadas de bibliotecaSyscalls do kernelKernel + espaço de usuário
OverheadAlto (10-100x)AltoBaixo (~5%)Muito baixo (~2%)
Conectar a PID em execuçãoSimSimSimSim
Filtrar por syscallSim (-e trace=)Sim (-e)Sim (—filter)Sim (scripts customizados)
Resumo estatísticoSim (-c)Sim (-c)Sim (—summary)Scripts customizados
Versão do kernel necessáriaQualquerQualquer3.7+4.9+ (eBPF)
Seguro em produçãoApenas uso breveApenas uso breveSimSim
Melhor paraDepuração rápidaProblemas de chamadas de bibliotecaProfiling com baixo overheadLógica de rastreamento complexa

Regra geral: Use strace para diagnóstico rápido (conecte, encontre o problema, desconecte). Mude para perf trace ou bpftrace para monitoramento contínuo em produção onde o overhead importa.

Padrões Comuns de Depuração com strace

Padrão 1: Descobrir por que um Programa Não Encontra um Arquivo

strace -e trace=openat,stat,access ./my_app 2>&1 | grep -i "no such file\|enoent\|eacces"

Isso mostra imediatamente todos os arquivos que o programa tenta abrir e falha. Comum em problemas de arquivos de configuração, bibliotecas compartilhadas ausentes ou caminhos incorretos.

Padrão 2: Descobrir Quais Arquivos de Configuração um Programa Lê

strace -e trace=openat ./my_app 2>&1 | grep -v ENOENT | grep '= [0-9]'

Isso filtra apenas as aberturas de arquivo bem-sucedidas — mostrando exatamente quais arquivos de configuração, bibliotecas e arquivos de dados o programa realmente usa.

Padrão 3: Depurar Problemas de Resolução DNS

strace -e trace=network -s 256 curl https://example.com 2>&1 | grep -E 'connect|sendto|recvfrom'

Você verá a consulta DNS indo para os nameservers em /etc/resolv.conf, a resposta e depois a conexão HTTPS real. Se a consulta DNS leva segundos, você encontrou a fonte de latência.

Padrão 4: Descobrir por que um Serviço Falha na Inicialização

sudo strace -f -o /tmp/service_trace.log systemctl start my_service
# Depois pesquise o trace por erros
grep '= -1' /tmp/service_trace.log | grep -v 'ENOENT.*locale\|ENOENT.*lib' | head -30

O grep filtra erros inofensivos de “arquivo não encontrado” oriundos da sondagem de locale e biblioteca (que são normais), deixando apenas as falhas reais.

Padrão 5: Monitorar Gravações de Arquivo em Tempo Real

sudo strace -fp $(pidof my_app) -e trace=write -s 1024 2>&1 | grep 'write([0-9]*,'

Veja cada byte que o processo grava em qualquer descritor de arquivo — útil para depurar problemas de logging ou modificações inesperadas de arquivos.

Casos Especiais e Armadilhas

Rastreando binários setuid: O strace não consegue se conectar a programas setuid a menos que você execute o próprio strace como root. O kernel remove as permissões de ptrace por segurança.

Aplicações multi-thread: Sempre use -f (seguir forks) com aplicações multi-thread. Sem ele, você vê apenas as syscalls da thread principal e perde as threads de trabalho onde o problema real vive.

Ambientes de container: Dentro de containers Docker, o strace requer a capability SYS_PTRACE. Execute com --cap-add=SYS_PTRACE ou use --privileged para depuração:

docker run --cap-add=SYS_PTRACE my_image strace ./my_app

No Kubernetes, adicione a capability ao security context do seu pod:

securityContext:
  capabilities:
    add: ["SYS_PTRACE"]

O impacto no desempenho é real: O strace intercepta cada chamada de sistema via ptrace, o que requer duas trocas de contexto por chamada. Um processo fazendo 100.000 syscalls/segundo será dramaticamente desacelerado. Nunca deixe o strace conectado a um processo de produção por mais tempo do que o necessário para capturar o problema.

strace -c mascara chamadas individualmente lentas: O resumo -c mostra médias. Um processo pode fazer 10.000 chamadas read() rápidas e uma read() de 30 segundos — a média parece boa. Use -C (maiúsculo) para obter tanto o resumo quanto o trace em tempo real para identificar outliers.

Solução de Problemas

”Operation not permitted” ao Conectar

# Verificar escopo do ptrace (Ubuntu/Debian)
cat /proc/sys/kernel/yama/ptrace_scope

Se o valor for 1 (padrão no Ubuntu), você só pode rastrear seus próprios processos. Para permitir temporariamente o rastreamento de qualquer processo:

# Temporário — redefine ao reiniciar
sudo sysctl kernel.yama.ptrace_scope=0

# Ou simplesmente use sudo com strace
sudo strace -p 12345

A Saída do Trace é Avassaladora

# Combinar filtros: apenas operações de arquivo com falha com temporização
strace -Z -e trace=file -T -s 256 ./my_app 2>&1 | head -50

Necessidade de Rastrear um Processo de Vida Curta

Para processos que iniciam e terminam rapidamente (como tarefas cron):

# Envolver o comando
strace -f -o /tmp/cron_trace.log /path/to/cron_script.sh

# Ou rastrear o pai que o spawna
sudo strace -fp $(pidof crond) -o /tmp/cron_trace.log

Resumo

  • strace rastreia chamadas de sistema do kernel — use quando um processo falha silenciosamente, trava ou se comporta mal e os logs não dão pistas
  • Conecte-se a processos em execução com strace -p PID sem reiniciá-los — adicione -f para aplicações multi-thread
  • Filtre com -e trace= para focar em operações de arquivo, rede, processo ou memória em vez de se afogar em ruído
  • Use -Z para mostrar apenas chamadas com falha — a forma mais rápida de descobrir por que algo está quebrado
  • Use -c para resumos de desempenho — identifique quais chamadas de sistema consomem mais tempo
  • O overhead de desempenho é significativo — conecte brevemente em produção e desconecte. Para rastreamento contínuo, use perf trace ou bpftrace
  • Containers precisam da capability SYS_PTRACE — adicione-a explicitamente no Docker ou Kubernetes

Artigos Relacionados