Skip to content

cuilan/FsEventBridge

Repository files navigation

CI Release License Platform C Kernel Tests

╔══════════════════════════════════════════════════════╗
║░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓║
║                                                      ║
║         ██████████   ██████████   █████████          ║
║         ██           ██           ██      ██         ║
║         ███████      ███████      ███████            ║
║         ██           ██           ██      ██         ║
║         ██           ██████████   █████████          ║
║                                                      ║
║░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓░▓║
║       FsEventBridge · fanotify · NDJSON / UDS        ║
╚══════════════════════════════════════════════════════╝

High-Performance File System Event Bridge(Linux fanotify · NDJSON over Unix Domain Socket

GitHub stars Repository Releases


FsEventBridge 提供的内核文件事件转为 NDJSON 流,经 UDS 分发给 Go、Python、Java 等下游。(命令行请使用 fseventbridgefeb。)

英文文档: Documentation in English · 文档索引


演示

下列录屏展示在监控目录中创建/写入文件后,NDJSONUnix Domain Socket 逐行输出(运行需 rootCAP_SYS_ADMIN;示例客户端见 tests/test_client.py 等)。

fseventbridge / feb 终端演示


🚀 核心特性

  • 内核级大范围监控:基于 fanotify FAN_MARK_FILESYSTEM锚点路径所在的文件系统/挂载上打标;随后在网关内按 锚点子树recursive / --no-recursive(见使用指南)再做逻辑过滤,再通过 UDS 发出。实际事件是否出现仍取决于内核与挂载类型(参见 NFS 说明)。
  • NFS 客户端挂载无需改动 NFS 服务端;在本机 NFS 客户端挂载点上,事件是否出现、是否齐全,由 **Linux 内核 + NFS 客户端实现(及 NFS 版本)**共同决定。本仓库当前没有单独的「NFS 专用协议」代码路径——与同机 ext4/XFS 等相比,不能保证事件语义与覆盖率完全一致,需要在目标内核上实测(详见 DEVELOPMENT_PLAN.md 中的兼容性验证)。
  • C17 + 严控告警:源码按 ISO C17CMake 设定 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 权限或与容器 / 内核策略有关,不等同于应用程序逻辑故障。

监控范围与 recursive

网关在内核侧使用 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_scopesubtreedirect_children,与 recursive 对应)及 logical_scope_explained=…(英文单行,概括「内核 FAN_MARK_FILESYSTEM + 用户态按锚点收窄 + 再施加 exclude_*」)。便于干跑验收与自动化解析。

容器、WSL2user.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.tomlsystemctl 单元名:fseventbridge.service(项目名仍常写作 FsEventBridge)。

sudo fseventbridge -c /etc/fseventbridge/config.toml
# 或通过便捷名:sudo feb -c ...

消费事件(NDJSON)

先启动 FsEventBridge(运行命令 fseventbridgefeb),再在业务侧连接同一 UDS,按行读取 JSON(一行一个对象)。示例客户端:tests/test_client.pytests/test_client.go

每条事件对象的字段:

字段 含义
path 文件路径
event 可读事件名,如 CLOSE_WRITEMODIFY
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

🔗 上游集成示例 (Go)

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.mdEnglish: docs/README.en.md


⚖️ 开源协议

本项目采用 Apache-2.0 协议开源。

About

High-performance Linux file event gateway: fanotify notifications → NDJSON over Unix Domain Socket, for polyglot consumers.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors