bpftrace 贡献指南:从编写工具、RFC 提案到代码合入的完整实践
2026/9/24 17:22:18 网站建设 项目流程
  • 可观测性
  • 性能剖析
  • eBPF

【免费下载链接】bpftrace

High-level tracing language for Linux

项目地址:https://gitcode.com/gh_mirrors/bp/bpftrace
点击查看免费下载

bpftrace 是一个面向 Linux 的高层跟踪语言,致力于让开发者用极简的单行命令快速编写基于 eBPF 的可观测性程序。本文以仓库根目录的 CONTRIBUTING.md 为主线,结合 docs/developers.md、tests/README.md、docs/coding_guidelines.md 与 docs/release_process.md 等配套文档,系统讲解 bpftrace 社区的贡献方式:如何提交问题、如何编写并分享 bpftrace 工具、如何搭建开发环境与构建、如何通过 RFC 流程推进重大变更、如何保证提交质量并通过 DCO 签名完成合规贡献。读完本文,你将掌握从"提一个 Issue"到"代码成功合入 master"的完整路径,以及每个环节背后的仓库级实现依据。

一、参与贡献的入口:Issue、IRC 与 Good First Issues

bpftrace 对贡献持开放态度(Contributions are welcome),任何形式的参与都被欢迎,包括:

  • Bug 报告与功能请求:通过 GitHub Issue Tracker 提交。
  • 开发讨论:参与 #bpftrace 的 IRC 频道(irc.oftc.net),用于社区与开发者之间的实时交流。
  • 新手任务:带有good first issue标签的 Issue 专为初次贡献者设计,适合作为入门切入点。

从仓库现状看,good first issue通常涉及小范围改动,比如修正文档、修复特定内置函数的边界情况等,可以直接走普通的 GitHub pull request 工作流,无需走 RFC 流程。

二、贡献工具:写自己的 bpftrace 工具并分享

bpftrace 社区鼓励每个人编写并分享自己的 bpftrace 工具(Contributing Tools),工具可以托管在任何你喜欢的地方,没有强制约束。

对于希望与社区共享的工具,有两个去向:

  1. 社区工具仓库(user-tools repository):这是一个社区中心,任何人不经主仓库审核即可提交自己写的工具,适合那些功能明确、面向特定场景的脚本。
  2. 主仓库的 tools/ 目录:这是由维护者精选的一小撮示例集合,具有以下特征(见 tools/README.md):
    • 经过生产环境实战检验(battle-tested in production);
    • 随 bpftrace 一起打包分发;
    • 同时承担测试与验证职责——tools/下每个.bt脚本都会在**工具解析测试(tool parsing tests)**中被逐一执行,确保它们始终语法有效、可运行。

这意味着,如果你的工具希望进入主仓库,不仅要代码正确,还要能够持续通过自动化的工具解析测试。仓库中 scripts/bpftrace_tidy.sh 可用于格式化.bt脚本,使其符合 bpftrace 自身的代码风格。

三、开发环境准备:clone、内核依赖与特性检查

3.1 初始化子模块

bpftrace 使用 git submodule 管理第三方依赖(最典型的是 libbpf/ 子模块,参见 docs/dependency_support.md),因此在检出代码时必须初始化子模块:

git clone --recurse-submodules https://github.com/bpftrace/bpftrace cd bpftrace

3.2 Linux 内核要求

bpftrace 最大的运行时依赖是 Linux 内核。根据 docs/dependency_support.md,当前仓库要求的最低内核版本为 6.1,并建议支持稳定内核与最近 4 个 LTS 内核。需要更老内核支持的用户可以回退使用旧版本 bpftrace。

内核必须以正确选项构建,关键配置项包括:

CONFIG_BPF=y CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT=y CONFIG_HAVE_EBPF_JIT=y CONFIG_BPF_EVENTS=y CONFIG_FTRACE_SYSCALLS=y CONFIG_FUNCTION_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_DYNAMIC_FTRACE=y CONFIG_HAVE_KPROBES=y CONFIG_KPROBES=y CONFIG_KPROBE_EVENTS=y CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_UPROBES=y CONFIG_UPROBE_EVENTS=y CONFIG_DEBUG_FS=y

