4. SystemTap 环境搭建:内核版本要求、安装 SystemTap、安装内核调试符号
SystemTap 通过将脚本编译为内核模块并动态加载,实现对内核运行状态的实时探测。这一机制对内核版本、调试符号以及工具链有严格依赖。本章从内核版本兼容性、SystemTap 安装、内核调试符号(kernel-debuginfo)获取三个维度,搭建可用的调试环境。
环境前提: 本课程所有案例基于 RHEL/CentOS 7/8/9 或 Fedora 系列发行版。Ubuntu/Debian 用户需使用
linux-image-*-dbgsym 包,原理相同但包名不同。
4.1 内核版本要求与兼容性矩阵
SystemTap 对内核版本有明确要求:
- 主线支持: 内核版本 ≥ 2.6.18(RHEL 5 起)即可运行基础探测。
- 推荐版本: 内核 ≥ 3.10(RHEL 7)以获得完整的 kprobe、uprobe、tracepoint 支持。
- 调试符号依赖: 必须安装与当前运行内核 完全一致 的 kernel-debuginfo 包。
- 安全限制: 内核需开启
CONFIG_DEBUG_INFO、CONFIG_KPROBES、CONFIG_RELAY、CONFIG_DEBUG_FS。
| 发行版 | 内核版本范围 | SystemTap 版本 | 调试符号包名 | 兼容性 |
|---|---|---|---|---|
| RHEL/CentOS 7 | 3.10.0 – 3.10.0-1160 | ≥ 3.0 | kernel-debuginfo-$(uname -r) | ✅ 完全支持 |
| RHEL/CentOS 8 | 4.18.0 – 4.18.0-553 | ≥ 4.0 | kernel-debuginfo-$(uname -r) | ✅ 完全支持 |
| RHEL/CentOS 9 | 5.14.0 – 5.14.0-503 | ≥ 4.6 | kernel-debuginfo-$(uname -r) | ✅ 完全支持 |
| Fedora 36+ | 5.17+ | ≥ 4.7 | kernel-debuginfo-$(uname -r) | ✅ 完全支持 |
| Ubuntu 20.04/22.04 | 5.4 / 5.15 | ≥ 4.2 | linux-image-*-dbgsym | ⚠️ 需额外配置 ddebs 源 |
版本验证命令: 使用
uname -r 获取当前内核版本,使用 stap --version 查看 SystemTap 版本。务必确保 debuginfo 包的 release 字段与 uname -r 输出完全一致。
4.2 安装 SystemTap
SystemTap 由用户态工具 stap、编译后端 staprun 以及运行时库组成。安装方式根据发行版不同略有差异。
4.2.1 RHEL/CentOS/Fedora 安装
# 启用 EPEL 和 BaseOS 仓库(RHEL 8/9 需要)
sudo subscription-manager repos --enable=rhel-8-for-x86_64-baseos-rpms
sudo subscription-manager repos --enable=rhel-8-for-x86_64-appstream-rpms
# 安装 SystemTap 主包
sudo yum install -y systemtap systemtap-runtime
# 验证安装
stap --version
4.2.2 Ubuntu/Debian 安装
# 添加 ddebs 源(用于获取 dbgsym 包)
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C8CAB6595FDFF622
echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list.d/ddebs.list
sudo apt update
sudo apt install -y systemtap systemtap-runtime
# 验证安装
stap --version
注意: Ubuntu 的 SystemTap 版本通常落后于 RHEL/Fedora。如果遇到编译错误,建议升级到 Ubuntu 22.04+ 或使用
systemtap-git 源码编译。
4.3 安装内核调试符号(kernel-debuginfo)
内核调试符号是 SystemTap 能够将脚本中的函数名、变量名解析为内存地址的关键。没有 debuginfo,SystemTap 只能使用原始地址探测,可读性极差。
4.3.1 获取 debuginfo 包
debuginfo 包必须与当前运行内核的 完整版本号 精确匹配。使用以下命令查看当前内核版本:
# 查看完整内核版本
uname -r
# 示例输出:4.18.0-553.el8_10.x86_64
根据发行版安装对应的 debuginfo 包:
| 发行版 | 安装命令 | 包名示例 |
|---|---|---|
| RHEL/CentOS 7 | yum install kernel-debuginfo-$(uname -r) |
kernel-debuginfo-3.10.0-1160.el7.x86_64 |
| RHEL/CentOS 8 | yum install kernel-debuginfo-$(uname -r) |
kernel-debuginfo-4.18.0-553.el8_10.x86_64 |
| RHEL/CentOS 9 | dnf install kernel-debuginfo-$(uname -r) |
kernel-debuginfo-5.14.0-503.el9.x86_64 |
| Fedora | dnf install kernel-debuginfo-$(uname -r) |
kernel-debuginfo-6.8.5-200.fc39.x86_64 |
| Ubuntu | apt install linux-image-$(uname -r)-dbgsym |
linux-image-5.15.0-91-generic-dbgsym |
4.3.2 验证 debuginfo 安装
安装完成后,使用 stap -L 测试是否能解析内核符号:
# 测试探测点:内核函数 kmem_cache_alloc
stap -L 'kernel.function("kmem_cache_alloc")'
# 正常输出示例:
# kernel.function("kmem_cache_alloc@mm/slub.c:2950") $cachep:struct kmem_cache* $flags:gfp_t
# 如果输出为空或报错,说明 debuginfo 未正确安装
快速诊断: 使用
stap --vp 01 -e 'probe begin { printf("hello\n"); exit() }' 测试 SystemTap 能否正常编译和运行。如果成功,说明环境就绪。
4.4 常见问题与排错
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
stap -L 返回空 |
debuginfo 未安装或版本不匹配 | 重新安装 kernel-debuginfo-$(uname -r) |
stap 编译报错:Cannot find module |
缺少内核头文件或 build 依赖 | 安装 kernel-devel、kernel-headers |
stap 运行报错:ERROR: Couldn't insert module |
内核锁或安全模块(SELinux/AppArmor)阻止 | 临时设置 setenforce 0 或添加 SELinux 规则 |
stap --version 版本过低 |
发行版仓库中 SystemTap 较旧 | 从 源码编译 或使用第三方仓库 |
Ubuntu 下 apt install 找不到 dbgsym |
ddebs 源未正确配置 | 参考 4.2.2 节重新添加源并 apt update |
生产环境建议:
- 在测试机或容器中先验证 SystemTap 环境,再部署到生产。
- 使用
stap --vp 03开启详细日志,定位编译或加载阶段的错误。 - 保留一份与生产内核完全相同的 debuginfo 包离线存档,避免仓库更新后版本漂移。
4.5 环境验证清单
完成上述步骤后,执行以下命令确认环境就绪:
# 1. 确认内核版本
uname -r
# 2. 确认 SystemTap 版本
stap --version
# 3. 确认 debuginfo 已安装
rpm -qa | grep kernel-debuginfo # RHEL/CentOS/Fedora
dpkg -l | grep dbgsym # Ubuntu
# 4. 测试探测点
stap -L 'kernel.function("kmem_cache_alloc")'
# 5. 运行 hello world 脚本
echo 'probe begin { printf("SystemTap ready!\n"); exit() }' | stap -