
Um rastreador moderno de chamadas de sistema construído sobre eBPF. Pense no strace, mas com uma TUI real, filtros inteligentes, descriptografia TLS e uma saída que é realmente legível.
Um rastreador de syscalls para Linux, construído sobre eBPF. Como o strace, mas com uma TUI ao vivo, filtros inteligentes e decodificação de argumentos que você pode realmente ler.

$ sudo snoop curl https://example.com
[ 0.001] curl(1234/1234) openat(AT_FDCWD, "/etc/ssl/certs/ca-certificates.crt", O_RDONLY) = 4 <0.031ms>
[ 0.002] curl(1234/1234) read(4, 0x7f3a1c000b20, 4096) = 4096 <0.012ms>
[ 0.003] curl(1234/1234) socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 5 <0.008ms>
[ 0.004] curl(1234/1234) connect(5, 93.184.216.34:443) = 0 <42.187ms>
[ 0.046] curl(1234/1234) sendto(5, 0x55a3bc001b40, 78, MSG_NOSIGNAL) = 78 <0.011ms>
Ou execute sem --raw e obtenha uma TUI em tela cheia:
snoop pid:1234 comm:curl events:142 elapsed:0.341s
┌── syscall stream ─────────────────────────────────────┐┌── top syscalls ─────────┐
│ [ 0.001] curl openat("/etc/ssl/…") = 4 <0.031ms> ││ syscall count pct│
│ [ 0.002] curl read(4, …) = 4096 ││ read 38 26.8%│
│ [ 0.003] curl socket(AF_INET, …) = 5 ││ write 21 14.8%│
│ [ 0.004] curl connect(5, 93.184.216.34:443) = 0 ││ openat 18 12.7%│
│ [ 0.046] curl sendto(5, …) = 78 ││ mmap 14 9.9%│
└───────────────────────────────────────────────────────┘└─────────────────────────┘
[q]uit [Space]pause [/]search [f]iles [n]et [c]lear [↑↓]scroll [G]bottom
strace usa ptrace, que para o seu processo a cada syscall. snoop usa tracepoints eBPF em vez disso — seu processo continua rodando a toda velocidade com o rastreamento acontecendo no kernel. Além do desempenho, snoop decodifica argumentos em algo que você pode realmente ler, tem uma TUI em tempo real e pode salvar/reproduzir/diferenciar rastros.
--raw (compatível com strace), --json (JSON Lines para
jq), --explain (agrupa syscalls em resumos de atividade de alto nível)--files, --net, --slow 10, --syscall openat-p PID) ou iniciar um (snoop <cmd>)--follow rastreia também filhos bifurcados--docker <nome> e --pod <nome> rastreiam tudo
dentro de um container--tls intercepta SSL_write/SSL_read via uprobes para mostrar
texto simples--ltrace monitora malloc/free/calloc/reallocsnoop record salva em disco, snoop view reproduz
offline (sem necessidade de root)snoop diff before.snoop after.snoop mostra o que mudou entre
duas execuções--flamegraph out.svgSem módulos de kernel, sem toolchain C. Os programas eBPF são puramente Rust (aya) e são embutidos no binário.
CAP_BPF + CAP_PERFMONcurl -L https://github.com/pandaadir05/snoop/releases/latest/download/snoop-x86_64-linux.tar.gz \
| tar -xz
sudo install -m755 snoop /usr/local/bin/snoop
Para aarch64, substitua x86_64 por aarch64.
cargo install --git https://github.com/pandaadir05/snoop snoop
Isso compila os programas eBPF automaticamente. Nenhuma toolchain C ou cabeçalhos de kernel necessários, apenas Rust.
# Rastrear um comando
sudo snoop ls /etc
sudo snoop -- nginx -g 'daemon off;'
# Anexar a um processo em execução
sudo snoop -p $(pidof postgres)
sudo snoop -p 1234 --follow # rastrear também filhos bifurcados
# Containers
sudo snoop --docker my-nginx
sudo snoop --pod my-app-pod --namespace production
# Filtragem
sudo snoop -p 1234 --files # apenas chamadas de sistema de arquivos
sudo snoop -p 1234 --net # apenas chamadas de rede
sudo snoop -p 1234 --slow 5 # apenas chamadas mais lentas que 5ms
sudo snoop -p 1234 --syscall openat --syscall read
--explain agrupa syscalls brutos em resumos de alto nível em vez de mostrar
cada chamada individualmente:
sudo snoop -p 1234 --explain
READ /etc/passwd ↓1.2 KB (2 calls, 0.80ms)
NET 127.0.0.1:5432 ↑512 B ↓4.0 KB (18.20ms)
EXEC /usr/bin/python3
Intercepta SSL_write/SSL_read no OpenSSL para capturar texto simples:
sudo snoop -p 1234 --tls
sudo snoop -p 1234 --ltrace
Grave um rastro e depois reproduza-o mais tarde sem root:
sudo snoop record -p 1234 -o trace.snoop
snoop view trace.snoop
snoop view trace.snoop --files --slow 5 --json | jq 'select(.name=="read")'
Útil para detectar regressões após uma implantação:
sudo snoop record -p 1234 -o before.snoop
# ... implantar mudança ...
sudo snoop record -p 1234 -o after.snoop
snoop diff before.snoop after.snoop
SYSCALL COUNTS
read 1200 → 1800 (+50.0%) ▲
openat 340 → 210 (-38.2%) ▼
DURATION REGRESSIONS (median)
read 0.02ms → 0.08ms (+300%)
ONLY IN after
statx (4x)
sudo snoop -p 1234 --json | jq 'select(.name == "connect")'
sudo snoop -p 1234 --flamegraph syscalls.svg
-p, --pid <PID> Anexar a um processo em execução
--follow Rastrear filhos bifurcados (requer --pid)
--docker <NOME|ID> Rastrear todos os processos em um container Docker
--pod <POD> Rastrear todos os processos em um pod Kubernetes
-n, --namespace <NS> Namespace do Kubernetes (padrão: default)
--raw Saída de uma linha compatível com strace
--json JSON Lines — um objeto por syscall
--explain Resumos de atividade semântica
--files Apenas syscalls do sistema de arquivos
--net Apenas syscalls de rede
--slow <MILISSEGUNDOS> Apenas chamadas mais lentas que o limite
--syscall <NOME> Apenas esta syscall (repetível)
--no-decode Argumentos hex brutos, sem decodificação
--tls Capturar texto simples TLS via uprobes SSL_write/SSL_read
--ltrace Rastrear malloc/free/calloc/realloc
--flamegraph <CAMINHO> Escrever SVG de flamegraph ao sair
--ebpf-obj <CAMINHO> Substituir objeto eBPF embutido [$SNOOP_EBPF_OBJ]
| Tecla | Ação |
|---|---|
q | Sair |
Espaço | Pausar / retomar |
/ | Busca incremental |
f | Alternar filtro de sistema de arquivos |
n | Alternar filtro de rede |
c | Limpar lista de eventos |
Enter | Mostrar popup de detalhes para o evento selecionado |
↑ / k | Rolar para cima |
↓ / j | Rolar para baixo |
G / Fim | Ir para o evento mais recente |
g / Início | Ir para o evento mais antigo |
Dois programas eBPF se anexam a raw_syscalls/sys_enter e sys_exit. Na entrada,
o número da syscall e os argumentos vão para um mapa de rascunho por thread. Na saída, o
valor de retorno é combinado com os dados de entrada e enviado para um ring buffer.
O espaço do usuário drena o ring buffer através de um fd assíncrono e passa tudo pelo
pipeline de filtro/decodificação.
kernel userspace
────── ─────────
raw_syscalls/sys_enter ──► SYSCALL_ENTER map (rascunho por tid)
raw_syscalls/sys_exit ──► EVENTS ring buffer (4 MiB)
│
consumidor poll (tokio::spawn)
│
┌──────────┴──────────┐
RawOutput TuiApp
(uma linha/syscall) (ratatui TUI)
Os programas eBPF são escritos em Rust com aya, compilados para bytecode BPF no momento da compilação e embutidos no binário. Sem dependências de tempo de execução, sem cabeçalhos de kernel.
git clone https://github.com/pandaadir05/snoop
cd snoop
# Nightly só é necessário para o alvo BPF
rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
# bpf-linker liga o objeto eBPF (nenhum LLVM do sistema necessário)
cargo install bpf-linker --no-default-features
cargo build --release
sudo ./target/release/snoop -p $$
O script de compilação compila os programas eBPF automaticamente. Nenhuma etapa separada necessária.
Durante o desenvolvimento, você também pode usar xtask:
cargo xtask run -- -p $$
| Camada | Crate |
|---|---|
| Programas eBPF | aya-ebpf |
| Carregador eBPF | aya |
| TUI | ratatui + crossterm |
| CLI | clap (derive) |
| Runtime assíncrono | tokio |
| Flamegraph | inferno |
MIT ou Apache-2.0, à sua escolha.