上述配置可以通过仓库提供的 scripts/check_kernel_features.sh 一键核验。该脚本会依次尝试读取命令行参数指定的配置文件、/boot/config-$(uname -r)/boot/config/proc/config.gz,并逐个zgrep检查上面的每个选项是否为y(源码见 scripts/check_kernel_features.sh):

./scripts/check_kernel_features.sh # 输出示例: # All required features present!

如果缺少选项,脚本会逐条打印缺失项并以非零码退出。内核选项齐备后,最好再确认系统没有启用 kernel lockdown(常见于启用 Secure Boot 的环境),否则 bpftrace 会被内核拒绝运行,具体排查方法见下文"构建与疑难排障"。

四、构建 bpftrace:Nix 优先,发行版兜底

4.1 Nix 构建(推荐)

Nix 是 bpftrace 官方推荐的构建方式,也是 CI 所使用的构建环境。Nix 会全量托管所有构建与运行时依赖,理论上保证近乎 100% 的可复现性,且开发者无需手动安装任何构建/运行包

所有 Nix 构建与测试命令都需要在 Nix dev shell 内执行:

nix develop # 进入 dev shell mkdir build cmake -B build -DCMAKE_BUILD_TYPE=Debug make -C build -j$(nproc)
  • 使用不同 LLVM 版本开发:nix develop .#bpftrace-llvm21(仓库 flake.nix 中默认 LLVM 为最新受支持版本,并为 x86_64-linux 与 aarch64-linux 提供多版本产物)。
  • 更多 Nix 示例(静态构建、fuzzing、flake 管理)见 docs/nix.md。

4.2 发行版构建

发行版构建依赖你在宿主系统上自行安装 bpftrace 的全部构建与运行依赖,然后调用 cmake。需要注意 bpftrace 对libbpfbcc的新版本有严格依赖,且会紧跟其上游进展,因此:

  • 在包较新的发行版上,发行版构建通常工作良好;
  • 在包滞后的发行版(如 Debian)上,建议改用 Nix 构建,或手动编译安装新版bcclibbpf

仓库提供了多份 Dockerfile 作为依赖清单参考:docker/Dockerfile.ubuntu、docker/Dockerfile.fedora、docker/Dockerfile.debian(另有 alpine、opensuse、static 变体)。

依赖装好后:

mkdir build cmake -B build -DCMAKE_BUILD_TYPE=Release make -C build -j$(nproc)

关键 cmake 选项:

  • -DBUILD_TESTING=ON(默认开启,会生成bpftrace_test等测试目标);
  • -DLLVM_REQUESTED_VERSION=<major>(指定 LLVM 主版本)。

4.3 构建产物与疑难排障

  • 构建产物位于build/src/bpftrace
  • Kernel Lockdown:若系统启用了内核 lockdown(常伴随 Secure Boot),bpftrace 会被阻止运行。解决方式:
    1. 在 UEFI 中关闭 Secure Boot;或
    2. 执行sudo mokutil --disable-validation后重启;或
    3. SysRQ+x临时解除 lockdown(仅持续到下次启动)。

五、RFC 流程:重大变更的标准路径

这是 CONTRIBUTING.md 的核心章节之一,适用于重大(substantial)或破坏性(breaking)变更。Bug 修复、文档更新、小功能以及带good first issue标签的问题,直接走普通 PR 工作流即可,无需 RFC。

完整的 RFC 流程分三步:

5.1 第一步:创建 RFC Issue

