bpftrace 简单示例
前提:安装 bpftrace,内核开启 BPF 支持;需要 root 运行(sudo bpftrace xxx.bt) 语法:bpftrace 是类 awk 语言,
probe /filter/ { action }
示例1:探测某个进程的 open 系统调用(最常用入门)
文件名:trace_open.bt
#!/usr/bin/env bpftrace // 探针:syscall:sys_openat(现代linux打开文件用openat) // 过滤:只看 PID=1234 的进程,把1234换成你要探测的程序pid tracepoint:syscalls:sys_enter_openat /pid == 1234/ { printf("PID:%d 打开文件: %s\n", pid, str(args->filename)); }运行:
sudo bpftrace trace_open.bt然后启动你的目标程序,它每次调用 openat 打开文件就会打印路径。
如果想按进程名过滤(比如探测
nginx):
tracepoint:syscalls:sys_enter_openat /comm == "nginx"/ { printf("PID:%d comm:%s file:%s\n", pid, comm, str(args->filename)); }示例2:kprobe 捕获函数调用(探测程序内部函数,适合用户态/内核函数)
假设你要探测目标程序
/bin/bash里的readline用户态函数(用户态函数需要符号) 文件名:trace_readline.bt
#!/usr/bin/env bpftrace uprobe:/bin/bash:readline { printf("bash readline() called, pid:%d\n", pid); }运行:
sudo bpftrace trace_readline.bt新开 bash,敲回车就会触发。
uprobe = 用户态探针;kprobe = 内核函数探针。
示例3:统计进程调用 read 的耗时(带时间)
tracepoint:syscalls:sys_enter_read /pid ==1234/ { @start[tid] = nsecs; } tracepoint:syscalls:sys_exit_read /pid ==1234 && @start[tid]/ { $dur = nsecs - @start[tid]; printf("read 耗时: %d ns\n", $dur); delete(@start[tid]); }直接在命令行单行运行(不用写文件,快速试)
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat /comm == "cat"/ { printf("file: %s\n", str(args->filename)); }'另开终端执行cat /etc/passwd,你就能看到打印。
参考链接 :0voice · GitHub