linux bpftrace 命令
bpftrace 是一個基于 eBPF (擴展伯克利包過濾器) 的高級追蹤工具,它允許開發者在不修改內核代碼的情況下,動態地觀察和分析 Linux 系統的運行狀態。
eBPF 是 Linux 內核中的一項革命性技術,它提供了一個安全的虛擬機環境,可以在內核中運行用戶定義的代碼。bpftrace 構建在 eBPF 之上,提供了一個更簡單、更高級的抽象層。
bpftrace 的核心優勢
實時系統觀測
- 無需重啟系統或應用
- 極低的性能開銷
- 可以觀測內核和用戶空間程序
靈活的探測能力
- 支持多種探測點類型:函數入口/出口、定時器、硬件事件等
- 可以追蹤系統調用、網絡事件、磁盤 I/O 等
簡單的腳本語言
- 類似 AWK 的語法,學習曲線平緩
- 內置豐富的函數和變量
- 支持條件過濾和聚合統計
bpftrace 安裝與配置
安裝方法
實例
驗證安裝
sudo bpftrace -e 'BEGIN { printf("Hello, bpftrace!n"); }'
bpftrace 基本語法
bpftrace 程序由探測點(probe)和關聯的動作(action)組成,基本結構如下:
probe /filter/ { action }
探測點類型
探測點類型 | 描述 | 示例 |
---|---|---|
kprobe | 內核函數入口 | kprobe:vfs_read |
kretprobe | 內核函數返回 | kretprobe:vfs_read |
uprobe | 用戶空間函數入口 | uprobe:/bin/bash:readline |
tracepoint | 內核靜態追蹤點 | tracepoint:syscalls:sys_enter_open |
interval | 定時觸發 | interval:s:5 |
software | 軟件事件 | software:faults:major |
常用內置變量
- pid:當前進程 ID
- tid:當前線程 ID
- comm:當前進程名
- nsecs:納秒級時間戳
- arg0-argN:函數參數
- retval:函數返回值
bpftrace 實用示例
1. 追蹤系統調用
實例
2. 分析函數執行時間
實例
# 測量 vfs_read 的執行時間
sudo bpftrace -e ‘
kprobe:vfs_read { @start[tid] = nsecs; }
kretprobe:vfs_read /@start[tid]/ {
? ? @times = hist(nsecs – @start[tid]);
? ? delete(@start[tid]);
}’
sudo bpftrace -e ‘
kprobe:vfs_read { @start[tid] = nsecs; }
kretprobe:vfs_read /@start[tid]/ {
? ? @times = hist(nsecs – @start[tid]);
? ? delete(@start[tid]);
}’
3. 監控進程的文件訪問
實例
# 跟蹤指定進程打開的文件
sudo bpftrace -e ‘tracepoint:syscalls:sys_enter_openat /pid == 1234/ { printf(“%s -> %sn”, comm, str(args->filename)); }’
sudo bpftrace -e ‘tracepoint:syscalls:sys_enter_openat /pid == 1234/ { printf(“%s -> %sn”, comm, str(args->filename)); }’
4. 統計 TCP 連接
實例
# 按進程統計 TCP 連接數
sudo bpftrace -e ‘kprobe:tcp_connect { @[comm] = count(); }’
sudo bpftrace -e ‘kprobe:tcp_connect { @[comm] = count(); }’
bpftrace 高級特性
1. 地圖(map)功能
bpftrace 提供了多種內置地圖類型用于數據聚合:
實例
# 統計直方圖
@hist = hist(nsecs);
@hist = hist(nsecs);
# 計算平均值
@avg = avg(nsecs);
# 統計唯一值
@unique = count();
2. 條件過濾
實例
# 只追蹤特定進程的 read 調用
tracepoint:syscalls:sys_enter_read /pid == 1234/ {
? ? printf(“PID %d reading %d bytesn”, pid, args->count);
}
tracepoint:syscalls:sys_enter_read /pid == 1234/ {
? ? printf(“PID %d reading %d bytesn”, pid, args->count);
}
3. 多探針組合
實例
# 跟蹤從 socket 創建到連接的全過程
kprobe:sock_alloc {
? ? @socket[tid] = 1;
}
kprobe:sock_alloc {
? ? @socket[tid] = 1;
}
kprobe:tcp_connect /@socket[tid]/ {
? ? printf(“socket %d connecting to %s:%dn”, args->sock->__sk_common.skc_dport,
? ? ? ? ? ?ntop(args->sock->__sk_common.skc_daddr),
? ? ? ? ? ?args->sock->__sk_common.skc_dport);
? ? delete(@socket[tid]);
}
bpftrace 最佳實踐
- 限制追蹤范圍:使用 PID 或命令名過濾,減少系統開銷
- 避免過度打印:過多的 printf 會影響性能
- 使用聚合:盡量使用 count()、sum() 等聚合函數
- 清理資源:長時間運行的腳本要定期清理地圖數據
- 安全考慮:bpftrace 需要 root 權限,謹慎運行未知腳本
bpftrace 與其他工具對比
工具 | 優點 | 缺點 |
---|---|---|
bpftrace | 靈活、高性能、易用 | 需要 root 權限 |
strace | 簡單、無需編譯 | 性能開銷大 |
perf | 功能全面、低開銷 | 學習曲線陡峭 |
SystemTap | 功能強大 | 需要編譯、配置復雜 |
學習資源推薦
- bpftrace 官方文檔
- bpftrace 單行教程
- bpftrace 示例倉庫
bpftrace 是系統性能分析和故障排查的強大工具,通過實踐這些示例和掌握其核心概念,你將能夠更深入地理解和優化 Linux 系統的運行行為。
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END