在Linux中安装systemtap
SystemTap是GPLv2许可证系统范围的工具,可让我们从正在运行的Linux系统中收集跟踪和性能分析数据。
用户编写了一个stap脚本,然后我们可以将其编译为Linux内核模块,以将其链接到将在其下运行的相同内核源。
该脚本设置事件和处理程序,由内核模块在指定的事件触发时调用这些事件和处理程序。
为此,它使用内核中的kprobes和uprobes接口(如果可用)。
systemtap
Systemtap连接到Linux内核并监视可用事件,这些事件通过kprobes内核工具公开
基于事件,内核可以运行作为子例程执行的处理程序
事件和处理程序一起称为"探针"
Stap通过运行脚本来完成其工作。
要运行这些脚本,我们需要在内核中编译stap脚本并将其作为内核模块启动。
内核模块接下来将执行其工作,然后将其卸载stap
命令将运行脚本并进行编译
监控内核事件
ftrace可用的事件可以通过systemtap访问
内核功能
probe.kernel.function(" function-name")
内核系统调用
probe.syscall."syscall-name"
内核跟踪点
probe.kernel.trace(" tracepoint")
安装systemtap
Systemtap安装了通常不希望在生产系统上使用的软件包,它给系统带来了严重的变更,因此,应仅在测试环境中使用。
重要的提示:
确保节点上安装的所有与内核相关的rpm(最重要的是加载的内核)具有相同版本。
以下软件包是强制性的必备软件
内核开发
内核调试信息
内核公共调试信息
系统点击
systemtap-debuginfo
说明:
对于CentOS,我们可以从http://debuginfo.centos.org/7/x86_64/获得调试rpm。
同样,对于RHEL,我们可以使用订阅管理器添加debug-rpms存储库
为此,我们可以创建自己的存储库来下载所有必需的依赖项。
在开始安装之前,请检查"活动内核版本"。
# uname -r 3.10.0-862.14.4.el7.x86_64
# rpm -qa | grep kernel kernel-headers-3.10.0-862.14.4.el7.x86_64 kernel-tools-libs-3.10.0-862.14.4.el7.x86_64 kernel-3.10.0-862.14.4.el7.x86_64
所以现在我们知道我们需要kernel-devel
,kernel-debuginfo
和kernel-common-debuginfo
以及3.10.0-862.14.4.el7.x86_64
版本。
# yum -y install kernel-debuginfo*3.10.0-862.14.4* kernel-devel-*3.10.0-862.14.4* kernel-common-debuginfo*3.10.0-862.14.4*
接下来是时候安装systemtap和必备的rpm
# yum -y install systemtap systemtap-debuginfo
最后,在安装了所有systemtap和必备rpm之后,"重新引导节点以使更改生效。
"
因此,现在节点已全部设置为执行stap。
初步测试
如果当前正在使用打算通过SystemTap进行探测的内核,则可以立即测试部署是否成功。
如果没有,请重新启动系统并加载适当的内核。
要开始测试,请运行以下命令:
# stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}'
此命令指示SystemTap打印已执行的读取,然后在检测到虚拟文件系统读取后正确退出。
如果SystemTap部署成功,它将输出类似于以下内容的输出:
# stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}' Pass 1: parsed user script and 479 library scripts using 248000virt/49976res/345 6shr/46528data kb, in 770usr/30sys/976real ms. Pass 2: analyzed script: 1 probe, 1 function, 7 embeds, 0 globals using 408460virt/172252res/1540shr/206988data kb, in 3590usr/1040sys/16653real ms. Pass 3: translated to C into "/tmp/stapzKM0yC/stap_b91faccbe0f7c63a74a89a2ddb3f15c2_2696_src.c" using 408460virt/173248res/2484shr/206988data kb, in 20usr/0sys/48real ms. Pass 4: compiled C into "stap_b91faccbe0f7c63a74a89a2ddb3f15c2_2696.ko" in 1570usr/330sys/3301real ms. Pass 5: starting run. read performed Pass 5: run completed in 10usr/20sys/322real ms.
运行SystemTap脚本
默认脚本随SystemTap软件包一起安装在/usr/share/systemtap/examples /中
使用stap命令准备脚本
检查脚本语法
展开脚本,使其包含探针和函数调用
将脚本语言翻译为C
编译为内核模块
编译后,使用staprun运行脚本
添加-v可获得更多详细信息
编译SystemTap脚本
可以导出使用stap编译的内核模块,以便它们可以在其他系统上运行
通常,在编写systemtap脚本时,会处理" 5次运行"
使用
stap -p 4 -v~/tmp/mymodule.stp
仅运行编译在运行stap命令的第4遍后(即编译发生时),
-p 4
选项将停止
下面是一个简单的stap脚本,它将打印我们好世界
# cat hello-world.stp #!/use/bin/env stap probe begin { printf ("hello world\n") exit () }
让我们以冗长的方式执行此脚本
# stap -v hello-world.stp Pass 1: parsed user script and 479 library scripts using 247996virt/49972res/3448shr/46524data kb, in 810usr/30sys/996real ms. Pass 2: analyzed script: 1 probe, 1 function, 0 embeds, 0 globals using 249316virt/51552res/3748shr/47844data kb, in 20usr/0sys/16real ms. Pass 3: using cached /root/.systemtap/cache/b0/stap_b013d9850b952b9fa68246bba7df5605_1013.c Pass 4: using cached /root/.systemtap/cache/b0/stap_b013d9850b952b9fa68246bba7df5605_1013.ko Pass 5: starting run. hello world Pass 5: run completed in 0usr/10sys/298real ms.
正如我们看到的,这里有5次执行,在第4次运行中,我们获得了stap脚本的内核模块。
现在我们可以在创建内核模块时"在第4次运行时停止脚本执行"
# stap -v -p 4 hello-world.stp Pass 1: parsed user script and 479 library scripts using 247868virt/49964res/3448shr/46396data kb, in 820usr/20sys/852real ms. Pass 2: analyzed script: 1 probe, 1 function, 0 embeds, 0 globals using 249188virt/51544res/3748shr/47716data kb, in 10usr/0sys/13real ms. /root/.systemtap/cache/b0/stap_b013d9850b952b9fa68246bba7df5605_1013.ko Pass 3: using cached /root/.systemtap/cache/b0/stap_b013d9850b952b9fa68246bba7df5605_1013.c Pass 4: using cached /root/.systemtap/cache/b0/stap_b013d9850b952b9fa68246bba7df5605_1013.ko
正如预期的那样,脚本的执行在第4次运行时停止了,现在我们可以访问所提供的stap脚本的内核模块了。
# ls -l /root/.systemtap/cache/b0/stap_b013d9850b952b9fa68246bba7df5605_1013.ko -rw-r--r-- 1 root root 86232 Dec 2 21:09 /root/.systemtap/cache/b0/stap_b013d9850b952b9fa68246bba7df5605_1013.ko
要运行在其他地方创建的SystemTap模块,我们需要安装systemtap-runtime
,它提供了staprun
命令。
所以现在我们可以使用staprun执行此内核模块
# staprun /root/.systemtap/cache/b0/stap_b013d9850b952b9fa68246bba7df5605_1013.ko hello world
因此该脚本正在运行,我们得到了一个hello world输出。
示例脚本
这是一个示例性的stap脚本,可以了解进程是否收到了" signal 15"(" SIGTERM")。
# cat /tmp/getstatus.stp #!/usr/bin/env stap probe signal.send { time_ns = gettimeofday_ns(); if (pid_name == @1) { if (sig_name == "SIGTERM") { printf("%ld: %s(pid: %d) received a %s signal sent by %s(%d)\n", time_ns, pid_name, sig_pid, sig_name, execname(), pid()) exit() } } }
因此,让我们执行脚本并监视" dhcpd"进程
# stap /tmp/getstatus.stp dhcpd
在另一个终端上,我将使用"信号15"(" SIGTERM")停止dhcpd进程,并监视" stap"状态
# stap /tmp/getstatus.stp dhcpd 1543762612968405347: dhcpd(pid: 4201) received a SIGTERM signal sent by bash(3517)
如我们所见,它会按预期打印一条消息。
因此,我们的配置按预期工作。