
eBPF 기반의 최신 syscall 트레이서입니다. 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 tracepoint를 사용합니다. 프로세스는 커널 내에서 트레이싱이 발생하는 동안 전체 속도로 계속 실행됩니다. 성능 외에도 snoop은 인수를 실제로 읽을 수 있는 형태로 디코딩하고, 실시간 TUI를 제공하며, 트레이스를 저장/재생/비교할 수 있습니다.
--raw (strace 호환), --json (JSON Lines, jq용), --explain (시스템 콜을 상위 수준 활동 요약으로 그룹화)--files, --net, --slow 10, --syscall openat-p PID) 또는 생성 (snoop <cmd>)--follow는 포크된 자식도 추적합니다.--docker <name> 및 --pod <name>으로 컨테이너 내부의 모든 것을 추적합니다.커널 모듈이나 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 # 5ms보다 느린 호출만
sudo snoop -p 1234 --syscall openat --syscall read
--explain은 원시 시스템 콜을 개별 호출 대신 상위 수준 요약으로 그룹화합니다:
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
OpenSSL에서 SSL_write/SSL_read를 연결하여 평문을 캡처합니다:
sudo snoop -p 1234 --tls
sudo snoop -p 1234 --ltrace
트레이스를 기록한 후 나중에 루트 없이 재생:
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 포크된 자식 추적 (--pid 필요)
--docker <NAME|ID> Docker 컨테이너의 모든 프로세스 추적
--pod <POD> Kubernetes 파드의 모든 프로세스 추적
-n, --namespace <NS> Kubernetes 네임스페이스 (기본값: default)
--raw 한 줄 strace 호환 출력
--json JSON Lines — 시스템 콜당 하나의 객체
--explain 의미론적 활동 요약
--files 파일 시스템 시스템 콜만
--net 네트워크 시스템 콜만
--slow <MILLIS> 임계값보다 느린 호출만
--syscall <NAME> 이 시스템 콜만 (반복 가능)
--no-decode 원시 16진수 인수, 디코딩 없음
--tls SSL_write/SSL_read uprobe를 통해 TLS 평문 캡처
--ltrace malloc/free/calloc/realloc 추적
--flamegraph <PATH> 종료 시 플레임그래프 SVG 작성
--ebpf-obj <PATH> 내장된 eBPF 객체 재정의 [$SNOOP_EBPF_OBJ]
두 개의 eBPF 프로그램이 raw_syscalls/sys_enter 및 sys_exit에 연결됩니다. 진입 시 시스템 콜 번호와 인수가 스레드별 스크래치 맵에 저장됩니다. 종료 시 반환값이 진입 데이터와 쌍을 이루어 링 버퍼로 푸시됩니다. 사용자 공간은 비동기 fd를 통해 링 버퍼를 소비하고 모든 것을 필터/디코드 파이프라인에 전달합니다.
커널 사용자 공간
────── ─────────
raw_syscalls/sys_enter ──► SYSCALL_ENTER 맵 (스레드별 스크래치)
raw_syscalls/sys_exit ──► EVENTS 링 버퍼 (4 MiB)
│
폴 소비자 (tokio::spawn)
│
┌──────────┴──────────┐
RawOutput TuiApp
(한 줄/시스템 콜) (ratatui TUI)
eBPF 프로그램은 aya를 사용하여 Rust로 작성되었으며, 빌드 시 BPF 바이트코드로 컴파일되어 바이너리에 내장됩니다. 런타임 종속성이나 커널 헤더가 필요 없습니다.
git clone https://github.com/pandaadir05/snoop
cd snoop
# Nightly는 BPF 타겟에만 필요합니다
rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
# bpf-linker가 eBPF 객체를 링크합니다 (시스템 LLVM 불필요)
cargo install bpf-linker --no-default-features
cargo build --release
sudo ./target/release/snoop -p $$
빌드 스크립트가 eBPF 프로그램을 자동으로 컴파일합니다. 별도 단계가 필요 없습니다.
개발 중에는 xtask를 사용할 수도 있습니다:
cargo xtask run -- -p $$
MIT 또는 Apache-2.0, 선택 사항입니다.
--tlsSSL_writeSSL_read--ltrace는 malloc/free/calloc/realloc을 추적합니다.snoop record로 디스크에 저장하고, snoop view로 오프라인 재생 (루트 불필요)snoop diff before.snoop after.snoop으로 두 실행 간의 차이를 보여줍니다.--flamegraph out.svg| 키 | 동작 |
|---|
q | 종료 |
Space | 일시 중지 / 재개 |
/ | 증분 검색 |
f | 파일 시스템 필터 켜기/끄기 |
n | 네트워크 필터 켜기/끄기 |
c | 이벤트 목록 지우기 |
Enter | 선택한 이벤트의 세부 정보 팝업 표시 |
↑ / k | 위로 스크롤 |
↓ / j | 아래로 스크롤 |
G / End | 최신 이벤트로 이동 |
g / Home | 가장 오래된 이벤트로 이동 |
| 계층 | 크레이트 |
|---|
| eBPF 프로그램 | aya-ebpf |
| eBPF 로더 | aya |
| TUI | ratatui + crossterm |
| CLI | clap (derive) |
| 비동기 런타임 | tokio |
| 플레임그래프 | inferno |