Linux下Bpftrace具体使用方法

Bpftrace是Linux的新开源跟踪程序,用于分析生产性能问题和故障排除软件。 它的用户和贡献者包括Netflix,Facebook,Red Hat,Shopify等,它是由Alastair Robertson创建的, Alastair Robertson是一位才华横溢的英国开发商,赢得了各种编码竞赛,下面为大家分享一下Linux下Bpftrace具体使用方法。

安装和快速入门

在终端 使用 sudo 执行下面的命令安装 bpftrace:

$ sudo dnf install bpftrace

使用“hello world”进行实验:

$ sudo bpftrace -e 'BEGIN { printf("hello world\n"); }'

注意,出于特权级的需要,你必须使用 root 运行 bpftrace,使用 -e 选项指明一个程序,构建一个所谓的“单行程序”。这个例子只会打印 “hello world”,接着等待你按下 Ctrl+C。

BEGIN 是一个特殊的探针名,只在执行一开始生效一次;每次探针命中时,大括号 {} 内的操作(这个例子中只是一个 printf)

都会执行。

现在让我们转向一个更有用的例子:

$ sudo bpftrace -e 't:syscalls:sys_enter_execve { printf("%s called %s\n", comm, str(args->filename)); }'

这个例子打印了父进程的名字(comm)和系统中正在创建的每个新进程的名称。t:syscalls:sys_enter_execve 是一个内核追踪点,是 tracepoint:syscalls:sys_enter_execve 的简写,两种形式都可以使用。下一部分会向你展示如何列出所有可用的追踪点。

comm 是一个 bpftrace 内建指令,代表进程名;filename 是 t:syscalls:sys_enter_execve 追踪点的一个字段,这些字段可以通过 args 内建指令访问。

追踪点的所有可用字段可以通过这个命令列出:

bpftrace -lv "t:syscalls:sys_enter_execve"

示例用法

bpftrace 的一个核心概念是探针点,即 eBPF 程序可以连接到的(内核或用户空间的)代码中的测量点,可以分成以下几大类:

  • kprobe——内核函数的开始处 kretprobe——内核函数的返回处 uprobe——用户级函数的开始处 uretprobe——用户级函数的返回处 tracepoint——内核静态追踪点 USDT——用户级静态追踪点 profile——基于时间的采样 interval——基于时间的输出 software——内核软件事件 hardware——处理器级事件

所有可用的 kprobe / kretprobe、tracepoints、software 和 hardware 探针可以通过这个命令列出:

$ sudo bpftrace -l

uprobe / uretprobe 和 USDT 是用户空间探针,专用于某个可执行文件。要使用这些探针,通过下文中的特殊语法。profile 和 interval 探以固定的时间间隔触发;固定的时间间隔不在本文的范畴内。

统计系统调用数

映射 是保存计数、统计数据和柱状图的特殊 BPF 数据类型,你可以使用映射统计每个系统调用正在被调用的次数:

$ sudo bpftrace -e 't:syscalls:sys_enter_* { @[probe] = count(); }'

一些探针类型允许使用通配符匹配多个探针,你也可以使用一个逗号隔开的列表为一个操作块指明多个连接点。上面的例子中,操作块连接到了所有名称以 t:syscalls:sysenter_ 开头的追踪点,即所有可用的系统调用。

bpftrace 的内建函数 count() 统计系统调用被调用的次数;@[] 代表一个映射(一个关联数组)。该映射的键 probe 是另一个内建指令,代表完整的探针名。

这个例子中,相同的操作块连接到了每个系统调用,之后每次有系统调用被调用时,映射就会被更新,映射中和系统调用对应的项就会增加。程序终止时,自动打印出所有声明的映射。

下面的例子统计所有的系统调用,然后通过 bpftrace 过滤语法使用 PID 过滤出某个特定进程调用的系统调用:

$ sudo bpftrace -e 't:syscalls:sys_enter_* / pid == 1234 / { @[probe] = count(); }'

进程写的字节数

让我们使用上面的概念分析每个进程正在写的字节数:

$ sudo bpftrace -e 't:syscalls:sys_exit_write /args->ret > 0/ { @[comm] = sum(args->ret); }'

bpftrace 连接操作块到写系统调用的返回探针(t:syscalls:sys_exit_write),然后使用过滤器丢掉代表错误代码的负值(/arg->ret > 0/)。

映射的键 comm 代表调用系统调用的进程名;内建函数 sum() 累计每个映射项或进程写的字节数;args 是一个 bpftrace 内建指令,用于访问追踪点的参数和返回值。如果执行成功,write 系统调用返回写的字节数,arg->ret

用于访问这个字节数。

进程的读取大小分布(柱状图):

bpftrace 支持创建柱状图。让我们分析一个创建进程的 read 大小分布的柱状图的例子:

$ sudo bpftrace -e 't:syscalls:sys_exit_read { @[comm] = hist(args->ret); }'

