From bdf0773fe4cad43539dec0383f3e306929663f02 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Thu, 14 Jan 2016 10:09:20 -0800 Subject: [PATCH] fix pep8 lint errors in the rest of the tools no functional changes Signed-off-by: Alexei Starovoitov --- tools/biolatency_example.txt | 2 +- tools/funccount | 93 +++++++++++------------ tools/funclatency | 173 ++++++++++++++++++++++--------------------- tools/hardirqs | 159 +++++++++++++++++++-------------------- tools/hardirqs_example.txt | 2 +- tools/killsnoop | 87 +++++++++++----------- tools/killsnoop_example.txt | 2 +- tools/opensnoop | 99 +++++++++++++------------ tools/opensnoop_example.txt | 96 +++++++++++------------- tools/pidpersec | 26 +++---- tools/softirqs | 141 ++++++++++++++++++----------------- tools/softirqs_example.txt | 2 +- tools/syncsnoop | 15 ++-- tools/syncsnoop_example.txt | 2 +- tools/tcpaccept | 143 +++++++++++++++++------------------ tools/tcpaccept_example.txt | 10 +-- tools/tcpconnect | 165 +++++++++++++++++++++-------------------- tools/tcpconnect_example.txt | 10 +-- tools/vfscount | 15 ++-- tools/vfscount_example.txt | 2 +- tools/vfsstat | 84 +++++++++++---------- tools/vfsstat_example.txt | 2 +- 22 files changed, 669 insertions(+), 661 deletions(-) diff --git a/tools/biolatency_example.txt b/tools/biolatency_example.txt index 06944c0..8112a34 100644 --- a/tools/biolatency_example.txt +++ b/tools/biolatency_example.txt @@ -5,7 +5,7 @@ biolatency traces block device I/O (disk I/O), and records the distribution of I/O latency (time), printing this as a histogram when Ctrl-C is hit. For example: -# ./biolatency +# ./biolatency Tracing block device I/O... Hit Ctrl-C to end. ^C usecs : count distribution diff --git a/tools/funccount b/tools/funccount index 6689872..f417087 100755 --- a/tools/funccount +++ b/tools/funccount @@ -1,7 +1,8 @@ #!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports # -# funccount Count kernel function calls. -# For Linux, uses BCC, eBPF. See .c file. +# funccount Count kernel function calls. +# For Linux, uses BCC, eBPF. See .c file. # # USAGE: funccount [-h] [-p PID] [-i INTERVAL] [-T] [-r] pattern # @@ -11,7 +12,7 @@ # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 09-Sep-2015 Brendan Gregg Created this. +# 09-Sep-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF @@ -28,63 +29,63 @@ examples = """examples: ./funccount -p 185 'vfs_*' # count vfs calls for PID 181 only """ parser = argparse.ArgumentParser( - description="Count kernel function calls", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=examples) + description="Count kernel function calls", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=examples) parser.add_argument("-p", "--pid", - help="trace this PID only") + help="trace this PID only") parser.add_argument("-i", "--interval", default=99999999, - help="summary interval, seconds") + help="summary interval, seconds") parser.add_argument("-T", "--timestamp", action="store_true", - help="include timestamp on output") + help="include timestamp on output") parser.add_argument("-r", "--regexp", action="store_true", - help="use regular expressions. Default is \"*\" wildcards only.") + help="use regular expressions. Default is \"*\" wildcards only.") parser.add_argument("pattern", - help="search expression for kernel functions") + help="search expression for kernel functions") args = parser.parse_args() pattern = args.pattern if not args.regexp: - pattern = pattern.replace('*', '.*') - pattern = '^' + pattern + '$' + pattern = pattern.replace('*', '.*') + pattern = '^' + pattern + '$' debug = 0 # signal handler def signal_ignore(signal, frame): - print() + print() # load BPF program bpf_text = """ #include struct key_t { - u64 ip; + u64 ip; }; BPF_HASH(counts, struct key_t); int trace_count(struct pt_regs *ctx) { - FILTER - struct key_t key = {}; - u64 zero = 0, *val; - key.ip = ctx->ip; - val = counts.lookup_or_init(&key, &zero); - (*val)++; - return 0; + FILTER + struct key_t key = {}; + u64 zero = 0, *val; + key.ip = ctx->ip; + val = counts.lookup_or_init(&key, &zero); + (*val)++; + return 0; } """ if args.pid: - bpf_text = bpf_text.replace('FILTER', - ('u32 pid; pid = bpf_get_current_pid_tgid(); ' + - 'if (pid != %s) { return 0; }') % (args.pid)) + bpf_text = bpf_text.replace('FILTER', + ('u32 pid; pid = bpf_get_current_pid_tgid(); ' + + 'if (pid != %s) { return 0; }') % (args.pid)) else: - bpf_text = bpf_text.replace('FILTER', '') + bpf_text = bpf_text.replace('FILTER', '') if debug: - print(bpf_text) + print(bpf_text) b = BPF(text=bpf_text) b.attach_kprobe(event_re=pattern, fn_name="trace_count") matched = b.num_open_kprobes() if matched == 0: - print("0 functions matched by \"%s\". Exiting." % args.pattern) - exit() + print("0 functions matched by \"%s\". Exiting." % args.pattern) + exit() # header print("Tracing %d functions for \"%s\"... Hit Ctrl-C to end." % @@ -93,23 +94,23 @@ print("Tracing %d functions for \"%s\"... Hit Ctrl-C to end." % # output exiting = 0 if args.interval else 1 while (1): - try: - sleep(int(args.interval)) - except KeyboardInterrupt: - exiting=1 - # as cleanup can take many seconds, trap Ctrl-C: - signal.signal(signal.SIGINT, signal_ignore) + try: + sleep(int(args.interval)) + except KeyboardInterrupt: + exiting = 1 + # as cleanup can take many seconds, trap Ctrl-C: + signal.signal(signal.SIGINT, signal_ignore) - print() - if args.timestamp: - print("%-8s\n" % strftime("%H:%M:%S"), end="") + print() + if args.timestamp: + print("%-8s\n" % strftime("%H:%M:%S"), end="") - print("%-16s %-26s %8s" % ("ADDR", "FUNC", "COUNT")) - counts = b.get_table("counts") - for k, v in sorted(counts.items(), key=lambda counts: counts[1].value): - print("%-16x %-26s %8d" % (k.ip, b.ksym(k.ip), v.value)) - counts.clear() + print("%-16s %-26s %8s" % ("ADDR", "FUNC", "COUNT")) + counts = b.get_table("counts") + for k, v in sorted(counts.items(), key=lambda counts: counts[1].value): + print("%-16x %-26s %8d" % (k.ip, b.ksym(k.ip), v.value)) + counts.clear() - if exiting: - print("Detaching...") - exit() + if exiting: + print("Detaching...") + exit() diff --git a/tools/funclatency b/tools/funclatency index 79a9406..1968c94 100755 --- a/tools/funclatency +++ b/tools/funclatency @@ -1,7 +1,8 @@ #!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports # -# funclatency Time kernel funcitons and print latency as a histogram. -# For Linux, uses BCC, eBPF. +# funclatency Time kernel funcitons and print latency as a histogram. +# For Linux, uses BCC, eBPF. # # USAGE: funclatency [-h] [-p PID] [-i INTERVAL] [-T] [-u] [-m] [-r] pattern # @@ -20,7 +21,7 @@ # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 20-Sep-2015 Brendan Gregg Created this. +# 20-Sep-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF @@ -39,30 +40,30 @@ examples = """examples: ./funclatency -F 'vfs_r*' # show one histogram per matched function """ parser = argparse.ArgumentParser( - description="Time kernel funcitons and print latency as a histogram", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=examples) + description="Time kernel funcitons and print latency as a histogram", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=examples) parser.add_argument("-p", "--pid", - help="trace this PID only") + help="trace this PID only") parser.add_argument("-i", "--interval", default=99999999, - help="summary interval, seconds") + help="summary interval, seconds") parser.add_argument("-T", "--timestamp", action="store_true", - help="include timestamp on output") + help="include timestamp on output") parser.add_argument("-u", "--microseconds", action="store_true", - help="microsecond histogram") + help="microsecond histogram") parser.add_argument("-m", "--milliseconds", action="store_true", - help="millisecond histogram") + help="millisecond histogram") parser.add_argument("-F", "--function", action="store_true", - help="show a separate histogram per function") + help="show a separate histogram per function") parser.add_argument("-r", "--regexp", action="store_true", - help="use regular expressions. Default is \"*\" wildcards only.") + help="use regular expressions. Default is \"*\" wildcards only.") parser.add_argument("pattern", - help="search expression for kernel functions") + help="search expression for kernel functions") args = parser.parse_args() pattern = args.pattern if not args.regexp: - pattern = pattern.replace('*', '.*') - pattern = '^' + pattern + '$' + pattern = pattern.replace('*', '.*') + pattern = '^' + pattern + '$' debug = 0 # define BPF program @@ -71,8 +72,8 @@ bpf_text = """ #include typedef struct ip_key { - u64 ip; - u64 slot; + u64 ip; + u64 slot; } ip_key_t; BPF_HASH(start, u32); @@ -80,73 +81,73 @@ STORAGE int trace_func_entry(struct pt_regs *ctx) { - u32 pid = bpf_get_current_pid_tgid(); - u64 ts = bpf_ktime_get_ns(); + u32 pid = bpf_get_current_pid_tgid(); + u64 ts = bpf_ktime_get_ns(); - FILTER - ENTRYSTORE - start.update(&pid, &ts); + FILTER + ENTRYSTORE + start.update(&pid, &ts); - return 0; + return 0; } int trace_func_return(struct pt_regs *ctx) { - u64 *tsp, delta; - u32 pid = bpf_get_current_pid_tgid(); - - // calculate delta time - tsp = start.lookup(&pid); - if (tsp == 0) { - return 0; // missed start - } - delta = bpf_ktime_get_ns() - *tsp; - start.delete(&pid); - FACTOR - - // store as histogram - STORE - - return 0; + u64 *tsp, delta; + u32 pid = bpf_get_current_pid_tgid(); + + // calculate delta time + tsp = start.lookup(&pid); + if (tsp == 0) { + return 0; // missed start + } + delta = bpf_ktime_get_ns() - *tsp; + start.delete(&pid); + FACTOR + + // store as histogram + STORE + + return 0; } """ # code substitutions if args.pid: - bpf_text = bpf_text.replace('FILTER', - 'if (pid != %s) { return 0; }' % args.pid) + bpf_text = bpf_text.replace('FILTER', + 'if (pid != %s) { return 0; }' % args.pid) else: - bpf_text = bpf_text.replace('FILTER', '') + bpf_text = bpf_text.replace('FILTER', '') if args.milliseconds: - bpf_text = bpf_text.replace('FACTOR', 'delta /= 1000000;') - label = "msecs" + bpf_text = bpf_text.replace('FACTOR', 'delta /= 1000000;') + label = "msecs" elif args.microseconds: - bpf_text = bpf_text.replace('FACTOR', 'delta /= 1000;') - label = "usecs" + bpf_text = bpf_text.replace('FACTOR', 'delta /= 1000;') + label = "usecs" else: - bpf_text = bpf_text.replace('FACTOR', '') - label = "nsecs" + bpf_text = bpf_text.replace('FACTOR', '') + label = "nsecs" if args.function: - bpf_text = bpf_text.replace('STORAGE', 'BPF_HASH(ipaddr, u32);\n' + - 'BPF_HISTOGRAM(dist, ip_key_t);') - # stash the IP on entry, as on return it's kretprobe_trampoline: - bpf_text = bpf_text.replace('ENTRYSTORE', - 'u64 ip = ctx->ip; ipaddr.update(&pid, &ip);') - bpf_text = bpf_text.replace('STORE', - 'u64 ip, *ipp = ipaddr.lookup(&pid); if (ipp) { ip = *ipp; ' + - 'dist.increment((ip_key_t){ip, bpf_log2l(delta)}); ' + - 'ipaddr.delete(&pid); }') + bpf_text = bpf_text.replace('STORAGE', 'BPF_HASH(ipaddr, u32);\n' + + 'BPF_HISTOGRAM(dist, ip_key_t);') + # stash the IP on entry, as on return it's kretprobe_trampoline: + bpf_text = bpf_text.replace('ENTRYSTORE', + 'u64 ip = ctx->ip; ipaddr.update(&pid, &ip);') + bpf_text = bpf_text.replace('STORE', + 'u64 ip, *ipp = ipaddr.lookup(&pid); if (ipp) { ip = *ipp; ' + + 'dist.increment((ip_key_t){ip, bpf_log2l(delta)}); ' + + 'ipaddr.delete(&pid); }') else: - bpf_text = bpf_text.replace('STORAGE', 'BPF_HISTOGRAM(dist);') - bpf_text = bpf_text.replace('ENTRYSTORE', '') - bpf_text = bpf_text.replace('STORE', - 'dist.increment(bpf_log2l(delta));') + bpf_text = bpf_text.replace('STORAGE', 'BPF_HISTOGRAM(dist);') + bpf_text = bpf_text.replace('ENTRYSTORE', '') + bpf_text = bpf_text.replace('STORE', + 'dist.increment(bpf_log2l(delta));') if debug: - print(bpf_text) + print(bpf_text) # signal handler def signal_ignore(signal, frame): - print() + print() # load BPF program b = BPF(text=bpf_text) @@ -154,8 +155,8 @@ b.attach_kprobe(event_re=pattern, fn_name="trace_func_entry") b.attach_kretprobe(event_re=pattern, fn_name="trace_func_return") matched = b.num_open_kprobes() if matched == 0: - print("0 functions matched by \"%s\". Exiting." % args.pattern) - exit() + print("0 functions matched by \"%s\". Exiting." % args.pattern) + exit() # header print("Tracing %d functions for \"%s\"... Hit Ctrl-C to end." % @@ -165,23 +166,23 @@ print("Tracing %d functions for \"%s\"... Hit Ctrl-C to end." % exiting = 0 if args.interval else 1 dist = b.get_table("dist") while (1): - try: - sleep(int(args.interval)) - except KeyboardInterrupt: - exiting=1 - # as cleanup can take many seconds, trap Ctrl-C: - signal.signal(signal.SIGINT, signal_ignore) - - print() - if args.timestamp: - print("%-8s\n" % strftime("%H:%M:%S"), end="") - - if args.function: - dist.print_log2_hist(label, "Function", BPF.ksym) - else: - dist.print_log2_hist(label) - dist.clear() - - if exiting: - print("Detaching...") - exit() + try: + sleep(int(args.interval)) + except KeyboardInterrupt: + exiting = 1 + # as cleanup can take many seconds, trap Ctrl-C: + signal.signal(signal.SIGINT, signal_ignore) + + print() + if args.timestamp: + print("%-8s\n" % strftime("%H:%M:%S"), end="") + + if args.function: + dist.print_log2_hist(label, "Function", BPF.ksym) + else: + dist.print_log2_hist(label) + dist.clear() + + if exiting: + print("Detaching...") + exit() diff --git a/tools/hardirqs b/tools/hardirqs index bff5e51..05a8871 100755 --- a/tools/hardirqs +++ b/tools/hardirqs @@ -1,7 +1,8 @@ #!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports # -# hardirqs Summarize hard IRQ (interrupt) event time. -# For Linux, uses BCC, eBPF. +# hardirqs Summarize hard IRQ (interrupt) event time. +# For Linux, uses BCC, eBPF. # # USAGE: hardirqs [-h] [-T] [-Q] [-m] [-D] [interval] [count] # @@ -10,7 +11,7 @@ # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 19-Oct-2015 Brendan Gregg Created this. +# 19-Oct-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF @@ -25,27 +26,27 @@ examples = """examples: ./hardirqs -NT 1 # 1s summaries, nanoseconds, and timestamps """ parser = argparse.ArgumentParser( - description="Summarize hard irq event time as histograms", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=examples) + description="Summarize hard irq event time as histograms", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=examples) parser.add_argument("-T", "--timestamp", action="store_true", - help="include timestamp on output") + help="include timestamp on output") parser.add_argument("-N", "--nanoseconds", action="store_true", - help="output in nanoseconds") + help="output in nanoseconds") parser.add_argument("-d", "--dist", action="store_true", - help="show distributions as histograms") + help="show distributions as histograms") parser.add_argument("interval", nargs="?", default=99999999, - help="output interval, in seconds") + help="output interval, in seconds") parser.add_argument("count", nargs="?", default=99999999, - help="number of outputs") + help="number of outputs") args = parser.parse_args() countdown = int(args.count) if args.nanoseconds: - factor = 1 - label = "nsecs" + factor = 1 + label = "nsecs" else: - factor = 1000 - label = "usecs" + factor = 1000 + label = "usecs" debug = 0 ### define BPF program @@ -56,8 +57,8 @@ bpf_text = """ #include typedef struct irq_key { - char name[32]; - u64 slot; + char name[32]; + u64 slot; } irq_key_t; BPF_HASH(start, u32); BPF_HASH(irqdesc, u32, struct irq_desc *); @@ -66,59 +67,59 @@ BPF_HISTOGRAM(dist, irq_key_t); // time IRQ int trace_start(struct pt_regs *ctx, struct irq_desc *desc) { - u32 pid = bpf_get_current_pid_tgid(); - u64 ts = bpf_ktime_get_ns(); - start.update(&pid, &ts); - irqdesc.update(&pid, &desc); - return 0; + u32 pid = bpf_get_current_pid_tgid(); + u64 ts = bpf_ktime_get_ns(); + start.update(&pid, &ts); + irqdesc.update(&pid, &desc); + return 0; } int trace_completion(struct pt_regs *ctx) { - u64 *tsp, delta; - struct irq_desc **descp; - u32 pid = bpf_get_current_pid_tgid(); - - // fetch timestamp and calculate delta - tsp = start.lookup(&pid); - descp = irqdesc.lookup(&pid); - if (tsp == 0 || descp == 0) { - return 0; // missed start - } - // Note: descp is a value from map, so '&' can be done without - // probe_read, but the next level irqaction * needs a probe read. - // Do these steps first after reading the map, otherwise some of these - // pointers may get pushed onto the stack and verifier will fail. - struct irqaction *action = 0; - bpf_probe_read(&action, sizeof(action), &(*descp)->action); - const char **namep = &action->name; - char *name = 0; - bpf_probe_read(&name, sizeof(name), namep); - delta = bpf_ktime_get_ns() - *tsp; - - // store as sum or histogram - STORE - - start.delete(&pid); - irqdesc.delete(&pid); - return 0; + u64 *tsp, delta; + struct irq_desc **descp; + u32 pid = bpf_get_current_pid_tgid(); + + // fetch timestamp and calculate delta + tsp = start.lookup(&pid); + descp = irqdesc.lookup(&pid); + if (tsp == 0 || descp == 0) { + return 0; // missed start + } + // Note: descp is a value from map, so '&' can be done without + // probe_read, but the next level irqaction * needs a probe read. + // Do these steps first after reading the map, otherwise some of these + // pointers may get pushed onto the stack and verifier will fail. + struct irqaction *action = 0; + bpf_probe_read(&action, sizeof(action), &(*descp)->action); + const char **namep = &action->name; + char *name = 0; + bpf_probe_read(&name, sizeof(name), namep); + delta = bpf_ktime_get_ns() - *tsp; + + // store as sum or histogram + STORE + + start.delete(&pid); + irqdesc.delete(&pid); + return 0; } """ ### code substitutions if args.dist: - bpf_text = bpf_text.replace('STORE', - 'irq_key_t key = {.slot = bpf_log2l(delta)};' + - 'bpf_probe_read(&key.name, sizeof(key.name), name);' + - 'dist.increment(key);') + bpf_text = bpf_text.replace('STORE', + 'irq_key_t key = {.slot = bpf_log2l(delta)};' + + 'bpf_probe_read(&key.name, sizeof(key.name), name);' + + 'dist.increment(key);') else: - bpf_text = bpf_text.replace('STORE', - 'irq_key_t key = {.slot = 0 /* ignore */};' + - 'bpf_probe_read(&key.name, sizeof(key.name), name);' + - 'u64 zero = 0, *vp = dist.lookup_or_init(&key, &zero);' + - '(*vp) += delta;') + bpf_text = bpf_text.replace('STORE', + 'irq_key_t key = {.slot = 0 /* ignore */};' + + 'bpf_probe_read(&key.name, sizeof(key.name), name);' + + 'u64 zero = 0, *vp = dist.lookup_or_init(&key, &zero);' + + '(*vp) += delta;') if debug: - print(bpf_text) + print(bpf_text) ### load BPF program b = BPF(text=bpf_text) @@ -133,23 +134,23 @@ print("Tracing hard irq event time... Hit Ctrl-C to end.") exiting = 0 if args.interval else 1 dist = b.get_table("dist") while (1): - try: - sleep(int(args.interval)) - except KeyboardInterrupt: - exiting=1 - - print() - if args.timestamp: - print("%-8s\n" % strftime("%H:%M:%S"), end="") - - if args.dist: - dist.print_log2_hist(label, "hardirq") - else: - print("%-26s %11s" % ("HARDIRQ", "TOTAL_" + label)) - for k, v in sorted(dist.items(), key=lambda dist: dist[1].value): - print("%-26s %11d" % (k.name, v.value / factor)) - dist.clear() - - countdown -= 1 - if exiting or countdown == 0: - exit() + try: + sleep(int(args.interval)) + except KeyboardInterrupt: + exiting = 1 + + print() + if args.timestamp: + print("%-8s\n" % strftime("%H:%M:%S"), end="") + + if args.dist: + dist.print_log2_hist(label, "hardirq") + else: + print("%-26s %11s" % ("HARDIRQ", "TOTAL_" + label)) + for k, v in sorted(dist.items(), key=lambda dist: dist[1].value): + print("%-26s %11d" % (k.name, v.value / factor)) + dist.clear() + + countdown -= 1 + if exiting or countdown == 0: + exit() diff --git a/tools/hardirqs_example.txt b/tools/hardirqs_example.txt index c2d9fa2..a36eaac 100644 --- a/tools/hardirqs_example.txt +++ b/tools/hardirqs_example.txt @@ -4,7 +4,7 @@ Demonstrations of hardirqs, the Linux eBPF/bcc version. This program traces hard interrupts (irqs), and stores timing statistics in-kernel for efficiency. For example: -# ./hardirqs +# ./hardirqs Tracing hard irq event time... Hit Ctrl-C to end. ^C HARDIRQ TOTAL_usecs diff --git a/tools/killsnoop b/tools/killsnoop index ea9a843..ddf9d5a 100755 --- a/tools/killsnoop +++ b/tools/killsnoop @@ -1,14 +1,15 @@ #!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports # -# killsnoop Trace signals issued by the kill() syscall. -# For Linux, uses BCC, eBPF. Embedded C. +# killsnoop Trace signals issued by the kill() syscall. +# For Linux, uses BCC, eBPF. Embedded C. # # USAGE: killsnoop [-h] [-t] [-x] [-p PID] # # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 20-Sep-2015 Brendan Gregg Created this. +# 20-Sep-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF @@ -22,15 +23,15 @@ examples = """examples: ./killsnoop -p 181 # only trace PID 181 """ parser = argparse.ArgumentParser( - description="Trace signals issued by the kill() syscall", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=examples) + description="Trace signals issued by the kill() syscall", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=examples) parser.add_argument("-t", "--timestamp", action="store_true", - help="include timestamp on output") + help="include timestamp on output") parser.add_argument("-x", "--failed", action="store_true", - help="only show failed opens") + help="only show failed opens") parser.add_argument("-p", "--pid", - help="trace this PID only") + help="trace this PID only") args = parser.parse_args() debug = 0 @@ -43,63 +44,63 @@ BPF_HASH(args_sig, u32, int); int kprobe__sys_kill(struct pt_regs *ctx, int tpid, int sig) { - u32 pid = bpf_get_current_pid_tgid(); + u32 pid = bpf_get_current_pid_tgid(); - FILTER - args_pid.update(&pid, &tpid); - args_sig.update(&pid, &sig); + FILTER + args_pid.update(&pid, &tpid); + args_sig.update(&pid, &sig); - return 0; + return 0; }; int kretprobe__sys_kill(struct pt_regs *ctx) { - int *tpidp, *sigp, ret = ctx->ax; - u32 pid = bpf_get_current_pid_tgid(); + int *tpidp, *sigp, ret = ctx->ax; + u32 pid = bpf_get_current_pid_tgid(); - tpidp = args_pid.lookup(&pid); - sigp = args_sig.lookup(&pid); - if (tpidp == 0 || sigp == 0) { - return 0; // missed entry - } + tpidp = args_pid.lookup(&pid); + sigp = args_sig.lookup(&pid); + if (tpidp == 0 || sigp == 0) { + return 0; // missed entry + } - bpf_trace_printk("%d %d %d\\n", *tpidp, *sigp, ret); - args_pid.delete(&pid); - args_sig.delete(&pid); + bpf_trace_printk("%d %d %d\\n", *tpidp, *sigp, ret); + args_pid.delete(&pid); + args_sig.delete(&pid); - return 0; + return 0; } """ if args.pid: - bpf_text = bpf_text.replace('FILTER', - 'if (pid != %s) { return 0; }' % args.pid) + bpf_text = bpf_text.replace('FILTER', + 'if (pid != %s) { return 0; }' % args.pid) else: - bpf_text = bpf_text.replace('FILTER', '') + bpf_text = bpf_text.replace('FILTER', '') if debug: - print(bpf_text) + print(bpf_text) # initialize BPF b = BPF(text=bpf_text) # header if args.timestamp: - print("%-14s" % ("TIME(s)"), end="") + print("%-14s" % ("TIME(s)"), end="") print("%-6s %-16s %-4s %-6s %s" % ("PID", "COMM", "SIG", "TPID", "RESULT")) start_ts = 0 # format output while 1: - (task, pid, cpu, flags, ts, msg) = b.trace_fields() - (tpid_s, sig_s, ret_s) = msg.split(" ") - - ret = int(ret_s) - if (args.failed and (ret >= 0)): - continue - - # print columns - if args.timestamp: - if start_ts == 0: - start_ts = ts - print("%-14.9f" % (ts - start_ts), end="") - print("%-6d %-16s %-4s %-6s %s" % (pid, task, sig_s, tpid_s, ret_s)) + (task, pid, cpu, flags, ts, msg) = b.trace_fields() + (tpid_s, sig_s, ret_s) = msg.split(" ") + + ret = int(ret_s) + if (args.failed and (ret >= 0)): + continue + + # print columns + if args.timestamp: + if start_ts == 0: + start_ts = ts + print("%-14.9f" % (ts - start_ts), end="") + print("%-6d %-16s %-4s %-6s %s" % (pid, task, sig_s, tpid_s, ret_s)) diff --git a/tools/killsnoop_example.txt b/tools/killsnoop_example.txt index f80dc77..f968f79 100644 --- a/tools/killsnoop_example.txt +++ b/tools/killsnoop_example.txt @@ -3,7 +3,7 @@ Demonstrations of killsnoop, the Linux eBPF/bcc version. This traces signals sent via the kill() syscall. For example: -# ./killsnoop +# ./killsnoop PID COMM SIG TPID RESULT 17064 bash 9 27682 0 17064 bash 9 27682 -3 diff --git a/tools/opensnoop b/tools/opensnoop index 3746b35..83a9a7b 100755 --- a/tools/opensnoop +++ b/tools/opensnoop @@ -1,14 +1,15 @@ #!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports # -# opensnoop Trace open() syscalls. -# For Linux, uses BCC, eBPF. Embedded C. +# opensnoop Trace open() syscalls. +# For Linux, uses BCC, eBPF. Embedded C. # # USAGE: opensnoop [-h] [-t] [-x] [-p PID] # # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 17-Sep-2015 Brendan Gregg Created this. +# 17-Sep-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF @@ -22,15 +23,15 @@ examples = """examples: ./opensnoop -p 181 # only trace PID 181 """ parser = argparse.ArgumentParser( - description="Trace open() syscalls", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=examples) + description="Trace open() syscalls", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=examples) parser.add_argument("-t", "--timestamp", action="store_true", - help="include timestamp on output") + help="include timestamp on output") parser.add_argument("-x", "--failed", action="store_true", - help="only show failed opens") + help="only show failed opens") parser.add_argument("-p", "--pid", - help="trace this PID only") + help="trace this PID only") args = parser.parse_args() debug = 0 @@ -42,68 +43,70 @@ BPF_HASH(args_filename, u32, const char *); int kprobe__sys_open(struct pt_regs *ctx, const char __user *filename) { - u32 pid = bpf_get_current_pid_tgid(); + u32 pid = bpf_get_current_pid_tgid(); - FILTER - args_filename.update(&pid, &filename); + FILTER + args_filename.update(&pid, &filename); - return 0; + return 0; }; int kretprobe__sys_open(struct pt_regs *ctx) { - const char **filenamep; - int ret = ctx->ax; - u32 pid = bpf_get_current_pid_tgid(); + const char **filenamep; + int ret = ctx->ax; + u32 pid = bpf_get_current_pid_tgid(); - filenamep = args_filename.lookup(&pid); - if (filenamep == 0) { - // missed entry - return 0; - } + filenamep = args_filename.lookup(&pid); + if (filenamep == 0) { + // missed entry + return 0; + } - bpf_trace_printk("%s %d\\n", *filenamep, ret); - args_filename.delete(&pid); + bpf_trace_printk("%s %d\\n", *filenamep, ret); + args_filename.delete(&pid); - return 0; + return 0; } """ if args.pid: - bpf_text = bpf_text.replace('FILTER', - 'if (pid != %s) { return 0; }' % args.pid) + bpf_text = bpf_text.replace('FILTER', + 'if (pid != %s) { return 0; }' % args.pid) else: - bpf_text = bpf_text.replace('FILTER', '') + bpf_text = bpf_text.replace('FILTER', '') if debug: - print(bpf_text) + print(bpf_text) # initialize BPF b = BPF(text=bpf_text) # header if args.timestamp: - print("%-14s" % ("TIME(s)"), end="") + print("%-14s" % ("TIME(s)"), end="") print("%-6s %-16s %4s %3s %s" % ("PID", "COMM", "FD", "ERR", "PATH")) start_ts = 0 # format output while 1: - (task, pid, cpu, flags, ts, msg) = b.trace_fields() - (filename, ret_s) = msg.split(" ") - - ret = int(ret_s) - if (args.failed and (ret >= 0)): - continue - - # split return value into FD and errno columns - if ret >= 0: - fd_s = ret; err = 0 - else: - fd_s = "-1"; err = - ret - - # print columns - if args.timestamp: - if start_ts == 0: - start_ts = ts - print("%-14.9f" % (ts - start_ts), end="") - print("%-6d %-16s %4s %3s %s" % (pid, task, fd_s, err, filename)) + (task, pid, cpu, flags, ts, msg) = b.trace_fields() + (filename, ret_s) = msg.split(" ") + + ret = int(ret_s) + if (args.failed and (ret >= 0)): + continue + + # split return value into FD and errno columns + if ret >= 0: + fd_s = ret + err = 0 + else: + fd_s = "-1" + err = - ret + + # print columns + if args.timestamp: + if start_ts == 0: + start_ts = ts + print("%-14.9f" % (ts - start_ts), end="") + print("%-6d %-16s %4s %3s %s" % (pid, task, fd_s, err, filename)) diff --git a/tools/opensnoop_example.txt b/tools/opensnoop_example.txt index 5a0c782..d84f16a 100644 --- a/tools/opensnoop_example.txt +++ b/tools/opensnoop_example.txt @@ -5,38 +5,38 @@ opensnoop traces the open() syscall system-wide, and prints various details. Example output: # ./opensnoop -PID COMM FD ERR PATH -17326 <...> 7 0 /sys/kernel/debug/tracing/trace_pipe -1576 snmpd 9 0 /proc/net/dev -1576 snmpd 11 0 /proc/net/if_inet6 -1576 snmpd 11 0 /proc/sys/net/ipv4/neigh/eth0/retrans_time_ms -1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/eth0/retrans_time_ms -1576 snmpd 11 0 /proc/sys/net/ipv6/conf/eth0/forwarding -1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/eth0/base_reachable_time_ms -1576 snmpd 11 0 /proc/sys/net/ipv4/neigh/lo/retrans_time_ms -1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/lo/retrans_time_ms -1576 snmpd 11 0 /proc/sys/net/ipv6/conf/lo/forwarding -1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/lo/base_reachable_time_ms -1576 snmpd 9 0 /proc/diskstats -1576 snmpd 9 0 /proc/stat -1576 snmpd 9 0 /proc/vmstat -1956 supervise 9 0 supervise/status.new -1956 supervise 9 0 supervise/status.new -17358 run 3 0 /etc/ld.so.cache -17358 run 3 0 /lib/x86_64-linux-gnu/libtinfo.so.5 -17358 run 3 0 /lib/x86_64-linux-gnu/libdl.so.2 -17358 run 3 0 /lib/x86_64-linux-gnu/libc.so.6 -17358 run -1 6 /dev/tty -17358 run 3 0 /proc/meminfo -17358 run 3 0 /etc/nsswitch.conf -17358 run 3 0 /etc/ld.so.cache -17358 run 3 0 /lib/x86_64-linux-gnu/libnss_compat.so.2 -17358 run 3 0 /lib/x86_64-linux-gnu/libnsl.so.1 -17358 run 3 0 /etc/ld.so.cache -17358 run 3 0 /lib/x86_64-linux-gnu/libnss_nis.so.2 -17358 run 3 0 /lib/x86_64-linux-gnu/libnss_files.so.2 -17358 run 3 0 /etc/passwd -17358 run 3 0 ./run +PID COMM FD ERR PATH +17326 <...> 7 0 /sys/kernel/debug/tracing/trace_pipe +1576 snmpd 9 0 /proc/net/dev +1576 snmpd 11 0 /proc/net/if_inet6 +1576 snmpd 11 0 /proc/sys/net/ipv4/neigh/eth0/retrans_time_ms +1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/eth0/retrans_time_ms +1576 snmpd 11 0 /proc/sys/net/ipv6/conf/eth0/forwarding +1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/eth0/base_reachable_time_ms +1576 snmpd 11 0 /proc/sys/net/ipv4/neigh/lo/retrans_time_ms +1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/lo/retrans_time_ms +1576 snmpd 11 0 /proc/sys/net/ipv6/conf/lo/forwarding +1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/lo/base_reachable_time_ms +1576 snmpd 9 0 /proc/diskstats +1576 snmpd 9 0 /proc/stat +1576 snmpd 9 0 /proc/vmstat +1956 supervise 9 0 supervise/status.new +1956 supervise 9 0 supervise/status.new +17358 run 3 0 /etc/ld.so.cache +17358 run 3 0 /lib/x86_64-linux-gnu/libtinfo.so.5 +17358 run 3 0 /lib/x86_64-linux-gnu/libdl.so.2 +17358 run 3 0 /lib/x86_64-linux-gnu/libc.so.6 +17358 run -1 6 /dev/tty +17358 run 3 0 /proc/meminfo +17358 run 3 0 /etc/nsswitch.conf +17358 run 3 0 /etc/ld.so.cache +17358 run 3 0 /lib/x86_64-linux-gnu/libnss_compat.so.2 +17358 run 3 0 /lib/x86_64-linux-gnu/libnsl.so.1 +17358 run 3 0 /etc/ld.so.cache +17358 run 3 0 /lib/x86_64-linux-gnu/libnss_nis.so.2 +17358 run 3 0 /lib/x86_64-linux-gnu/libnss_files.so.2 +17358 run 3 0 /etc/passwd +17358 run 3 0 ./run ^C While tracing, the snmpd process opened various /proc files (reading metrics), @@ -68,25 +68,19 @@ second. The -x option only prints failed opens: # ./opensnoop -x -PID COMM FD ERR PATH -18372 run -1 6 /dev/tty -18373 run -1 6 /dev/tty -18373 multilog -1 13 lock -18372 multilog -1 13 lock -18384 df -1 2 /usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo -18384 df -1 2 /usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo -18384 df -1 2 /usr/share/locale/en_US/LC_MESSAGES/coreutils.mo -18384 df -1 2 /usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo -18384 df -1 2 /usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo -18384 df -1 2 /usr/share/locale/en/LC_MESSAGES/coreutils.mo -18384 df -1 2 /usr/share/locale-langpack/en_US.UTF-8/LC_MESSAGES/coreutils.mo -18384 df -1 2 /usr/share/locale-langpack/en_US.utf8/LC_MESSAGES/coreutils.mo -18384 df -1 2 /usr/share/locale-langpack/en_US/LC_MESSAGES/coreutils.mo -18384 df -1 2 /usr/share/locale-langpack/en.UTF-8/LC_MESSAGES/coreutils.mo -18384 df -1 2 /usr/share/locale-langpack/en.utf8/LC_MESSAGES/coreutils.mo -18384 df -1 2 /usr/share/locale-langpack/en/LC_MESSAGES/coreutils.mo -18385 run -1 6 /dev/tty -18386 run -1 6 /dev/tty +PID COMM FD ERR PATH +18372 run -1 6 /dev/tty +18373 run -1 6 /dev/tty +18373 multilog -1 13 lock +18372 multilog -1 13 lock +18384 df -1 2 /usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo +18384 df -1 2 /usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo +18384 df -1 2 /usr/share/locale/en_US/LC_MESSAGES/coreutils.mo +18384 df -1 2 /usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo +18384 df -1 2 /usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo +18384 df -1 2 /usr/share/locale/en/LC_MESSAGES/coreutils.mo +18385 run -1 6 /dev/tty +18386 run -1 6 /dev/tty This caught a df command failing to open a coreutils.mo file, and trying from different directories. diff --git a/tools/pidpersec b/tools/pidpersec index 7e23fbb..879c875 100755 --- a/tools/pidpersec +++ b/tools/pidpersec @@ -1,8 +1,8 @@ #!/usr/bin/python -# vim: ts=8 noet sw=8 +# @lint-avoid-python-3-compatibility-imports # -# pidpersec Count new processes (via fork). -# For Linux, uses BCC, eBPF. See .c file. +# pidpersec Count new processes (via fork). +# For Linux, uses BCC, eBPF. See .c file. # # USAGE: pidpersec # @@ -11,14 +11,14 @@ # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 11-Aug-2015 Brendan Gregg Created this. +# 11-Aug-2015 Brendan Gregg Created this. from bcc import BPF -from ctypes import c_ushort, c_int, c_ulonglong +from ctypes import c_int from time import sleep, strftime # load BPF program -b = BPF(src_file = "pidpersec.c") +b = BPF(src_file="pidpersec.c") b.attach_kprobe(event="sched_fork", fn_name="do_count") # stat indexes @@ -29,11 +29,11 @@ print("Tracing... Ctrl-C to end.") # output while (1): - try: - sleep(1) - except KeyboardInterrupt: - exit() + try: + sleep(1) + except KeyboardInterrupt: + exit() - print("%s: PIDs/sec: %d" % (strftime("%H:%M:%S"), - b["stats"][S_COUNT].value)) - b["stats"].clear() + print("%s: PIDs/sec: %d" % (strftime("%H:%M:%S"), + b["stats"][S_COUNT].value)) + b["stats"].clear() diff --git a/tools/softirqs b/tools/softirqs index b3c2f3b..40545b3 100755 --- a/tools/softirqs +++ b/tools/softirqs @@ -1,14 +1,15 @@ #!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports # -# softirqs Summarize soft IRQ (interrupt) event time. -# For Linux, uses BCC, eBPF. +# softirqs Summarize soft IRQ (interrupt) event time. +# For Linux, uses BCC, eBPF. # # USAGE: softirqs [-h] [-T] [-N] [-d] [interval] [count] # # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 20-Oct-2015 Brendan Gregg Created this. +# 20-Oct-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF @@ -23,27 +24,27 @@ examples = """examples: ./softirqs -NT 1 # 1s summaries, nanoseconds, and timestamps """ parser = argparse.ArgumentParser( - description="Summarize soft irq event time as histograms", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=examples) + description="Summarize soft irq event time as histograms", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=examples) parser.add_argument("-T", "--timestamp", action="store_true", - help="include timestamp on output") + help="include timestamp on output") parser.add_argument("-N", "--nanoseconds", action="store_true", - help="output in nanoseconds") + help="output in nanoseconds") parser.add_argument("-d", "--dist", action="store_true", - help="show distributions as histograms") + help="show distributions as histograms") parser.add_argument("interval", nargs="?", default=99999999, - help="output interval, in seconds") + help="output interval, in seconds") parser.add_argument("count", nargs="?", default=99999999, - help="number of outputs") + help="number of outputs") args = parser.parse_args() countdown = int(args.count) if args.nanoseconds: - factor = 1 - label = "nsecs" + factor = 1 + label = "nsecs" else: - factor = 1000 - label = "usecs" + factor = 1000 + label = "usecs" debug = 0 ### define BPF program @@ -51,8 +52,8 @@ bpf_text = """ #include typedef struct irq_key { - u64 ip; - u64 slot; + u64 ip; + u64 slot; } irq_key_t; BPF_HASH(start, u32); BPF_HASH(iptr, u32); @@ -61,48 +62,48 @@ BPF_HISTOGRAM(dist, irq_key_t); // time IRQ int trace_start(struct pt_regs *ctx) { - u32 pid = bpf_get_current_pid_tgid(); - u64 ip = ctx->ip, ts = bpf_ktime_get_ns(); - start.update(&pid, &ts); - iptr.update(&pid, &ip); - return 0; + u32 pid = bpf_get_current_pid_tgid(); + u64 ip = ctx->ip, ts = bpf_ktime_get_ns(); + start.update(&pid, &ts); + iptr.update(&pid, &ip); + return 0; } int trace_completion(struct pt_regs *ctx) { - u64 *tsp, delta, ip, *ipp; - u32 pid = bpf_get_current_pid_tgid(); - - // fetch timestamp and calculate delta - tsp = start.lookup(&pid); - ipp = iptr.lookup(&pid); - if (tsp == 0 || ipp == 0) { - return 0; // missed start - } - delta = bpf_ktime_get_ns() - *tsp; - ip = *ipp; - - // store as sum or histogram - STORE - - start.delete(&pid); - iptr.delete(&pid); - return 0; + u64 *tsp, delta, ip, *ipp; + u32 pid = bpf_get_current_pid_tgid(); + + // fetch timestamp and calculate delta + tsp = start.lookup(&pid); + ipp = iptr.lookup(&pid); + if (tsp == 0 || ipp == 0) { + return 0; // missed start + } + delta = bpf_ktime_get_ns() - *tsp; + ip = *ipp; + + // store as sum or histogram + STORE + + start.delete(&pid); + iptr.delete(&pid); + return 0; } """ ### code substitutions if args.dist: - bpf_text = bpf_text.replace('STORE', - 'irq_key_t key = {.ip = ip, .slot = bpf_log2l(delta)};' + - 'dist.increment(key);') + bpf_text = bpf_text.replace('STORE', + 'irq_key_t key = {.ip = ip, .slot = bpf_log2l(delta)};' + + 'dist.increment(key);') else: - bpf_text = bpf_text.replace('STORE', - 'irq_key_t key = {.ip = ip, .slot = 0 /* ignore */};' + - 'u64 zero = 0, *vp = dist.lookup_or_init(&key, &zero);' + - '(*vp) += delta;') + bpf_text = bpf_text.replace('STORE', + 'irq_key_t key = {.ip = ip, .slot = 0 /* ignore */};' + + 'u64 zero = 0, *vp = dist.lookup_or_init(&key, &zero);' + + '(*vp) += delta;') if debug: - print(bpf_text) + print(bpf_text) ### load BPF program b = BPF(text=bpf_text) @@ -114,8 +115,8 @@ for softirqfunc in ("blk_iopoll_softirq", "blk_done_softirq", "rcu_process_callbacks", "run_rebalance_domains", "tasklet_action", "tasklet_hi_action", "run_timer_softirq", "net_tx_action", "net_rx_action"): - b.attach_kprobe(event=softirqfunc, fn_name="trace_start") - b.attach_kretprobe(event=softirqfunc, fn_name="trace_completion") + b.attach_kprobe(event=softirqfunc, fn_name="trace_start") + b.attach_kretprobe(event=softirqfunc, fn_name="trace_completion") print("Tracing soft irq event time... Hit Ctrl-C to end.") @@ -123,23 +124,23 @@ print("Tracing soft irq event time... Hit Ctrl-C to end.") exiting = 0 if args.interval else 1 dist = b.get_table("dist") while (1): - try: - sleep(int(args.interval)) - except KeyboardInterrupt: - exiting=1 - - print() - if args.timestamp: - print("%-8s\n" % strftime("%H:%M:%S"), end="") - - if args.dist: - dist.print_log2_hist(label, "softirq", section_print_fn=b.ksym) - else: - print("%-26s %11s" % ("SOFTIRQ", "TOTAL_" + label)) - for k, v in sorted(dist.items(), key=lambda dist: dist[1].value): - print("%-26s %11d" % (b.ksym(k.ip), v.value / factor)) - dist.clear() - - countdown -= 1 - if exiting or countdown == 0: - exit() + try: + sleep(int(args.interval)) + except KeyboardInterrupt: + exiting = 1 + + print() + if args.timestamp: + print("%-8s\n" % strftime("%H:%M:%S"), end="") + + if args.dist: + dist.print_log2_hist(label, "softirq", section_print_fn=b.ksym) + else: + print("%-26s %11s" % ("SOFTIRQ", "TOTAL_" + label)) + for k, v in sorted(dist.items(), key=lambda dist: dist[1].value): + print("%-26s %11d" % (b.ksym(k.ip), v.value / factor)) + dist.clear() + + countdown -= 1 + if exiting or countdown == 0: + exit() diff --git a/tools/softirqs_example.txt b/tools/softirqs_example.txt index be6ee2d..c759c76 100644 --- a/tools/softirqs_example.txt +++ b/tools/softirqs_example.txt @@ -4,7 +4,7 @@ Demonstrations of softirqs, the Linux eBPF/bcc version. This program traces soft interrupts (irqs), and stores timing statistics in-kernel for efficiency. For example: -# ./softirqs +# ./softirqs Tracing soft irq event time... Hit Ctrl-C to end. ^C SOFTIRQ TOTAL_usecs diff --git a/tools/syncsnoop b/tools/syncsnoop index dd4148d..cae57ea 100755 --- a/tools/syncsnoop +++ b/tools/syncsnoop @@ -1,7 +1,8 @@ #!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports # -# syncsnoop Trace sync() syscall. -# For Linux, uses BCC, eBPF. Embedded C. +# syncsnoop Trace sync() syscall. +# For Linux, uses BCC, eBPF. Embedded C. # # Written as a basic example of BCC trace & reformat. See # examples/hello_world.py for a BCC trace with default output example. @@ -9,15 +10,15 @@ # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 13-Aug-2015 Brendan Gregg Created this. +# 13-Aug-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF # load BPF program -b = BPF(text = """ +b = BPF(text=""" void kprobe__sys_sync(void *ctx) { - bpf_trace_printk("sync()\\n"); + bpf_trace_printk("sync()\\n"); }; """) @@ -26,5 +27,5 @@ print("%-18s %s" % ("TIME(s)", "CALL")) # format output while 1: - (task, pid, cpu, flags, ts, msg) = b.trace_fields() - print("%-18.9f %s" % (ts, msg)) + (task, pid, cpu, flags, ts, msg) = b.trace_fields() + print("%-18.9f %s" % (ts, msg)) diff --git a/tools/syncsnoop_example.txt b/tools/syncsnoop_example.txt index 56cc21e..4425c5b 100644 --- a/tools/syncsnoop_example.txt +++ b/tools/syncsnoop_example.txt @@ -3,7 +3,7 @@ Demonstrations of syncsnoop, the Linux eBPF/bcc version. This program traces calls to the kernel sync() routine, with basic timestamps: -# ./syncsnoop +# ./syncsnoop TIME(s) CALL 16458148.611952 sync() 16458151.533709 sync() diff --git a/tools/tcpaccept b/tools/tcpaccept index 7e58bb5..2fda8a7 100755 --- a/tools/tcpaccept +++ b/tools/tcpaccept @@ -1,7 +1,8 @@ #!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports # -# tcpaccept Trace TCP accept()s. -# For Linux, uses BCC, eBPF. Embedded C. +# tcpaccept Trace TCP accept()s. +# For Linux, uses BCC, eBPF. Embedded C. # # USAGE: tcpaccept [-h] [-t] [-p PID] # @@ -15,7 +16,7 @@ # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 13-Oct-2015 Brendan Gregg Created this. +# 13-Oct-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF @@ -28,13 +29,13 @@ examples = """examples: ./tcpaccept -p 181 # only trace PID 181 """ parser = argparse.ArgumentParser( - description="Trace TCP accepts", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=examples) + description="Trace TCP accepts", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=examples) parser.add_argument("-t", "--timestamp", action="store_true", - help="include timestamp on output") + help="include timestamp on output") parser.add_argument("-p", "--pid", - help="trace this PID only") + help="trace this PID only") args = parser.parse_args() debug = 0 @@ -46,88 +47,88 @@ bpf_text = """ int kretprobe__inet_csk_accept(struct pt_regs *ctx) { - struct sock *newsk = (struct sock *)ctx->ax; - u32 pid = bpf_get_current_pid_tgid(); - - if (newsk == NULL) - return 0; - - // check this is TCP - u8 protocol = 0; - // workaround for reading the sk_protocol bitfield: - bpf_probe_read(&protocol, 1, (void *)((long)&newsk->sk_wmem_queued) - 3); - if (protocol != IPPROTO_TCP) - return 0; - - // pull in details - u16 family = 0, lport = 0; - u32 saddr = 0, daddr = 0; - bpf_probe_read(&family, sizeof(family), &newsk->__sk_common.skc_family); - bpf_probe_read(&lport, sizeof(lport), &newsk->__sk_common.skc_num); - if (family == AF_INET) { - bpf_probe_read(&saddr, sizeof(saddr), - &newsk->__sk_common.skc_rcv_saddr); - bpf_probe_read(&daddr, sizeof(daddr), - &newsk->__sk_common.skc_daddr); - - // output - bpf_trace_printk("4 %x %x %d\\n", daddr, saddr, lport); - } else if (family == AF_INET6) { - // just grab the last 4 bytes for now - bpf_probe_read(&saddr, sizeof(saddr), - &newsk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[3]); - bpf_probe_read(&daddr, sizeof(daddr), - &newsk->__sk_common.skc_v6_daddr.in6_u.u6_addr32[3]); - - // output and flip byte order of addresses - bpf_trace_printk("6 %x %x %d\\n", bpf_ntohl(daddr), - bpf_ntohl(saddr), lport); - } - // else drop - - return 0; + struct sock *newsk = (struct sock *)ctx->ax; + u32 pid = bpf_get_current_pid_tgid(); + + if (newsk == NULL) + return 0; + + // check this is TCP + u8 protocol = 0; + // workaround for reading the sk_protocol bitfield: + bpf_probe_read(&protocol, 1, (void *)((long)&newsk->sk_wmem_queued) - 3); + if (protocol != IPPROTO_TCP) + return 0; + + // pull in details + u16 family = 0, lport = 0; + u32 saddr = 0, daddr = 0; + bpf_probe_read(&family, sizeof(family), &newsk->__sk_common.skc_family); + bpf_probe_read(&lport, sizeof(lport), &newsk->__sk_common.skc_num); + if (family == AF_INET) { + bpf_probe_read(&saddr, sizeof(saddr), + &newsk->__sk_common.skc_rcv_saddr); + bpf_probe_read(&daddr, sizeof(daddr), + &newsk->__sk_common.skc_daddr); + + // output + bpf_trace_printk("4 %x %x %d\\n", daddr, saddr, lport); + } else if (family == AF_INET6) { + // just grab the last 4 bytes for now + bpf_probe_read(&saddr, sizeof(saddr), + &newsk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[3]); + bpf_probe_read(&daddr, sizeof(daddr), + &newsk->__sk_common.skc_v6_daddr.in6_u.u6_addr32[3]); + + // output and flip byte order of addresses + bpf_trace_printk("6 %x %x %d\\n", bpf_ntohl(daddr), + bpf_ntohl(saddr), lport); + } + // else drop + + return 0; } """ # code substitutions if args.pid: - bpf_text = bpf_text.replace('FILTER', - 'if (pid != %s) { return 0; }' % args.pid) + bpf_text = bpf_text.replace('FILTER', + 'if (pid != %s) { return 0; }' % args.pid) else: - bpf_text = bpf_text.replace('FILTER', '') + bpf_text = bpf_text.replace('FILTER', '') if debug: - print(bpf_text) + print(bpf_text) # initialize BPF b = BPF(text=bpf_text) # header if args.timestamp: - print("%-9s" % ("TIME(s)"), end="") + print("%-9s" % ("TIME(s)"), end="") print("%-6s %-12s %-2s %-16s %-16s %-4s" % ("PID", "COMM", "IP", "RADDR", "LADDR", "LPORT")) start_ts = 0 def inet_ntoa(addr): - dq = '' - for i in range(0, 4): - dq = dq + str(addr & 0xff) - if (i != 3): - dq = dq + '.' - addr = addr >> 8 - return dq + dq = '' + for i in range(0, 4): + dq = dq + str(addr & 0xff) + if (i != 3): + dq = dq + '.' + addr = addr >> 8 + return dq # format output while 1: - (task, pid, cpu, flags, ts, msg) = b.trace_fields() - (ip_s, raddr_hs, laddr_hs, lport_s) = msg.split(" ") - - if args.timestamp: - if start_ts == 0: - start_ts = ts - print("%-9.3f" % (ts - start_ts), end="") - print("%-6d %-12.12s %-2s %-16s %-16s %-4s" % (pid, task, ip_s, - inet_ntoa(int(raddr_hs, 16)) if ip_s == "4" else "..." + raddr_hs, - inet_ntoa(int(laddr_hs, 16)) if ip_s == "4" else "..." + laddr_hs, - lport_s)) + (task, pid, cpu, flags, ts, msg) = b.trace_fields() + (ip_s, raddr_hs, laddr_hs, lport_s) = msg.split(" ") + + if args.timestamp: + if start_ts == 0: + start_ts = ts + print("%-9.3f" % (ts - start_ts), end="") + print("%-6d %-12.12s %-2s %-16s %-16s %-4s" % (pid, task, ip_s, + inet_ntoa(int(raddr_hs, 16)) if ip_s == "4" else "..." + raddr_hs, + inet_ntoa(int(laddr_hs, 16)) if ip_s == "4" else "..." + laddr_hs, + lport_s)) diff --git a/tools/tcpaccept_example.txt b/tools/tcpaccept_example.txt index 494de1d..04cdc67 100644 --- a/tools/tcpaccept_example.txt +++ b/tools/tcpaccept_example.txt @@ -7,8 +7,8 @@ addresses changed to protect the innocent): # ./tcpaccept PID COMM IP RADDR LADDR LPORT -907 sshd 4 192.168.56.1 192.168.56.102 22 -907 sshd 4 127.0.0.1 127.0.0.1 22 +907 sshd 4 192.168.56.1 192.168.56.102 22 +907 sshd 4 127.0.0.1 127.0.0.1 22 5389 perl 6 ...fec0ae21 ...fec0ae21 7001 This output shows three connections, two to PID 907, an "sshd" process listening @@ -30,9 +30,9 @@ The -t option prints a timestamp column: # ./tcpaccept -t TIME(s) PID COMM IP RADDR LADDR LPORT -0.000 907 sshd 4 127.0.0.1 127.0.0.1 22 -0.992 907 sshd 4 127.0.0.1 127.0.0.1 22 -1.984 907 sshd 4 127.0.0.1 127.0.0.1 22 +0.000 907 sshd 4 127.0.0.1 127.0.0.1 22 +0.992 907 sshd 4 127.0.0.1 127.0.0.1 22 +1.984 907 sshd 4 127.0.0.1 127.0.0.1 22 USAGE message: diff --git a/tools/tcpconnect b/tools/tcpconnect index 9277095..2fb5307 100755 --- a/tools/tcpconnect +++ b/tools/tcpconnect @@ -1,7 +1,8 @@ #!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports # -# tcpconnect Trace TCP connect()s. -# For Linux, uses BCC, eBPF. Embedded C. +# tcpconnect Trace TCP connect()s. +# For Linux, uses BCC, eBPF. Embedded C. # # USAGE: tcpconnect [-h] [-t] [-p PID] # @@ -10,7 +11,7 @@ # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 25-Sep-2015 Brendan Gregg Created this. +# 25-Sep-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF @@ -23,13 +24,13 @@ examples = """examples: ./tcpconnect -p 181 # only trace PID 181 """ parser = argparse.ArgumentParser( - description="Trace TCP connects", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=examples) + description="Trace TCP connects", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=examples) parser.add_argument("-t", "--timestamp", action="store_true", - help="include timestamp on output") + help="include timestamp on output") parser.add_argument("-p", "--pid", - help="trace this PID only") + help="trace this PID only") args = parser.parse_args() debug = 0 @@ -43,82 +44,82 @@ BPF_HASH(currsock, u32, struct sock *); int trace_connect_entry(struct pt_regs *ctx, struct sock *sk) { - u32 pid = bpf_get_current_pid_tgid(); - FILTER + u32 pid = bpf_get_current_pid_tgid(); + FILTER - // stash the sock ptr for lookup on return - currsock.update(&pid, &sk); + // stash the sock ptr for lookup on return + currsock.update(&pid, &sk); - return 0; + return 0; }; static int trace_connect_return(struct pt_regs *ctx, short ipver) { - int ret = ctx->ax; - u32 pid = bpf_get_current_pid_tgid(); - - struct sock **skpp; - skpp = currsock.lookup(&pid); - if (skpp == 0) { - return 0; // missed entry - } - - if (ret != 0) { - // failed to send SYNC packet, may not have populated - // socket __sk_common.{skc_rcv_saddr, ...} - currsock.delete(&pid); - return 0; - } - - // pull in details - struct sock *skp = *skpp; - u32 saddr = 0, daddr = 0; - u16 dport = 0; - bpf_probe_read(&dport, sizeof(dport), &skp->__sk_common.skc_dport); - if (ipver == 4) { - bpf_probe_read(&saddr, sizeof(saddr), - &skp->__sk_common.skc_rcv_saddr); - bpf_probe_read(&daddr, sizeof(daddr), - &skp->__sk_common.skc_daddr); - - // output - bpf_trace_printk("4 %x %x %d\\n", saddr, daddr, ntohs(dport)); - } else /* 6 */ { - // just grab the last 4 bytes for now - bpf_probe_read(&saddr, sizeof(saddr), - &skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[3]); - bpf_probe_read(&daddr, sizeof(daddr), - &skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32[3]); - - // output and flip byte order of addresses - bpf_trace_printk("6 %x %x %d\\n", bpf_ntohl(saddr), - bpf_ntohl(daddr), ntohs(dport)); - } - - currsock.delete(&pid); - - return 0; + int ret = ctx->ax; + u32 pid = bpf_get_current_pid_tgid(); + + struct sock **skpp; + skpp = currsock.lookup(&pid); + if (skpp == 0) { + return 0; // missed entry + } + + if (ret != 0) { + // failed to send SYNC packet, may not have populated + // socket __sk_common.{skc_rcv_saddr, ...} + currsock.delete(&pid); + return 0; + } + + // pull in details + struct sock *skp = *skpp; + u32 saddr = 0, daddr = 0; + u16 dport = 0; + bpf_probe_read(&dport, sizeof(dport), &skp->__sk_common.skc_dport); + if (ipver == 4) { + bpf_probe_read(&saddr, sizeof(saddr), + &skp->__sk_common.skc_rcv_saddr); + bpf_probe_read(&daddr, sizeof(daddr), + &skp->__sk_common.skc_daddr); + + // output + bpf_trace_printk("4 %x %x %d\\n", saddr, daddr, ntohs(dport)); + } else /* 6 */ { + // just grab the last 4 bytes for now + bpf_probe_read(&saddr, sizeof(saddr), + &skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[3]); + bpf_probe_read(&daddr, sizeof(daddr), + &skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32[3]); + + // output and flip byte order of addresses + bpf_trace_printk("6 %x %x %d\\n", bpf_ntohl(saddr), + bpf_ntohl(daddr), ntohs(dport)); + } + + currsock.delete(&pid); + + return 0; } int trace_connect_v4_return(struct pt_regs *ctx) { - return trace_connect_return(ctx, 4); + return trace_connect_return(ctx, 4); } int trace_connect_v6_return(struct pt_regs *ctx) { - return trace_connect_return(ctx, 6); + return trace_connect_return(ctx, 6); } """ # code substitutions if args.pid: - bpf_text = bpf_text.replace('FILTER', - 'if (pid != %s) { return 0; }' % args.pid) + bpf_text = bpf_text.replace('FILTER', + 'if (pid != %s) { return 0; }' % args.pid) else: - bpf_text = bpf_text.replace('FILTER', '') + bpf_text = bpf_text.replace('FILTER', '') if debug: - print(bpf_text) + print(bpf_text) # initialize BPF b = BPF(text=bpf_text) @@ -129,31 +130,31 @@ b.attach_kretprobe(event="tcp_v6_connect", fn_name="trace_connect_v6_return") # header if args.timestamp: - print("%-9s" % ("TIME(s)"), end="") + print("%-9s" % ("TIME(s)"), end="") print("%-6s %-12s %-2s %-16s %-16s %-4s" % ("PID", "COMM", "IP", "SADDR", "DADDR", "DPORT")) start_ts = 0 def inet_ntoa(addr): - dq = '' - for i in range(0, 4): - dq = dq + str(addr & 0xff) - if (i != 3): - dq = dq + '.' - addr = addr >> 8 - return dq + dq = '' + for i in range(0, 4): + dq = dq + str(addr & 0xff) + if (i != 3): + dq = dq + '.' + addr = addr >> 8 + return dq # format output while 1: - (task, pid, cpu, flags, ts, msg) = b.trace_fields() - (ip_s, saddr_hs, daddr_hs, dport_s) = msg.split(" ") - - if args.timestamp: - if start_ts == 0: - start_ts = ts - print("%-9.3f" % (ts - start_ts), end="") - print("%-6d %-12.12s %-2s %-16s %-16s %-4s" % (pid, task, ip_s, - inet_ntoa(int(saddr_hs, 16)) if ip_s == "4" else "..." + saddr_hs, - inet_ntoa(int(daddr_hs, 16)) if ip_s == "4" else "..." + daddr_hs, - dport_s)) + (task, pid, cpu, flags, ts, msg) = b.trace_fields() + (ip_s, saddr_hs, daddr_hs, dport_s) = msg.split(" ") + + if args.timestamp: + if start_ts == 0: + start_ts = ts + print("%-9.3f" % (ts - start_ts), end="") + print("%-6d %-12.12s %-2s %-16s %-16s %-4s" % (pid, task, ip_s, + inet_ntoa(int(saddr_hs, 16)) if ip_s == "4" else "..." + saddr_hs, + inet_ntoa(int(daddr_hs, 16)) if ip_s == "4" else "..." + daddr_hs, + dport_s)) diff --git a/tools/tcpconnect_example.txt b/tools/tcpconnect_example.txt index 8b0410b..1089a58 100644 --- a/tools/tcpconnect_example.txt +++ b/tools/tcpconnect_example.txt @@ -5,12 +5,12 @@ This tool traces the kernel function performing active TCP connections (eg, via a connect() syscall; accept() are passive connections). Some example output (IP addresses changed to protect the innocent): -# ./tcpconnect +# ./tcpconnect PID COMM IP SADDR DADDR DPORT -1479 telnet 4 127.0.0.1 127.0.0.1 23 -1469 curl 4 10.201.219.236 54.245.105.25 80 -1469 curl 4 10.201.219.236 54.67.101.145 80 -11072 ssh 6 ...fe8203ac ...fe82abcd 22 +1479 telnet 4 127.0.0.1 127.0.0.1 23 +1469 curl 4 10.201.219.236 54.245.105.25 80 +1469 curl 4 10.201.219.236 54.67.101.145 80 +11072 ssh 6 ...fe8203ac ...fe82abcd 22 This output shows four connections, one from a "telnet" process, two from "curl", and one from "ssh". The output details shows the IP version, source diff --git a/tools/vfscount b/tools/vfscount index d669862..bc0f544 100755 --- a/tools/vfscount +++ b/tools/vfscount @@ -1,21 +1,22 @@ #!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports # -# vfscount Count VFS calls ("vfs_*"). -# For Linux, uses BCC, eBPF. See .c file. +# vfscount Count VFS calls ("vfs_*"). +# For Linux, uses BCC, eBPF. See .c file. # # Written as a basic example of counting functions. # # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 14-Aug-2015 Brendan Gregg Created this. +# 14-Aug-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF from time import sleep # load BPF program -b = BPF(src_file = "vfscount.c") +b = BPF(src_file="vfscount.c") b.attach_kprobe(event_re="^vfs_.*", fn_name="do_count") # header @@ -23,11 +24,11 @@ print("Tracing... Ctrl-C to end.") # output try: - sleep(99999999) + sleep(99999999) except KeyboardInterrupt: - pass + pass print("\n%-16s %-26s %8s" % ("ADDR", "FUNC", "COUNT")) counts = b.get_table("counts") for k, v in sorted(counts.items(), key=lambda counts: counts[1].value): - print("%-16x %-26s %8d" % (k.ip, b.ksym(k.ip), v.value)) + print("%-16x %-26s %8d" % (k.ip, b.ksym(k.ip), v.value)) diff --git a/tools/vfscount_example.txt b/tools/vfscount_example.txt index e6d1001..1012bff 100644 --- a/tools/vfscount_example.txt +++ b/tools/vfscount_example.txt @@ -3,7 +3,7 @@ Demonstrations of vfscount, the Linux eBPF/bcc version. This counts VFS calls, by tracing all kernel functions beginning with "vfs_": -# ./vfscount +# ./vfscount Tracing... Ctrl-C to end. ^C ADDR FUNC COUNT diff --git a/tools/vfsstat b/tools/vfsstat index 5925516..44119f9 100755 --- a/tools/vfsstat +++ b/tools/vfsstat @@ -1,7 +1,8 @@ #!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports # -# vfsstat Count some VFS calls. -# For Linux, uses BCC, eBPF. See .c file. +# vfsstat Count some VFS calls. +# For Linux, uses BCC, eBPF. See .c file. # # Written as a basic example of counting multiple events as a stat tool. # @@ -10,33 +11,33 @@ # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # -# 14-Aug-2015 Brendan Gregg Created this. +# 14-Aug-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF -from ctypes import c_ushort, c_int, c_ulonglong +from ctypes import c_int from time import sleep, strftime from sys import argv def usage(): - print("USAGE: %s [interval [count]]" % argv[0]) - exit() + print("USAGE: %s [interval [count]]" % argv[0]) + exit() # arguments interval = 1 count = -1 if len(argv) > 1: - try: - interval = int(argv[1]) - if interval == 0: - raise - if len(argv) > 2: - count = int(argv[2]) - except: # also catches -h, --help - usage() + try: + interval = int(argv[1]) + if interval == 0: + raise + if len(argv) > 2: + count = int(argv[2]) + except: # also catches -h, --help + usage() # load BPF program -b = BPF(src_file = "vfsstat.c") +b = BPF(src_file="vfsstat.c") b.attach_kprobe(event="vfs_read", fn_name="do_read") b.attach_kprobe(event="vfs_write", fn_name="do_write") b.attach_kprobe(event="vfs_fsync", fn_name="do_fsync") @@ -45,40 +46,41 @@ b.attach_kprobe(event="vfs_create", fn_name="do_create") # stat column labels and indexes stat_types = { - "READ" : 1, - "WRITE" : 2, - "FSYNC" : 3, - "OPEN" : 4, - "CREATE" : 5 + "READ": 1, + "WRITE": 2, + "FSYNC": 3, + "OPEN": 4, + "CREATE": 5 } # header print("%-8s " % "TIME", end="") for stype in stat_types.keys(): - print(" %8s" % (stype + "/s"), end="") - idx = stat_types[stype] + print(" %8s" % (stype + "/s"), end="") + idx = stat_types[stype] print("") # output i = 0 while (1): - if count > 0: - i += 1 - if i > count: - exit() - try: - sleep(interval) - except KeyboardInterrupt: - pass; exit() + if count > 0: + i += 1 + if i > count: + exit() + try: + sleep(interval) + except KeyboardInterrupt: + pass + exit() - print("%-8s: " % strftime("%H:%M:%S"), end="") - # print each statistic as a column - for stype in stat_types.keys(): - idx = stat_types[stype] - try: - val = b["stats"][c_int(idx)].value / interval - print(" %8d" % val, end="") - except: - print(" %8d" % 0, end="") - b["stats"].clear() - print("") + print("%-8s: " % strftime("%H:%M:%S"), end="") + # print each statistic as a column + for stype in stat_types.keys(): + idx = stat_types[stype] + try: + val = b["stats"][c_int(idx)].value / interval + print(" %8d" % val, end="") + except: + print(" %8d" % 0, end="") + b["stats"].clear() + print("") diff --git a/tools/vfsstat_example.txt b/tools/vfsstat_example.txt index 48ef514..eba0343 100644 --- a/tools/vfsstat_example.txt +++ b/tools/vfsstat_example.txt @@ -4,7 +4,7 @@ Demonstrations of vfsstat, the Linux eBPF/bcc version. This traces some common VFS calls and prints per-second summaries. By default, the output interval is one second: -# ./vfsstat +# ./vfsstat TIME READ/s WRITE/s CREATE/s OPEN/s FSYNC/s 18:35:32: 231 12 4 98 0 18:35:33: 274 13 4 106 0 -- 2.7.4