bpftrace能帮我们干什么?1、统计 tcp连接的生命时长、2、统计mysql执行一条sql语句的时间3、统计redis执行命令的时间、 4、对文件进行一次读或者写的时间。
常用命令:
bpftrace -e 'Begin { printf("hello\n"); }'
bpftrace -l '*enter_accept*'
bpftrace -e 'tracepoint:syscalls:sys_enter_accept{ printf("accept\n"); }'
bpftrace -e 'tracepoint:syscalls:sys_enter_accept{ printf("accept %s\n", comm); }'
bpftrace -e 'tracepoint:syscalls:sys_enter_accept / comm == "networkio" / { printf("accept %s\n", comm); }'
bpftrace -e 't:syscalls:sys_enter_connect { printf("connect\n"); }'
Bpftrace -e 'kprobe:tcp_connect {printf("tcp_connect \n"); }'
bpftrace实现:获取到每一个连接的源IP、源端口、目的ip、目的端口 。执行方式bpftrace tcp_connect.bt
#include <net/sock.h>
#include <linux/socket.h>BEGIN
{printf("Enter tcp_connect Case \n");printf("%8s %6s %16s", "TIME", "PID", "COMM");printf("%19s:%5s %16s:%5s\n", "SADDR", "SPORT", "DADDR", "DPORT");
}kprobe:tcp_connect
{$sk = (struct sock*)arg0;$inet_family = $sk->__sk_common.skc_family;if ($inet_family == AF_INET) {$daddr = ntop($sk->__sk_common.skc_daddr);$saddr = ntop($sk->__sk_common.skc_rcv_saddr);}$dport = $sk->__sk_common.skc_dport;$lport = $sk->__sk_common.skc_num;$dport = bswap($dport);time("%H:%M:%S ");printf("%6d %16s", pid, comm);printf("%19s:%5d %16s:%5d\n", $saddr, $lport, $daddr, $dport);}END
{printf("Exit tcp_connect Case \n");
}
tcp_accept.bt
#include <net/sock.h>
#include <linux/socket.h>BEGIN
{printf("%8s %6s %16s", "TIME", "PID", "COMM");printf("%19s:%5s %16s:%5s\n", "SADDR", "SPORT", "DADDR", "DPORT");
}kretprobe:inet_csk_accept
{$sk = (struct sock*)retval;$inet_family = $sk->__sk_common.skc_family;if ($inet_family == AF_INET) {$daddr = ntop($sk->__sk_common.skc_daddr);$saddr = ntop($sk->__sk_common.skc_rcv_saddr);}$dport = $sk->__sk_common.skc_dport;$lport = $sk->__sk_common.skc_num;$dport = bswap($dport);time("%H:%M:%S ");printf("%6d %16s", pid, comm);printf("%19s:%5d %16s:%5d\n", $saddr, $lport, $daddr, $dport); }END
{printf("END\n");
}
tcp_life.bt tcp统计生命周期
#include <net/sock.h>
#include <linux/socket.h>BEGIN
{printf("%8s %6s %16s", "TIME", "PID", "COMM");printf("%19s:%5s %16s:%5s %s\n", "SADDR", "SPORT", "DADDR", "DPORT", "DURms");
}kprobe:tcp_set_state
{$sk = (struct sock*)arg0;$newstate = arg1;if ($newstate <= TCP_SYN_RECV) { // begin@birth[$sk] = nsecs;}if ($newstate == TCP_CLOSE ) { // end$dur = (nsecs - @birth[$sk]) / 1e6;$inet_family = $sk->__sk_common.skc_family;if ($inet_family == AF_INET) {$daddr = ntop($sk->__sk_common.skc_daddr);$saddr = ntop($sk->__sk_common.skc_rcv_saddr);}$dport = $sk->__sk_common.skc_dport;$lport = $sk->__sk_common.skc_num;$dport = bswap($dport);time("%H:%M:%S ");printf("%6d %16s", pid, comm);printf("%19s:%5d %16s:%5d %d\n", $saddr, $lport, $daddr, $dport, $dur); }
}END
{printf("END\n");
}
nginx.bt
BEGIN
{printf("NGINX\n");
}uprobe:/usr/local/nginx/sbin/nginx:ngx_close_connection
{printf("ngx_close_connection\n");
}END
{printf("Exit\n");
}
redis.bt
BEGIN
{}uprobe:/home/king/share/redis-7.4.0/src/redis-server:call
{printf("redis --> call\n");
}END
{}
mysqld.bt
BEGIN
{printf("Tracing MySQL Server\n");printf("%10s %6s %s\n", "TIME(ns)", "PID", "SQL");
}uprobe:/usr/sbin/mysqld:*dispatch_command*
{@start = nsecs;
}uprobe:/usr/sbin/mysqld:*dispatch_command*
/@start/
{$dur = nsecs - @start;printf("%10u %6d %s\n", $dur, pid, str(*arg1));
}END
{printf("Exit\n");
}
malloc.bt
BEGIN
{printf("%10s %16s %s\n", "TYPE", "NAME", "PID");
}uprobe:/lib/x86_64-linux-gnu/libc.so.6:malloc
/ comm == "King" /
{printf("%10s %16s %d\n", "malloc", comm, pid);
}uprobe:/lib/x86_64-linux-gnu/libc.so.6:free
/ comm == "King"/
{ printf("%10s %16s %d\n", "free", comm, pid);
}END
{printf("Exit\n");
}
ntyco.bt
BEGIN
{printf("Tracing NtyCo\n");
}
// 挂载到可执行程序里,具体函数
uprobe:/home/king/share/2404/7.2.1-bpf/NtyCo/nty_server:nty_coroutine_create
{printf("name: %s, pid: %d\n", comm, pid);
}END
{printf("Exit\n");
}
参考连接:https://github.com/0voice