新建一个 Issue,标题以 "RFC" 为前缀并打上 RFC 标签。Issue 中必须包含:

  • 变更的目标(goal(s));
  • 潜在的缺点(potential downsides,如适用);
  • 你考虑过的其他方案(other solutions you've considered)。

该 Issue 是整体设计与方案讨论的场所。实现细节不应在此讨论,因为实现细节往往容易引发对整体提案的旁枝末节式争论(bike-shedding)。

5.2 第二步:提交 POC 与 PR

当获得一位或多位维护者的正面信号、或没有负面信号时,可以创建 POC(概念验证),就绪后提交 pull request,并在 PR 中链接原始 RFC Issue。这是让其他人实验你的 POC、讨论实现细节的好时机。

需要特别留意两点:

  • POC 可能暴露原 RFC 方案的缺陷:这是完全正常的。回到原始 RFC,解释为什么已批准方案不适用或需要调整。若改动足够大,维护者可能要求对 RFC 上的新方案做额外批准;RFC 最终被拒绝也是正常的开发过程。
  • 配置开关(config flag):视改动规模而定,维护者可能要求将该特性放在 config flag 之后,即用户必须在脚本中显式 opt-in,例如:
config = { unstable_my_feature=true }

这样可以在不永久加入语言的前提下提高开发速度、等待更多用户反馈。需要注意的是,这类特性仍可能因为用户反馈或设计方向变化而被移除、最终未进入语言,但维护者会与原作者充分沟通。

5.3 第三步:POC 获批后的 PR 清单

当 POC 获得两位或以上维护者批准后,请遵循当前的 PR 清单:

  1. 更新 CHANGELOG.md:把本次用户可见的变更写入 changelog(格式遵循 Keep a Changelog,章节按Added/Changed/Fixed等组织);
  2. 更新 adoc 文档:即 man/adoc/bpftrace.adoc 中的语言/命令参考;
  3. 保证单元测试与运行时测试齐备:具体测试类型与写法见下一节。

六、测试:每个贡献的四道关卡

CONTRIBUTING.md 强调"Every contribution should (1) not break the existing tests and (2) introduce new tests if relevant"。bpftrace 共有四类测试(详见 tests/README.md):

类型位置运行方式说明
单元测试(Unit)tests/*.cppsudo <builddir>/tests/bpftrace_test基于 GoogleTest,覆盖语义分析器、codegen 等组件;可用--gtest_filterGTEST_FILTER筛选
自测试(Self)tests/self/sudo <builddir>/tests/self-tests.shtest:探针测试核心功能与标准库;单文件调试可用<builddir>/src/bpftrace --test <file>,用--probe-filter REGEX按名称筛选
运行时测试(Runtime)tests/runtime/非 Nix:sudo <builddir>/tests/runtime-tests.sh;Nix:sudo --preserve-env=PATH --preserve-env=PYTHONPATH ./build/tests/runtime-tests.sh调用真实 bpftrace 可执行文件,按"套件"(通常是单个文件)分组
工具解析测试(Tool parsing)tools/sudo <builddir>/tests/tools-parsing-test.sh逐一执行tools/下所有工具,确保其合法可运行

6.1 运行时测试指令速查

运行时测试用一组指令(directive)描述测试用例,以下是最常用的几个:

  • NAME:用例名(必填)。
  • RUNPROG:二选一必填。PROG直接给 bpftrace 程序(多行程序按首行列对齐);RUN在 shell 中执行命令。
  • EXPECT/EXPECT_NONE/EXPECT_REGEX/EXPECT_REGEX_NONE:期望输出,分别对应整行字面匹配、否定、正则匹配、正则否定;还有文件匹配EXPECT_FILE与 JSON 匹配EXPECT_JSON
  • TIMEOUT:用例超时(秒),必填。
  • BEFORE/AFTER/SETUP/CLEANUP:分别在 bpftrace 运行前/后、测试前后执行 shell 命令,用于拉起被测程序或清理资源。BEFORE会阻塞等待到与命令最后一个空格分隔 token 同名的进程出现 PID。
  • REQUIRES/REQUIRES_FEATURE:条件执行,前者执行 shell 命令成功才运行用例,后者检查 bpftrace 特性(见bpftrace --info与 tests/runtime/engine/runner.py)。
  • MIN_KERNEL/MAX_KERNEL/ARCH:内核版本与架构过滤,ARCH支持|逻辑或、be/le端序匹配与!否定前缀。
  • ENV:为 bpftrace 调用注入NAME=VALUE环境变量。
  • NEW_PIDNS:在挂载 proc 的新 pid 命名空间中执行BEFORE、bpftrace 与AFTER
  • RETURN_CODE/WILL_FAIL:断言退出码/预期非零退出。

RUN指令还支持运行时变量占位:{{BPFTRACE}}(bpftrace 路径)、{{BEFORE_PID}}(首个BEFORE进程的 PID)、{{CWD}}

测试程序放在 tests/testprogs/,测试库放在 tests/testlibs/,例如tests/testprogs/my_test.c会被构建为可在运行时测试中探测的./testprogs/my_test,特别适合 uprobe/USDT 类测试。

七、编码规范与代码风格

7.1 语义层面的 Coding Guidelines

docs/coding_guidelines.md 关注的是代码语义与语言特性取舍(格式交给 clang-format),核心约定包括:

  • 错误处理:可恢复错误通过返回值传递(std::optionalintbool);不可恢复错误抛出FatalUserException,异常不得用于可恢复错误。例如 map 写入失败(map 满、权限不足等)是可恢复错误,应传播;而debugfs未挂载则属于不可恢复错误,应直接抛异常告知用户系统未就绪。
  • struct vs. class:struct 仅用于携带数据的被动对象,所有字段公开、不持有不变量、无方法;其余一律用 class。
  • 命名:变量使用snake_case;私有成员带尾随下划线,公开成员与 struct 数据成员不带。
  • 日志级别DEBUG(始终输出)、V1(仅-v时输出,用于 BTF 不可用之类的警告)、HINT(紧跟 WARNING/ERROR 的解决提示)、WARNING(可继续运行但影响行为/输出)、ERROR(用户输入非法,最终经main.cpp捕获FatalUserExceptionexit(1))、BUG(内部非预期问题,直接 abort)。

7.2 代码风格与格式化

  • C++ 代码用仓库自带的 clang-format 配置格式化,可用git clang-format upstream/master便捷格式化提交。
  • bpftrace 语言代码(标准库与.bt脚本)由 bpftrace 自身格式化:bpftrace --fmt或 scripts/bpftrace_tidy.sh。
  • 避免单独的 "fix formatting" 提交:每个提交都应自带正确格式,否则 CI 会失败。
  • 注释风格:优先使用 C++ 风格注释(//);C 风格注释(/* */)仅用于单行内的嵌套注释(如对某个参数做注解)。bpftrace 语言本身两种注释块都支持,目前无强制偏好。

