Home | History | Annotate | Download | only in old
      1 #!/usr/bin/python
      2 # @lint-avoid-python-3-compatibility-imports
      3 #
      4 # filelife    Trace the lifespan of short-lived files.
      5 #             For Linux, uses BCC, eBPF. Embedded C.
      6 #
      7 # This traces the creation and deletion of files, providing information
      8 # on who deleted the file, the file age, and the file name. The intent is to
      9 # provide information on short-lived files, for debugging or performance
     10 # analysis.
     11 #
     12 # USAGE: filelife [-h] [-p PID]
     13 #
     14 # Copyright 2016 Netflix, Inc.
     15 # Licensed under the Apache License, Version 2.0 (the "License")
     16 #
     17 # 08-Feb-2015   Brendan Gregg   Created this.
     18 
     19 from __future__ import print_function
     20 from bcc import BPF
     21 import argparse
     22 from time import strftime
     23 
     24 # arguments
     25 examples = """examples:
     26     ./filelife           # trace all stat() syscalls
     27     ./filelife -p 181    # only trace PID 181
     28 """
     29 parser = argparse.ArgumentParser(
     30     description="Trace stat() syscalls",
     31     formatter_class=argparse.RawDescriptionHelpFormatter,
     32     epilog=examples)
     33 parser.add_argument("-p", "--pid",
     34     help="trace this PID only")
     35 args = parser.parse_args()
     36 debug = 0
     37 
     38 # define BPF program
     39 bpf_text = """
     40 #include <uapi/linux/ptrace.h>
     41 #include <linux/fs.h>
     42 
     43 BPF_HASH(birth, struct dentry *);
     44 
     45 // trace file creation time
     46 int trace_create(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
     47 {
     48     u32 pid = bpf_get_current_pid_tgid();
     49     FILTER
     50 
     51     u64 ts = bpf_ktime_get_ns();
     52     birth.update(&dentry, &ts);
     53 
     54     return 0;
     55 };
     56 
     57 // trace file deletion and output details
     58 int trace_unlink(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
     59 {
     60     u32 pid = bpf_get_current_pid_tgid();
     61     FILTER
     62 
     63     u64 *tsp, delta;
     64     tsp = birth.lookup(&dentry);
     65     if (tsp == 0) {
     66         return 0;   // missed create
     67     }
     68     delta = (bpf_ktime_get_ns() - *tsp) / 1000000;
     69     birth.delete(&dentry);
     70 
     71     if (dentry->d_iname[0] == 0)
     72         return 0;
     73 
     74     bpf_trace_printk("%d %s\\n", delta, dentry->d_iname);
     75 
     76     return 0;
     77 }
     78 """
     79 if args.pid:
     80     bpf_text = bpf_text.replace('FILTER',
     81         'if (pid != %s) { return 0; }' % args.pid)
     82 else:
     83     bpf_text = bpf_text.replace('FILTER', '')
     84 if debug:
     85     print(bpf_text)
     86 
     87 # initialize BPF
     88 b = BPF(text=bpf_text)
     89 b.attach_kprobe(event="vfs_create", fn_name="trace_create")
     90 b.attach_kprobe(event="vfs_unlink", fn_name="trace_unlink")
     91 
     92 # header
     93 print("%-8s %-6s %-16s %-7s %s" % ("TIME", "PID", "COMM", "AGE(s)", "FILE"))
     94 
     95 start_ts = 0
     96 
     97 # format output
     98 while 1:
     99     (task, pid, cpu, flags, ts, msg) = b.trace_fields()
    100     (delta, filename) = msg.split(" ", 1)
    101 
    102     # print columns
    103     print("%-8s %-6d %-16s %-7.2f %s" % (strftime("%H:%M:%S"), pid, task,
    104         float(delta) / 1000, filename))
    105