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 输出完全一致。
内核版本兼容性决策树 当前内核版本 内核 ≥ 3.10 (推荐) 2.6.18 ≤ 内核 < 3.10 内核 < 2.6.18 (不推荐) 安装 debuginfo + SystemTap 部分功能受限,建议升级内核 无法运行 SystemTap 说明 • 绿色分支:主流支持,功能完整。 • 橙色分支:基础探测可用,但 tracepoint 和 uprobe 可能受限。 • 红色分支:内核太旧,kprobe 机制缺失,无法安装 SystemTap。 • 建议:生产环境使用 RHEL 8/9 或 Fedora 最新稳定版。

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 能否正常编译和运行。如果成功,说明环境就绪。
SystemTap 环境搭建流程 ① 检查内核版本 (uname -r) ② 安装 SystemTap 主包 ③ 安装 kernel-debuginfo ④ 验证探测点 (stap -L) ⑤ 运行测试脚本 (stap hello.stp) 关键点:每一步都必须成功,否则后续调试无法进行。debuginfo 版本必须与内核完全一致,否则 stap -L 会返回空。 如果步骤③失败,检查仓库配置或手动下载对应 RPM/DEB 包。

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 -