中文+README
All checks were successful
CI / lint-and-build (push) Successful in 8s

This commit is contained in:
2026-06-14 12:08:27 +08:00
parent f9b32208e4
commit 26a5f99587
16 changed files with 376 additions and 80 deletions

164
README.md
View File

@@ -1,4 +1,164 @@
# syscall_monitor
<h1 align="center">syscall_monitor</h1>
<p align="center">
<strong>基于 eBPF 的 Linux 系统调用计数监控器,附带 Flask 可视化界面</strong>
</p>
1. 获取系统调用列表
<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)。