bpftrace — dynamiczne śledzenie systemu Linux z eBPF
Opublikowano: 10 kwietnia 2026 · Kategoria: VPS
eBPF (extended Berkeley Packet Filter) to rewolucja w obserwabilności systemu Linux. Pozwala
uruchamiać własny kod w przestrzeni jądra — bezpiecznie, weryfikowalnie i z minimalnym
narzutem wydajnościowym. bpftrace to wysokopoziomowy język zbudowany na eBPF, który
pozwala pisać zaawansowane skrypty śledzenia w jednej linii lub krótkich programach — bez znajomości
C czy API jądra. Używany przez inżynierów Netflix, Meta i Cloudflare do diagnozowania problemów
produkcyjnych w czasie rzeczywistym.
Instalacja bpftrace i BCC
# Ubuntu 22.04+ / Debian 12+ sudo apt install bpftrace bpfcc-tools linux-headers-$(uname -r) -y # Sprawdź wersję i obsługiwane probes bpftrace --version bpftrace -l # lista wszystkich dostępnych probe types # Wymagania kernela: # - Kernel 5.8+ dla pełnych możliwości (CO-RE, BTF) # - Kernel 4.9+ dla podstawowych funkcji # - Sprawdź BTF support: ls /sys/kernel/btf/vmlinux && echo "BTF OK" || echo "Brak BTF — ograniczone mozliwosci" # Upewnij się że masz uprawnienia # bpftrace wymaga root lub CAP_BPF + CAP_SYS_ADMIN (kernel 5.8+)
Składnia bpftrace — probes, predicates, actions
Programy bpftrace składają się z reguł w formacie: probe /predicate/ { action }. Probe definiuje kiedy uruchomić akcję, predicate filtruje zdarzenia, action to kod
wykonywany przy dopasowaniu.
# Hello World — jednolinijkowy program
bpftrace -e 'tracepoint:syscalls:sys_enter_open { printf("PID %d otwieral: %s\n", pid, str(args->filename)); }'
# Z filtrem na PID (predicate)
bpftrace -e 'tracepoint:syscalls:sys_enter_openat /pid == 1234/ { printf("%s\n", str(args->filename)); }'
# Śledź wywołania write() i ich rozmiar (histogram)
bpftrace -e 'tracepoint:syscalls:sys_enter_write { @bytes = hist(args->count); }'
# Latencja syscall (czas między enter a exit)
bpftrace -e '
tracepoint:syscalls:sys_enter_read { @start[tid] = nsecs; }
tracepoint:syscalls:sys_exit_read /{@start[tid]}/ {
@latency_us = hist((nsecs - @start[tid]) / 1000);
delete(@start[tid]);
}
'
# Zmienne wbudowane dostępne w probe:
# pid — PID procesu
# tid — thread ID
# uid — user ID
# comm — nazwa procesu (comm string)
# nsecs — czas w nanosekndach
# cpu — numer CPU
# curtask — wskaźnik na task_struct Typy probe — tracepoints, kprobes, uprobes
| Typ probe | Przykład | Stabilność API | Zastosowanie |
|---|---|---|---|
| tracepoint | tracepoint:syscalls:sys_enter_read | Wysoka (stabilne API) | Syscalls, scheduler, network, block I/O |
| kprobe | kprobe:tcp_connect | Średnia (zmienne między wersjami) | Dowolna funkcja jądra, wewnętrzne zdarzenia |
| kretprobe | kretprobe:tcp_connect | Średnia | Wartość zwracana funkcji jądra |
| uprobe | uprobe:/usr/bin/php:zend_execute | Niska (symbol dependent) | Funkcje aplikacji user-space, biblioteki |
| uretprobe | uretprobe:/usr/bin/node:uv__run | Niska | Wartość zwracana funkcji user-space |
| profile | profile:hz:99 | Wysoka | CPU sampling (jak perf), flame graphs |
| software | software:page-faults:1000 | Wysoka | Software events (page faults, context-switch) |
| hardware | hardware:cache-misses:1000000 | Sprzętowa | PMU counters (cache misses, CPU cycles) |
Gotowe narzędzia — BCC tools
# execsnoop — śledź wszystkie nowe procesy (bardzo przydatne!) sudo execsnoop-bpfcc # PCOMM PID PPID RET ARGS # bash 12345 1234 0 bash -c ls /etc # ls 12346 12345 0 /usr/bin/ls /etc # opensnoop — otwierane pliki z latencją sudo opensnoop-bpfcc -p $(pgrep nginx | head -1) # PID COMM FD ERR PATH # 1234 nginx 22 0 /etc/nginx/nginx.conf # biolatency — histogram latencji dysku (blkio) sudo biolatency-bpfcc # Tracing block device I/O... Hit Ctrl-C to end. # usecs : count distribution # 0 -> 1 : 234 |**** | # 2 -> 3 : 1289 |************************| # 4 -> 7 : 890 |**************** | # tcpconnect — nowe wychodzące połączenia TCP sudo tcpconnect-bpfcc # PID COMM IP SADDR DADDR DPORT # tcpretrans — retransmisje TCP (problemy sieciowe) sudo tcpretrans-bpfcc # funclatency — latencja konkretnej funkcji sudo funclatency-bpfcc 'do_sys_open' # offcputime — gdzie procesy spędzają czas poza CPU (blokady, I/O) sudo offcputime-bpfcc -p $(pgrep php-fpm | head -1) 10
Własne skrypty bpftrace — przykłady produkcyjne
# Plik: slow-writes.bt — znajdź wolne write() > 1ms
# Uruchom: sudo bpftrace slow-writes.bt
tracepoint:syscalls:sys_enter_write
{
@start[tid] = nsecs;
}
tracepoint:syscalls:sys_exit_write
/@start[tid]/
{
$latency_us = (nsecs - @start[tid]) / 1000;
if ($latency_us > 1000) {
printf("SLOW WRITE: comm=%s pid=%d fd=%d latency=%dms\n",
comm, pid, args->fd, $latency_us / 1000);
}
delete(@start[tid]);
}
# Uruchom skrypt z pliku
sudo bpftrace slow-writes.bt
# -------
# Jednolinijkowiec — top 10 procesów po liczbie syscall read
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_read { @reads[comm, pid] = count(); }
END { print(@reads, 10); }
' -- sleep 30
# -------
# Śledź połączenia MySQL z PHP (uprobe na libmysql)
sudo bpftrace -e '
uprobe:/usr/lib/x86_64-linux-gnu/libmysqlclient.so:mysql_real_connect
{
printf("MySQL connect: pid=%d comm=%s\n", pid, comm);
}
'