八、提交、合入与 Changelog

8.1 合并策略:squash + rebase

CONTRIBUTING.md 与 docs/developers.md 都明确了合并约定:所有 PR 需 squash + rebase(不含 merge commit),即 master 上每个 PR 只对应一个提交,这让 changelog 生成简单且精确、噪音最少。

例外:对于改动复杂的 PR,若提交结构良好,也可以 rebase + merge(仍不含 merge commit)。判断标准是:提交标题在 changelog 中读起来要说得通

8.2 Changelog 维护

  • changelog 面向最终用户,提供对用户重要的变更摘要;重构、测试改动等内部变更不写入
  • 为避免发版时突击补写,changelog随 PR 一起维护:每个有用户影响的 PR 都必须包含 changelog 条目。
  • 因为 changelog 格式中包含 PR 号,所以条目只能在 PR 打开后补充。单提交 PR 直接并入该提交;多提交 PR 可以单独增加一个 changelog 提交。

8.3 Developer's Certificate of Origin(DCO)

为追踪"谁做了什么",bpftrace 引入了sign-off(签名)流程。签名是每个提交末尾的一行,证明你编写了该提交、或有权利将其作为开源贡献传递。规则遵循 Developer's Certificate of Origin。

git commit--signoff选项为所有提交签名:

git commit --signoff --message "This is the commit message"

该选项会在提交日志消息末尾追加Signed-off-by尾注。请使用真实姓名与真实邮箱地址(不接受匿名贡献、github 登录名等)。

九、持续集成与 CI 排障

CI 在 NixOS 上以多种 LLVM 版本组成的矩阵执行上述全部测试,任务定义在 .github/workflows/ci.yml。CI 会在主仓库的所有分支与 PR 上自动运行,官方也建议在你自己的 fork 上启用 GitHub Actions,以便对测试分支提前跑 CI。

复现 CI 失败环境的步骤

  1. 从 GHA UI 获取 job 环境:

  1. 设置相关环境变量后运行 .github/include/ci.py。示例:
$ NIX_TARGET=.#bpftrace-llvm10 ./.github/include/ci.py
$ NIX_TARGET=.#bpftrace-llvm11 \ CMAKE_BUILD_TYPE=Release \ RUNTIME_TEST_DISABLE="probe.kprobe_offset_fail_size,usdt.usdt probes - file based semaphore activation multi process" \ ./.github/include/ci.py

