Современный трассировщик системных вызовов на основе eBPF. Представьте strace, но с настоящим TUI, умными фильтрами, расшифровкой TLS и на самом деле читаемым выводом.
Трассировщик системных вызовов для Linux, построенный на eBPF. Как strace, но с живым TUI, умными фильтрами и декодированием аргументов, которое действительно можно прочитать.

$ 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>
Или запустите его без --raw и получите полноэкранный 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 использует ptrace, что останавливает ваш процесс при каждом системном вызове. snoop использует eBPF-трассировочные точки — ваш процесс продолжает работать на полной скорости, а трассировка выполняется в ядре. Помимо производительности, snoop декодирует аргументы в удобочитаемый вид, имеет TUI в реальном времени и может сохранять, воспроизводить и сравнивать трассы.
--raw (как в strace), --json (JSON Lines для jq), --explain (группировка системных вызовов в высокоуровневые сводки действий)--files, --net, --slow 10, --syscall openat-p PID) или запуск нового (snoop <команда>)--follow — трассировка также дочерних процессов при fork--docker <имя> и --pod <имя> — трассировка всего внутри контейнера--tls перехватывает SSL_write/SSL_read через uprobe и показывает открытый текст--ltrace отслеживает malloc/free/calloc/reallocsnoop record сохраняет на диск, snoop view воспроизводит офлайн (без прав root)snoop diff before.snoop after.snoop показывает изменения между двумя запусками--flamegraph out.svgНикаких модулей ядра, никакого C-тулчейна. eBPF-программы написаны на чистом Rust (aya) и встроены в бинарник.
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
Для aarch64 замените x86_64 на aarch64.
cargo install --git https://github.com/pandaadir05/snoop snoop
Это автоматически собирает eBPF-программы. Ни C-тулчейна, ни заголовков ядра не требуется — только Rust.
# Трассировка команды
sudo snoop ls /etc
sudo snoop -- nginx -g 'daemon off;'
# Подключение к работающему процессу
sudo snoop -p $(pidof postgres)
sudo snoop -p 1234 --follow # также трассировать дочерние процессы
# Контейнеры
sudo snoop --docker my-nginx
sudo snoop --pod my-app-pod --namespace production
# Фильтрация
sudo snoop -p 1234 --files # только вызовы файловой системы
sudo snoop -p 1234 --net # только сетевые вызовы
sudo snoop -p 1234 --slow 5 # только вызовы дольше 5 мс
sudo snoop -p 1234 --syscall openat --syscall read
--explain группирует сырые системные вызовы в высокоуровневые сводки вместо показа каждого вызова отдельно:
sudo snoop -p 1234 --explain
READ /etc/passwd ↓1.2 KB (2 вызова, 0.80мс)
NET 127.0.0.1:5432 ↑512 B ↓4.0 KB (18.20мс)
EXEC /usr/bin/python3
Перехватывает SSL_write/SSL_read в OpenSSL для захвата открытого текста:
sudo snoop -p 1234 --tls
sudo snoop -p 1234 --ltrace
Запишите трассу, затем воспроизведите её позже без 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")'
Полезно для обнаружения регрессий после развёртывания:
sudo snoop record -p 1234 -o before.snoop
# ... применить изменения ...
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> Подключиться к работающему процессу
--follow Трассировать дочерние процессы при fork (требуется --pid)
--docker <ИМЯ|ID> Трассировать все процессы в Docker-контейнере
--pod <POD> Трассировать все процессы в поде Kubernetes
-n, --namespace <NS> Пространство имён Kubernetes (по умолчанию: default)
--raw Построчный вывод, совместимый со strace
--json JSON Lines — один объект на системный вызов
--explain Смысловые сводки активности
--files Только вызовы файловой системы
--net Только сетевые вызовы
--slow <МИЛЛИСЕК> Только вызовы дольше порога
--syscall <ИМЯ> Только этот системный вызов (можно повторять)
--no-decode Сырые аргументы в шестнадцатеричном виде, без декодирования
--tls Захватывать открытый текст TLS через uprobe SSL_write/SSL_read
--ltrace Трассировать malloc/free/calloc/realloc
--flamegraph <ПУТЬ> Записать SVG-флеймграф при выходе
--ebpf-obj <ПУТЬ> Переопределить встроенный eBPF-объект [$SNOOP_EBPF_OBJ]