╔══════════════════════════════════════════════════════╗ ║░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓║ ║ ║ ║ ██████████ ██████████ █████████ ║ ║ ██ ██ ██ ██ ║ ║ ███████ ███████ ███████ ║ ║ ██ ██ ██ ██ ║ ║ ██ ██████████ █████████ ║ ║ ║ ║░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓║ ║ FsEventBridge · fanotify · NDJSON / UDS ║ ╚══════════════════════════════════════════════════════╝
High-Performance File System Event Bridge(Linux fanotify · NDJSON over Unix Domain Socket)
将 FsEventBridge 提供的内核文件事件转为 NDJSON 流,经 UDS 分发给 Go、Python、Java 等下游。(命令行请使用 fseventbridge 或 feb。)
英文文档: Documentation in English · 文档索引
下列录屏展示在监控目录中创建/写入文件后,NDJSON 经 Unix Domain Socket 逐行输出(运行需 root 或 CAP_SYS_ADMIN;示例客户端见 tests/test_client.py 等)。
- 内核级大范围监控:基于
fanotifyFAN_MARK_FILESYSTEM在锚点路径所在的文件系统/挂载上打标;随后在网关内按 锚点子树 与recursive/--no-recursive(见使用指南)再做逻辑过滤,再通过 UDS 发出。实际事件是否出现仍取决于内核与挂载类型(参见 NFS 说明)。 - NFS 客户端挂载:无需改动 NFS 服务端;在本机 NFS 客户端挂载点上,事件是否出现、是否齐全,由 **Linux 内核 + NFS 客户端实现(及 NFS 版本)**共同决定。本仓库当前没有单独的「NFS 专用协议」代码路径——与同机 ext4/XFS 等相比,不能保证事件语义与覆盖率完全一致,需要在目标内核上实测(详见
DEVELOPMENT_PLAN.md中的兼容性验证)。 - C17 + 严控告警:源码按 ISO C17(
CMake设定C_STANDARD 17,并启用-Wall -Wextra -Werror,另使用_GNU_SOURCE以获得 Linux 必需的 POSIX/GNU API)。 - 高性能取向:链路以
fanotify+ 精简 NDJSON 推送为主;已链接liburing并支持可选初始化,热路径异步化与完整性能调优见路线图(Milestone 2;是否默认深度接入 io_uring 将结合压测结论决定)。 - 跨语言集成:通过 Unix Domain Socket 发送 NDJSON(每行一条 JSON),便于多语言消费。
- 工业级部署:集成 Systemd 就绪通知,提供
.deb/.rpm打包路径,贴合常见 Linux 运维方式。 - IPC 可靠性:客户端非阻塞发送、短写排队
[ipc]可配置上限与队列满策略;poll覆盖 fanotify、监听 fd 与慢客户端 POLLOUT;周期性[IPC] stats运维日志。
- Linux Kernel >= 5.1(推荐 6.x)
- GCC >= 12(支持 C17)
- CMake、pkg-config
- liburing、libsystemd(开发时需对应
-dev包)
也可使用仓库内脚本:bash scripts/build.sh
mkdir -p build && cd build
cmake ..
cmake --build . -j"$(nproc)"
# 产物:build/fseventbridge;同目录下另有 feb → fseventbridge(开发便捷,与 make install 行为一致)
# 可选:生成 Debian / RPM 安装包(需本机装有 cpack 相应生成器)
cpack监听文件事件需要 CAP_SYS_ADMIN。任选其一:
- 临时:
sudo ./fseventbridge …,或./feb …(build/内含指向主程序的feb符号链接)。 - 开发便利(每次重新编译后需重设):
sudo setcap cap_sys_admin+ep ./build/fseventbridge,之后可直接以普通用户运行。./build/feb与./build/fseventbridge等价。 - 包安装的
fseventbridge.service通过AmbientCapabilities=CAP_SYS_ADMIN等在单元内对齐能力(参见package/fseventbridge.service)。 - 若仍报
Operation not permitted:多为不具备fanotify权限或与容器 / 内核策略有关,不等同于应用程序逻辑故障。
网关在内核侧使用 FAN_MARK_FILESYSTEM:在 --dir / [monitor].path 所在路径所属的整块文件系统上打标,因此内核会评估该挂载上各处的事件;为贴近「只关心某一目录树」的常见需求,在向 UDS 转发之前会做 逻辑路径过滤(Milestone 4):
| 层级 | 行为 |
|---|---|
| 内核标记 | FAN_MARK_FILESYSTEM:标记包含锚点的整块文件系统;锚点主要用于选中挂载实例。 |
| 逻辑范围(默认启用) | 仅保留位于锚点之下的路径事件;同一文件系统内、锚点以外的兄弟目录等路径会在转发前丢弃。 |
recursive=true(随仓库 TOML 默认;CLI -r / --recursive 设为真) |
转发锚点的完整子树(仍服从 exclude_extensions / exclude_paths)。 |
recursive=false(CLI --no-recursive) |
仅锚点路径自身,及其目录下「直接一层」条目(不出现更深的路径层级,例如 ./a/b.txt)。 |
| 建议使用绝对路径 | 与服务单元、日志和运维脚本一致;相对路径取决于进程 CWD。 |
--check-config |
除各配置项外打印 logical_scope(subtree 或 direct_children,与 recursive 对应)及 logical_scope_explained=…(英文单行,概括「内核 FAN_MARK_FILESYSTEM + 用户态按锚点收窄 + 再施加 exclude_*」)。便于干跑验收与自动化解析。 |
容器、WSL2、user.namespaces 等场景下:fanotify 可能比常规实体机更受限制;以目标环境实测为准(亦见 DEVELOPMENT_PLAN.md 中的 NFS / 兼容性说明)。
监控目录、指定 Socket,并打印调试日志:
sudo ./fseventbridge -d /data/sate -s /tmp/feb.sock -l debug -r常用选项(完整列表见 fseventbridge --help;开发目录下也可用 ./build/feb -h,二者相同):
| 选项 | 作用 |
|---|---|
-d, --dir |
监控路径 |
-s, --socket |
UDS 路径(默认 /tmp/feb.sock) |
-c, --config |
TOML 配置文件 |
-r, --recursive |
锚点下的完整子树转发(逻辑过滤;CLI 设为真时覆盖配置文件) |
--no-recursive |
仅锚点及直接进入的一层路径(较深路径不转发) |
-l, --log-level |
debug / info / warn / error |
-e, --exclude-ext |
按扩展名排除(可重复) |
-x, --exclude-path |
按路径前缀排除(可重复) |
-i, --io-uring |
启用 io_uring 相关初始化 |
--no-io-uring |
关闭上述开关 |
--check-config |
加载配置后打印最终生效项并退出(含 logical_scope / logical_scope_explained,说明见下表后「监控范围」一节;无需 root) |
-v, --version |
版本信息 |
配置文件与 CLI 可同时使用:CLI 优先级更高。
仓库内可参考 configs/config.toml。极简示例:
[server]
socket_path = "/tmp/feb.sock"
log_level = "info"
[monitor]
path = "/data/sate"
recursive = true
events = ["CLOSE_WRITE"]
exclude_extensions = [".tmp", ".swp"]
exclude_paths = ["/data/sate/cache"]
[processor]
use_io_uring = true
[ipc]
per_client_queue_max_bytes = 262144
on_queue_full = "disconnect"使用方式:
包安装默认配置:/etc/fseventbridge/config.toml,systemctl 单元名:fseventbridge.service(项目名仍常写作 FsEventBridge)。
sudo fseventbridge -c /etc/fseventbridge/config.toml
# 或通过便捷名:sudo feb -c ...先启动 FsEventBridge(运行命令 fseventbridge 或 feb),再在业务侧连接同一 UDS,按行读取 JSON(一行一个对象)。示例客户端:tests/test_client.py、tests/test_client.go。
每条事件对象的字段:
| 字段 | 含义 |
|---|---|
path |
文件路径 |
event |
可读事件名,如 CLOSE_WRITE、MODIFY |
type |
与 event 对应的整数枚举(UNKNOWN = 0,其后按 CLOSE_WRITE、MOVED_TO … 递增) |
size |
当前文件大小(字节) |
ts |
网关观测时间:处理该 fanotify 事件并完成元数据读取之后的墙钟时刻(Unix 秒,CLOCK_REALTIME) |
mtime |
文件内容最后修改时间(st_mtim 秒);fstat 失败时为 -1 |
mask |
fanotify 原始掩码(可与内核 FAN_* 对照,例如 FAN_CLOSE_WRITE 常为 8/0x8) |
conn, _ := net.Dial("unix", "/tmp/feb.sock")
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
var event MyFileEvent // 按需映射 path / event / type / ts / mtime / mask 等字段
json.Unmarshal(scanner.Bytes(), &event)
processSatelliteData(event.Path)
}本地构建后:
bash tests/run.sh --milestone 0 --type unit # 无需 root
sudo -E bash tests/run.sh --milestone 0 --type e2e
sudo -E bash tests/run.sh --milestone 1 --type e2e # NDJSON 语义回归
sudo -E bash tests/run.sh --milestone 3 --type e2e # IPC(需 root)
sudo -E bash tests/run.sh --milestone 4 --type e2e # 监控范围与 recursive(需 root)说明见 tests/README.md。路线图见 DEVELOPMENT_PLAN.md。English: docs/README.en.md
本项目采用 Apache-2.0 协议开源。