柱状图是 BPF 映射,因此必须保存为一个映射(@),这个例子中映射键是 comm。

这个例子使 bpftrace 给每个调用 read 系统调用的进程生成一个柱状图。要生成一个全局柱状图,直接保存 hist() 函数到 @(不使用任何键)。

程序终止时,bpftrace 自动打印出声明的柱状图。创建柱状图的基准值是通过 args->ret 获取到的读取的字节数。

追踪用户空间程序

你也可以通过 uprobes / uretprobes 和 USDT(用户级静态定义的追踪)追踪用户空间程序。下一个例子使用探测用户级函数结尾处的 uretprobe ,获取系统中运行的每个 bash 发出的命令行:

$ sudo bpftrace -e 'uretprobe:/bin/bash:readline { printf("readline: \"%s\"\n", str(retval)); }'

要列出可执行文件 bash 的所有可用 uprobes / uretprobes, 执行这个命令:

$ sudo bpftrace -l "uprobe:/bin/bash"

uprobe 指向用户级函数执行的开始,uretprobe 指向执行的结束(返回处);readline() 是 /bin/bash 的一个函数,返回键入的命令行;retval 是被探测的指令的返回值,只能在 uretprobe 访问。

使用 uprobes 时,你可以用 arg0..argN 访问参数。需要调用 str() 将 char * 指针转化成一个字符串。

自带脚本

bpftrace 软件包附带了许多有用的脚本,可以在 /usr/share/bpftrace/tools/ 目录找到。

这些脚本中,你可以找到:

  • killsnoop.bt——追踪 kill() 系统调用发出的信号
  • tcpconnect.bt——追踪所有的 TCP 网络连接
  • pidpersec.bt——统计每秒钟(通过fork)创建的新进程
  • opensnoop.bt——追踪 open() 系统调用
  • bfsstat.bt——追踪一些 VFS 调用,按秒统计

你可以直接使用这些脚本,比如:

$ sudo /usr/share/bpftrace/tools/killsnoop.bt

你也可以在创建新的工具时参考这些脚本。

原创文章,作者:晴川运维,如若转载,请注明出处:https://baike.qcidc.com/10068.html

(0)
晴川运维晴川运维
上一篇 3小时前
下一篇 3小时前

相关推荐

  • Ansible可以帮我们做什么?

    ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量…

    Linux系统 2025年6月8日
  • Linux下安装Docker具体方法

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化,下面为大家分享一下Li…

    Linux系统 2025年6月12日
  • Linux下使用Helix具体使用方法

    Helix 是一个后现代的模态文本编辑器。受 kakoune/neovim 启发的编辑器,用 Rust 编写;编辑模型在很大程度上是基于 kakoune,下面为大家分享一下Linu…

    Linux系统 2025年6月8日
  • 详解Linux下端口映射

    端口映射器可实现端口映射功能,一个主要用途就是可以在局域网的网关上运行本程序,将网关服务器的某个端口映射为局域网中某台机器的某个端口,这样,局域网外部访问网关服务器的8081端口就…

    Linux系统 1天前
  • 详解Linux初始化系统

    在 Linux 和其他类 Uniux 系统中,init(初始化)进程是系统启动时由内核执行的第一个进程,其进程 ID(PID)为 1,并静默运行在后台,直到系统关闭。 init 进…

    Linux系统 2025年6月9日
  • Linux运维面试集锦

    本篇文章重点为大家分享一下Linux运维人员面试常见的问题及答案,准备参加Linux运维面试的小伙伴们是否做好了面试准备,今天在这里小编继续为大家分享一些Linux运维人员面试中的…

    Linux系统 2025年6月8日
  • 快速上手Elasticsearch

    Elasticsearch是一个开源的分布式、RESTful 风格的搜索和数据分析引擎,它的底层是开源库Apache Lucene。 Lucene 可以说是当下最先进、高性能、全功…

    Linux系统 3天前
  • Linux Mint 安装 Linux Kernel 4.12

    Linus Torvalds 发布了 Linux 内核 4.12。你可以从这里直接下载相关的 deb 包来安装。或者,继续阅读本文,按下面的步骤安装新内核。 警告:Linux 内核…

    Linux系统 5天前
  • Linux su命令:用户间切换(包含su和su -的区别)

    su 是最简单的用户切换命令,通过该命令可以实现任何身份的切换,包括从普通用户切换为 root 用户、从 root 用户切换为普通用户以及普通用户之间的切换。 普通用户之间切换以及…

    Linux系统 2025年6月8日
  • Linux终端中实现大小写字符转换

    Linux终端中提供了一些可以大小写之间转换文本的命令,通过这些命令可以提高我们的工作效率,本篇文章重点为大家讲解一下Linux终端中进行大小写字符转换具体方法。 环境 Cento…

    Linux系统 2025年6月11日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注