- 可观测性
- 性能剖析
- eBPF
【免费下载链接】bpftrace
High-level tracing language for Linux
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),工具可以托管在任何你喜欢的地方,没有强制约束。
对于希望与社区共享的工具,有两个去向:
- 社区工具仓库(user-tools repository):这是一个社区中心,任何人不经主仓库审核即可提交自己写的工具,适合那些功能明确、面向特定场景的脚本。
- 主仓库的 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 bpftrace3.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 对libbpf和bcc的新版本有严格依赖,且会紧跟其上游进展,因此:
- 在包较新的发行版上,发行版构建通常工作良好;
- 在包滞后的发行版(如 Debian)上,建议改用 Nix 构建,或手动编译安装新版
bcc与libbpf。
仓库提供了多份 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 会被阻止运行。解决方式:
- 在 UEFI 中关闭 Secure Boot;或
- 执行
sudo mokutil --disable-validation后重启;或 - 用
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 清单:
- 更新 CHANGELOG.md:把本次用户可见的变更写入 changelog(格式遵循 Keep a Changelog,章节按
Added/Changed/Fixed等组织); - 更新 adoc 文档:即 man/adoc/bpftrace.adoc 中的语言/命令参考;
- 保证单元测试与运行时测试齐备:具体测试类型与写法见下一节。
六、测试:每个贡献的四道关卡
CONTRIBUTING.md 强调"Every contribution should (1) not break the existing tests and (2) introduce new tests if relevant"。bpftrace 共有四类测试(详见 tests/README.md):
| 类型 | 位置 | 运行方式 | 说明 |
|---|---|---|---|
| 单元测试(Unit) | tests/*.cpp | sudo <builddir>/tests/bpftrace_test | 基于 GoogleTest,覆盖语义分析器、codegen 等组件;可用--gtest_filter或GTEST_FILTER筛选 |
| 自测试(Self) | tests/self/ | sudo <builddir>/tests/self-tests.sh | 用test:探针测试核心功能与标准库;单文件调试可用<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:用例名(必填)。RUN或PROG:二选一必填。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::optional、int、bool);不可恢复错误抛出FatalUserException,异常不得用于可恢复错误。例如 map 写入失败(map 满、权限不足等)是可恢复错误,应传播;而debugfs未挂载则属于不可恢复错误,应直接抛异常告知用户系统未就绪。 - struct vs. class:struct 仅用于携带数据的被动对象,所有字段公开、不持有不变量、无方法;其余一律用 class。
- 命名:变量使用
snake_case;私有成员带尾随下划线,公开成员与 struct 数据成员不带。 - 日志级别:
DEBUG(始终输出)、V1(仅-v时输出,用于 BTF 不可用之类的警告)、HINT(紧跟 WARNING/ERROR 的解决提示)、WARNING(可继续运行但影响行为/输出)、ERROR(用户输入非法,最终经main.cpp捕获FatalUserException后exit(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 失败环境的步骤:
- 从 GHA UI 获取 job 环境:
- 设置相关环境变量后运行 .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-g3acbvmtest 会把当前运行的 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>)。
十二、贡献流程速查清单
- 初始化子模块检出代码,用
scripts/check_kernel_features.sh验证内核特性; - 小改动直接提 PR;重大改动先发 RFC Issue,再提交链接 RFC 的 POC PR,获两位以上维护者批准后按 PR 清单推进;
- 每个贡献不破坏既有测试,并酌情新增单元测试、自测试或运行时测试(注意
TIMEOUT、NAME、RUN/PROG、EXPECT*等必填指令); - 遵循 docs/coding_guidelines.md 的语义规范,用 clang-format 与
bpftrace --fmt/scripts/bpftrace_tidy.sh保证格式; - 每个提交用
git commit --signoff签名(真实姓名+真实邮箱); - 用户可见变更同步更新 CHANGELOG.md 与 man/adoc/bpftrace.adoc;
- PR 保持 squash + rebase,不产生 merge commit。
至此,从 Issue 报告、工具编写与分享,到 RFC 提案、测试编写、代码合入与 DCO 合规,bpftrace 贡献的完整链路已经清晰。无论你贡献的是一个小工具、一次文档修正还是语言级新特性,都可以在这套流程中找到自己的位置。
- 可观测性
- 性能剖析
- eBPF
【免费下载链接】bpftrace
High-level tracing language for Linux
相关推荐
Delve 贡献指南:从 Issue 提报到代码合入的完整实践
Delve 贡献指南:从 Issue 提报到代码合入的完整实践 导读 本文基于 CONTRIBUTING.md https://link.gitcode.com
开发工具Mesop 贡献指南:从 Issue 到代码合入的完整实践路径
Mesop 贡献指南:从 Issue 到代码合入的完整实践路径 Mesop 是一个面向 AI 应用开发的 Python Web 框架("Rapidly buil
前端后端Web框架Magpie 开源贡献指南:从报告 Bug、提交功能到编写代码的完整实践
Magpie 开源贡献指南:从报告 Bug、提交功能到编写代码的完整实践 Magpie 是一款面向 Windows 10/11 的通用窗口超分辨率(upscal
桌面应用图形学图像处理
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考