Files
syscall_monitor/README.md
MarceloZoeng 83ac6179dc
All checks were successful
CI / lint-and-build (push) Successful in 24s
CD / deploy (push) Successful in 8s
加入 emoji 节标志
2026-06-14 12:41:37 +08:00

165 lines
7.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<h1 align="center">syscall_monitor</h1>
<p align="center">
<strong>基于 eBPF 的 Linux 系统调用计数监控器,附带 Flask 可视化界面</strong>
</p>
<p align="center">
<img src="https://img.shields.io/badge/python-3-blue?style=flat-square&logo=python&logoColor=white" alt="python">
<img src="https://img.shields.io/badge/flask-3.1-000000?style=flat-square&logo=flask&logoColor=white" alt="flask">
<img src="https://img.shields.io/badge/bcc-0.29-orange?style=flat-square" alt="bcc">
<img src="https://img.shields.io/badge/platform-linux-lightgrey?style=flat-square&logo=linux&logoColor=white" alt="platform">
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="license">
</p>
## 📖 项目简介
`syscall_monitor` 在 Linux 内核 `raw_syscalls:sys_enter` 跟踪点上挂载一段 eBPF 程序,按系统调用号在内核态做哈希计数;用户态由 Python 每秒读取一次快照,并在 Flask Web 页面上展示配置项中关心的系统调用调用次数。
由于挂载 eBPF 需要内核能力CAP_BPF / root整个程序必须以 root 权限运行。
## ✨ 主要特性
- 内核态全量计数用户态按需展示BPF 程序对所有系统调用号自增计数,配置变化无需重新挂载探针。
- 可在 Web 页面动态增删需要监控的系统调用名称,无需重启进程。
- `/api/counts` JSON 接口供前端每秒轮询,页面实时刷新。
- 后台采集线程 + 配置文件原子写入(`tmp``replace`),并发读写不丢更新。
- 提供 `setup.sh` / `run.sh` / `stop.sh` 三个部署脚本,配套 Gitea Actions CI/CD 工作流。
## 🧰 技术栈
| 类别 | 选型 | 来源 |
|------|------|------|
| 运行环境 | Linux需 root要求内核支持 eBPF/tracepoints | [main.py](main.py), [collector/syscall_tracer.py](collector/syscall_tracer.py) |
| 语言 | Python 3 | [requirements.txt](requirements.txt) |
| Web 框架 | Flask 3.1 + Jinja2 | [requirements.txt](requirements.txt), [web/app.py](web/app.py) |
| 内核采集 | bcc 0.29BPF Compiler Collection | [requirements.txt](requirements.txt), [collector/syscall_tracer.py](collector/syscall_tracer.py) |
| 前端 | 服务端模板 + 原生 JS `fetch` 轮询 | [web/templates/](web/templates/) |
| CI/CD | Gitea Actionsself-hosted runner | [.gitea/workflows/](.gitea/workflows/) |
## 📁 项目结构
```text
syscall_monitor/
├── main.py # 程序入口,校验 root 后启动 Flask
├── collector/
│ ├── __init__.py
│ └── syscall_tracer.py # eBPF 程序与采集线程
├── web/
│ ├── __init__.py
│ ├── app.py # Flask 应用工厂与路由
│ ├── static/style.css
│ └── templates/
│ ├── index.html # 实时监控页
│ └── config.html # 监控项配置页
├── config/
│ └── monitors.json # 需要展示的 syscall 名称列表
├── requirements.txt
├── setup.sh # 创建 venv--system-site-packages并装依赖
├── run.sh # nohup 后台启动pid 写入 .pid
├── stop.sh # 根据 .pid 停止进程
├── .gitea/
│ ├── README.md # CI/CD 详细说明
│ └── workflows/
│ ├── ci.yml # 语法检查 + venv 构建
│ └── cd.yml # rsync 部署 + 健康检查
└── LICENSE
```
## 🧬 模块关系
```mermaid
flowchart LR
Kernel[Linux Kernel<br/>raw_syscalls:sys_enter] -->|tracepoint| BPF[BPF_HASH counts]
BPF -->|每秒读取| Tracer[SyscallTracer<br/>后台线程]
Tracer -->|快照| Flask[Flask app]
Config[(config/monitors.json)] --> Tracer
Config --> Flask
Flask -->|/| IndexPage[实时监控页]
Flask -->|/api/counts| IndexPage
Flask -->|/config| ConfigPage[配置页]
```
## 🚀 快速开始
### 环境要求
- Linux 主机root 权限
- Python 3 + venv
- `bcc` / `python3-bpfcc` 等内核工具及对应内核头文件
参考安装命令(来自 [.gitea/README.md](.gitea/README.md)
```bash
sudo apt install -y python3-venv python3-bpfcc bpfcc-tools rsync curl linux-headers-$(uname -r)
```
### 安装
```bash
./setup.sh
```
脚本会创建启用 `--system-site-packages``.venv`(让 apt 安装的 bcc 在虚拟环境中可见),并按 `requirements.txt` 安装依赖。
### 配置
监控项保存在 [config/monitors.json](config/monitors.json) 的 `syscalls` 字段中,默认包含:`openat``read``write``execve``close`
也可在 Web 配置页通过表单新增或移除监控项,文件会被原子化写入。
### 运行
```bash
sudo ./run.sh
```
默认监听 `0.0.0.0:5000`,可通过环境变量覆盖:
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `HOST` | `0.0.0.0` | Flask 监听地址 |
| `PORT` | `5000` | Flask 监听端口 |
启动日志位于 `logs/app.log`,进程号写入 `.pid`
### 停止
```bash
sudo ./stop.sh
```
## 🔌 接口
| 方法 | 路径 | 处理函数 | 说明 |
|------|------|----------|------|
| GET | `/` | `index` | 实时监控首页,前端每秒轮询 `/api/counts` 刷新 |
| GET | `/api/counts` | `api_counts` | 返回 `{syscall 名: 累计次数}` 的 JSON |
| GET | `/config` | `config_page` | 监控项配置页 |
| POST | `/config` | `config_page` | 表单字段 `action=add/remove``name=<syscall>`PRG 后重定向回配置页 |
来源:[web/app.py](web/app.py)。
## 🚢 部署
仓库内附带的 Gitea Actions 工作流面向 **self-hosted Linux runner**
- [.gitea/workflows/ci.yml](.gitea/workflows/ci.yml)push / PR 到 `main` 触发,做 Python 语法检查并在临时 venv 中安装依赖。
- [.gitea/workflows/cd.yml](.gitea/workflows/cd.yml):推送 `v*` tag 或手动触发 `workflow_dispatch`。流程依次为:停旧实例 → `rsync --delete` 同步代码到固定目录 → `setup.sh``run.sh` → 进程存活校验 → HTTP 健康检查 → 输出启动日志。
完整的 runner 准备步骤(系统包安装、部署目录创建、免密 sudo 配置等)见 [.gitea/README.md](.gitea/README.md)。
## 🛠️ 开发说明
- `main.py``app.run(..., use_reloader=False)` 是关键:开启 Flask 自动重载会让主进程被 fork导致 eBPF 探针被加载两次而冲突。
- BPF 程序在内核里对**所有**系统调用号计数,过滤逻辑放在 Python 端 `_refresh_snapshot()` 里,因此修改配置无需重建 BPF 程序。
- `SyscallTracer` 通过模块级 `_tracer` 单例保证 BPF 程序在进程内只挂载一次。
## 🔒 安全与隐私
运行该程序需要 root / CAP_BPF 权限,会读取整机所有进程的系统调用频率信息,请勿在不受信任的环境或未脱敏的多租户主机上长期开启。监听地址默认 `0.0.0.0:5000`,对外暴露前请自行加上反向代理与访问控制。
## 📄 许可证
本项目以 MIT License 发布,详见 [LICENSE](LICENSE)。