
Ein moderner Syscall-Tracer, der auf eBPF basiert. Stellen Sie sich strace vor, aber mit einer echten TUI, intelligenten Filtern, TLS-Entschlüsselung und einer Ausgabe, die tatsächlich lesbar ist.
Ein Syscall-Tracer für Linux, basierend auf eBPF. Wie strace, aber mit einer Live-TUI, intelligenten Filtern und Argument-Dekodierung, die man tatsächlich lesen kann.

$ 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>
Oder führen Sie es ohne --raw aus und erhalten eine Vollbild-TUI:
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 verwendet ptrace, das Ihren Prozess bei jedem Syscall anhält. snoop verwendet stattdessen eBPF-Tracepoints – Ihr Prozess läuft mit voller Geschwindigkeit weiter, während die Ablaufverfolgung im Kernel stattfindet. Neben der Leistung dekodiert snoop Argumente in etwas Lesbares, bietet eine Echtzeit-TUI und kann Traces speichern, wiedergeben und vergleichen.
--raw (strace-kompatibel), --json (JSON Lines für jq), --explain (fasst Syscalls zu High-Level-Aktivitätszusammenfassungen zusammen)--files, --net, --slow 10, --syscall openat-p PID) oder starten (snoop <cmd>)--follow verfolgt auch Kindprozesse (fork)--docker <Name> und --pod <Name> verfolgen alles in einem ContainerKein Kernel-Modul, keine C-Toolchain. Die eBPF-Programme sind reines Rust (aya) und werden im Binärpaket mitgeliefert.
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
Für aarch64 ersetzen Sie x86_64 durch aarch64.
cargo install --git https://github.com/pandaadir05/snoop snoop
Dies erstellt die eBPF-Programme automatisch. Keine C-Toolchain oder Kernel-Header nötig, nur Rust.
# Befehl ablaufen lassen
sudo snoop ls /etc
sudo snoop -- nginx -g 'daemon off;'
# An laufenden Prozess anhängen
sudo snoop -p $(pidof postgres)
sudo snoop -p 1234 --follow # auch Kindprozesse (fork) verfolgen
# Container
sudo snoop --docker my-nginx
sudo snoop --pod my-app-pod --namespace production
# Filtern
sudo snoop -p 1234 --files # nur Dateisystem-Aufrufe
sudo snoop -p 1234 --net # nur Netzwerk-Aufrufe
sudo snoop -p 1234 --slow 5 # nur Aufrufe, die länger als 5ms dauern
sudo snoop -p 1234 --syscall openat --syscall read
--explain fasst rohe Syscalls zu High-Level-Zusammenfassungen zusammen, anstatt jeden einzelnen Aufruf anzuzeigen:
sudo snoop -p 1234 --explain
READ /etc/passwd ↓1.2 KB (2 Aufrufe, 0.80ms)
NET 127.0.0.1:5432 ↑512 B ↓4.0 KB (18.20ms)
EXEC /usr/bin/python3
Hakt SSL_write/SSL_read in OpenSSL ein, um Klartext zu erfassen:
sudo snoop -p 1234 --tls
sudo snoop -p 1234 --ltrace
Nehmen Sie einen Trace auf und spielen Sie ihn später ohne Root wieder ab:
sudo snoop record -p 1234 -o trace.snoop
snoop view trace.snoop
snoop view trace.snoop --files --slow 5 --json | jq 'select(.name=="read")'
Nützlich, um Regressionen nach einem Deployment zu erkennen:
sudo snoop record -p 1234 -o before.snoop
# ... Änderung ausrollen ...
sudo snoop record -p 1234 -o after.snoop
snoop diff before.snoop after.snoop
SYSCALL-ANZAHLEN
read 1200 → 1800 (+50.0%) ▲
openat 340 → 210 (-38.2%) ▼
DAUER-REGRESSIONEN (Median)
read 0.02ms → 0.08ms (+300%)
NUR IN after
statx (4x)
sudo snoop -p 1234 --json | jq 'select(.name == "connect")'
sudo snoop -p 1234 --flamegraph syscalls.svg
-p, --pid <PID> An einen laufenden Prozess anhängen
--follow Kindprozesse (fork) verfolgen (erfordert --pid)
--docker <NAME|ID> Alle Prozesse in einem Docker-Container verfolgen
--pod <POD> Alle Prozesse in einem Kubernetes-Pod verfolgen
-n, --namespace <NS> Kubernetes-Namespace (Standard: default)
--raw Einzeilige, strace-kompatible Ausgabe
--json JSON Lines – ein Objekt pro Syscall
--explain Semantische Aktivitätszusammenfassungen
--files Nur Dateisystem-Syscalls
--net Nur Netzwerk-Syscalls
--slow <MILLIS> Nur Aufrufe, die langsamer als der Schwellwert sind
--syscall <NAME> Nur dieser Syscall (wiederholbar)
--no-decode Rohe Hex-Argumente, keine Dekodierung
--tls TLS-Klartext via SSL_write/SSL_read uprobes erfassen
--ltrace malloc/free/calloc/realloc verfolgen
--flamegraph <PFAD> Flamegraph-SVG beim Beenden schreiben
--ebpf-obj <PFAD> Eingebettetes eBPF-Objekt überschreiben [$SNOOP_EBPF_OBJ]
Zwei eBPF-Programme hängen an raw_syscalls/sys_enter und sys_exit. Beim Eintritt werden die Syscall-Nummer und Argumente in eine pro-Thread-Scratch-Map geschrieben. Beim Austritt wird der Rückgabewert mit den Eintrittsdaten kombiniert und in einen Ringpuffer geschoben. Userspace entleert den Ringpuffer über einen asynchronen fd und leitet alles durch die Filter-/Dekodier-Pipeline.
Kernel Userspace
────── ─────────
raw_syscalls/sys_enter ──► SYSCALL_ENTER Map (pro-tid Scratch)
raw_syscalls/sys_exit ──► EVENTS Ringpuffer (4 MiB)
│
Poll-Consumer (tokio::spawn)
│
┌──────────┴──────────┐
RawOutput TuiApp
(eine Zeile/Syscall) (ratatui TUI)
eBPF-Programme sind in Rust mit aya geschrieben, werden zur Build-Zeit zu BPF-Bytecode kompiliert und im Binärpaket eingebettet. Keine Laufzeit-Abhängigkeiten, keine Kernel-Header.
git clone https://github.com/pandaadir05/snoop
cd snoop
# Nightly wird nur für das BPF-Target benötigt
rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
# bpf-linker verknüpft das eBPF-Objekt (kein system-LLVM nötig)
cargo install bpf-linker --no-default-features
cargo build --release
sudo ./target/release/snoop -p $$
Das Build-Skript kompiliert die eBPF-Programme automatisch. Kein separater Schritt nötig.
Während der Entwicklung kann auch xtask verwendet werden:
cargo xtask run -- -p $$
MIT oder Apache-2.0, nach Ihrer Wahl.
--tls hakt SSL_write/SSL_read via uprobes ein, um Klartext anzuzeigen--ltrace verfolgt malloc/free/calloc/reallocsnoop record speichert auf Disk, snoop view spielt offline ab (kein Root nötig)snoop diff before.snoop after.snoop zeigt, was sich zwischen zwei Läufen geändert hat--flamegraph out.svg| Taste | Aktion |
|---|
q | Beenden |
Space | Pause / Fortsetzen |
/ | Inkrementelle Suche |
f | Dateisystem-Filter umschalten |
n | Netzwerk-Filter umschalten |
c | Ereignisliste löschen |
Enter | Detail-Popup für ausgewähltes Ereignis anzeigen |
↑ / k | Nach oben scrollen |
↓ / j | Nach unten scrollen |
G / Ende | Zum neuesten Ereignis springen |
g / Pos1 | Zum ältesten Ereignis springen |
| Ebene | Crate |
|---|
| eBPF-Programme | aya-ebpf |
| eBPF-Lader | aya |
| TUI | ratatui + crossterm |
| CLI | clap (derive) |
| Async-Runtime | tokio |
| Flamegraph | inferno |