虚拟机测试(vmtests):CI 会借助嵌套虚拟化在受控内核下运行一部分运行时测试(使用 vmtest 管理虚拟机)。上述排障流程同样适用于 vmtest 化的运行时测试。若想在内核中快速手动验证,可:

$ nix develop (nix:nix-shell-env) $ vmtest -k $(nix build --print-out-paths .#kernel-6_12)/bzImage -- ./build/src/bpftrace -V => bzImage ===> Booting ===> Setting up VM ===> Running command bpftrace v0.21.0-344-g3acb

vmtest 会把当前运行的 userspace 映射进虚拟机,因此你可以直接在 guest 中运行宿主上构建的二进制(例如你的 bpftrace 开发构建)。

十、性能测量与更深层参考

在贡献过程中,若涉及性能敏感路径,可以用以下两个模式量化影响(见 docs/developers.md):

  • 编译期性能:bpftrace --mode compiler-bench,查看编译各 pass 的耗时;
  • 生成代码性能:bpftrace --mode bench配合BENCH探针,例如:
$ bpftrace --mode bench -e 'BENCH:my_benchmark { @a++; }' Attached 1 probe +--------------+--------------+ | BENCHMARK | AVERAGE TIME | +--------------+--------------+ | my_benchmark | 270ns | +--------------+--------------+

更多底层机制参见 docs/internals_development.md。

十一、与贡献相关的项目宏观约定

虽然 CONTRIBUTING.md 未展开论述,但理解下面两份配套文档有助于让你的贡献方向与项目愿景一致:

  • 设计原则:bpftrace 的使命是让不熟悉 eBPF 复杂性的用户也能快速编写基于 BPF 的可观测性程序。语言目标按优先级排序为:简洁(one-liners)、可读、对 eBPF 的干净抽象、快速迭代、可组合、内核与用户态性能良好、启动速度。非目标包括可测试性、可调试性、动态类型、类/继承、元编程、异常处理、以及 BPF 安全/LSM/XDP/调度等领域。重大或破坏性变更会被要求走 RFC 流程,这正是 CONTRIBUTING.md 中 RFC Process 一节的依据。
  • 发布流程:bpftrace 遵循语义化版本,每年发布两次,与 LLVM 发布节奏对齐(minor 版本在 LLVM 主版本发布两周后)。了解发布节奏有助于判断你的贡献会落在哪个版本窗口、以及何时该往 release 分支 backport(git cherry-pick -s -x <sha1>)。

十二、贡献流程速查清单

  1. 初始化子模块检出代码,用scripts/check_kernel_features.sh验证内核特性;
  2. 小改动直接提 PR;重大改动先发 RFC Issue,再提交链接 RFC 的 POC PR,获两位以上维护者批准后按 PR 清单推进;
  3. 每个贡献不破坏既有测试,并酌情新增单元测试、自测试或运行时测试(注意TIMEOUTNAMERUN/PROGEXPECT*等必填指令);
  4. 遵循 docs/coding_guidelines.md 的语义规范,用 clang-format 与bpftrace --fmt/scripts/bpftrace_tidy.sh保证格式;
  5. 每个提交用git commit --signoff签名(真实姓名+真实邮箱);
  6. 用户可见变更同步更新 CHANGELOG.md 与 man/adoc/bpftrace.adoc;
  7. PR 保持 squash + rebase,不产生 merge commit。

至此,从 Issue 报告、工具编写与分享,到 RFC 提案、测试编写、代码合入与 DCO 合规,bpftrace 贡献的完整链路已经清晰。无论你贡献的是一个小工具、一次文档修正还是语言级新特性,都可以在这套流程中找到自己的位置。

  • 可观测性
  • 性能剖析
  • eBPF

【免费下载链接】bpftrace

High-level tracing language for Linux

项目地址:https://gitcode.com/gh_mirrors/bp/bpftrace
点击查看免费下载
上一篇:Repomix 使用场景实战指南:用 AI 完成代码审查、Bug 调查、安全审计与架构分析
下一篇:使用 cilium-dbg envoy admin listeners 查看 Cilium 中 Envoy 的监听器(Listener)配置

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询