pandaadir05/snoop
GitHub: pandaadir05/snoop
一款基于 eBPF 的 Linux 系统调用追踪器,提供低开销实时 TUI、可视化过滤与 TLS 解密,替代传统 strace 提升观测效率。
Stars: 33 | Forks: 0
# snoop
[](https://github.com/pandaadir05/snoop/actions/workflows/ci.yml)
[](LICENSE)
一个基于 eBPF 的 Linux 系统调用追踪器。类似 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?
strace 使用 ptrace,会在每次系统调用时暂停进程。snoop 使用 eBPF tracepoints —— 进程保持全速运行,追踪在内核中完成。除了性能优势,snoop 还能将参数解码为可读内容、提供实时 TUI,并支持保存/回放/对比追踪。
## 功能
- **TUI** — 实时滚动的系统调用流,包含顶部系统调用面板、搜索、类别过滤、暂停/恢复。当 stdout 不是终端时自动回退为 strace 风格的行输出。
- **输出格式** — `--raw`(strace 兼容)、`--json`(JSON Lines,供 jq 使用)、`--explain`(将系统调用归类为高层活动摘要)
- **过滤** — `--files`、`--net`、`--slow 10`、`--syscall openat`
- **参数解码** — 对 60 多种系统调用进行解码 — 路径、标志、套接字地址等,无需再查阅手册页
- **附加** — 可附加到运行中的进程(`-p PID`)或直接启动一个(`snoop `)
- `--follow` — 同时追踪 fork 的子进程
- **容器** — `--docker ` 和 `--pod ` 可追踪容器内所有进程
- **TLS 捕获** — `--tls` 通过 uprobes 挂钩 `SSL_write`/`SSL_read` 显示明文
- **堆栈追踪** — `--ltrace` 跟踪 `malloc`/`free`/`calloc`/`realloc`
- **记录与回放** — `snoop record` 保存到磁盘,`snoop view` 离线回放(无需 root)
- **对比** — `snoop diff before.snoop after.snoop` 显示两次运行之间的差异
- **火焰图** — `--flamegraph out.svg`
无需内核模块,也无需 C 工具链。eBPF 程序使用纯 Rust(aya)编写,并内嵌在二进制文件中。
## 系统要求
- Linux 5.8+(需要 BPF 环形缓冲区支持)
- x86_64 或 aarch64
- 需 root 权限或 `CAP_BPF` + `CAP_PERFMON`
## 安装
### 预编译二进制文件
```
curl -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 # trace forked children too
# 容器
sudo snoop --docker my-nginx
sudo snoop --pod my-app-pod --namespace production
# 过滤
sudo snoop -p 1234 --files # only file-system calls
sudo snoop -p 1234 --net # only network calls
sudo snoop -p 1234 --slow 5 # only calls slower than 5ms
sudo snoop -p 1234 --syscall openat --syscall read
```
### Explain 模式
`--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
```
### TLS 解密
挂钩 `SSL_write`/`SSL_read` 以捕获明文:
```
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)
```
### JSON 输出
```
sudo snoop -p 1234 --json | jq 'select(.name == "connect")'
```
### 导出火焰图
```
sudo snoop -p 1234 --flamegraph syscalls.svg
```
## 标志
```
-p, --pid Attach to a running process
--follow Trace forked children (requires --pid)
--docker Trace all processes in a Docker container
--pod Trace all processes in a Kubernetes pod
-n, --namespace Kubernetes namespace (default: default)
--raw One-line strace-compatible output
--json JSON Lines — one object per syscall
--explain Semantic activity summaries
--files File-system syscalls only
--net Network syscalls only
--slow Only calls slower than threshold
--syscall Only this syscall (repeatable)
--no-decode Raw hex arguments, no decoding
--tls Capture TLS plaintext via SSL_write/SSL_read uprobes
--ltrace Trace malloc/free/calloc/realloc
--flamegraph Write flamegraph SVG on exit
--ebpf-obj Override embedded eBPF object [$SNOOP_EBPF_OBJ]
```
## TUI 按键绑定
| 按键 | 操作 |
| --- | --- |
| `q` | 退出 |
| `Space` | 暂停 / 恢复 |
| `/` | 增量搜索 |
| `f` | 切换文件系统过滤 |
| `n` | 切换网络过滤 |
| `c` | 清除事件列表 |
| `Enter` | 显示选中事件的详情弹窗 |
| `↑` / `k` | 向上滚动 |
| `↓` / `j` | 向下滚动 |
| `G` / `End` | 跳至最新事件 |
| `g` / `Home` | 跳至最早事件 |
## 工作原理
两个 eBPF 程序分别挂载到 `raw_syscalls/sys_enter` 和 `sys_exit`。在进入时,系统调用号和参数写入每个线程的暂存 Map;在退出时,返回值与入口数据配对并推送到环形缓冲区。
用户空间通过异步 fd 读取环形缓冲区,并经过过滤/解码管道处理。
```
kernel userspace
────── ─────────
raw_syscalls/sys_enter ──► SYSCALL_ENTER map (per-tid scratch)
raw_syscalls/sys_exit ──► EVENTS ring buffer (4 MiB)
│
poll consumer (tokio::spawn)
│
┌──────────┴──────────┐
RawOutput TuiApp
(one line/syscall) (ratatui TUI)
```
eBPF 程序使用 Rust 与 [aya](https://github.com/aya-rs/aya) 编写,在构建时编译为 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 $$
```
## 技术栈
| 层级 | Crate |
| --- | --- |
| eBPF 程序 | `aya-ebpf` |
| eBPF 加载器 | `aya` |
| TUI | `ratatui` + `crossterm` |
| CLI | `clap`(derive) |
| 异步运行时 | `tokio` |
| 火焰图 | `inferno` |
## 许可证
MIT 或 Apache-2.0,任选其一。
标签:Go, Linux 调试, Ruby工具, Rust, strace 替代, syscall tracer, TLS 解密, TUI 界面, 二进制发布, 可视化界面, 可读输出, 子域名生成, 开源工具, 性能分析, 智能过滤, 系统追踪, 网络流量审计, 网络调试, 自动化, 通知系统