diff --git a/man/man8/opensnoop.8 b/man/man8/opensnoop.8 index c30a9465c8a4..5c1767222b16 100644 --- a/man/man8/opensnoop.8 +++ b/man/man8/opensnoop.8 @@ -2,11 +2,11 @@ .SH NAME opensnoop \- Trace open() syscalls. Uses Linux eBPF/bcc. .SH SYNOPSIS -.B opensnoop [\-h] [\-t] [\-x] [\-p PID] +.B opensnoop [\-h] [\-t] [\-x] [\-p PID] [\-n name] .SH DESCRIPTION opensnoop traces the open() syscall, showing which processes are attempting to open which files. This can be useful for determining the location of config -and log files, or for troubleshooting applications that are failing, especially +and log files, or for troubleshooting applications that are failing, specially on startup. This works by tracing the kernel sys_open() function using dynamic tracing, and @@ -32,6 +32,9 @@ Only print failed opens. .TP \-p PID Trace this process ID only (filtered in-kernel). +.TP +\-n name +Only print processes where its name partially matches 'name' .SH EXAMPLES .TP Trace all open() syscalls: @@ -49,6 +52,10 @@ Trace only open() syscalls that failed: Trace PID 181 only: # .B opensnoop \-p 181 +.TP +Trace all open() syscalls from processes where its name partially matches 'ed': +# +.B opensnoop \-n ed .SH FIELDS .TP TIME(s) diff --git a/tools/opensnoop.py b/tools/opensnoop.py index 47f57133a569..f2bac4b67a41 100755 --- a/tools/opensnoop.py +++ b/tools/opensnoop.py @@ -23,6 +23,7 @@ ./opensnoop -t # include timestamps ./opensnoop -x # only show failed opens ./opensnoop -p 181 # only trace PID 181 + ./opensnoop -n main # only print process names containing "main" """ parser = argparse.ArgumentParser( description="Trace open() syscalls", @@ -34,6 +35,8 @@ help="only show failed opens") parser.add_argument("-p", "--pid", help="trace this PID only") +parser.add_argument("-n", "--name", + help="only print process names containing this name") args = parser.parse_args() debug = 0 @@ -53,7 +56,6 @@ struct data_t { u32 pid; u64 ts; - u64 delta; int ret; char comm[TASK_COMM_LEN]; char fname[NAME_MAX]; @@ -95,7 +97,6 @@ bpf_probe_read(&data.comm, sizeof(data.comm), valp->comm); bpf_probe_read(&data.fname, sizeof(data.fname), (void *)valp->fname); data.pid = valp->pid; - data.delta = tsp - valp->ts; data.ts = tsp / 1000; data.ret = PT_REGS_RC(ctx); @@ -126,15 +127,12 @@ class Data(ct.Structure): _fields_ = [ ("pid", ct.c_ulonglong), ("ts", ct.c_ulonglong), - ("delta", ct.c_ulonglong), ("ret", ct.c_int), ("comm", ct.c_char * TASK_COMM_LEN), ("fname", ct.c_char * NAME_MAX) ] -start_ts = 0 -prev_ts = 0 -delta = 0 +initial_ts = 0 # header if args.timestamp: @@ -144,10 +142,7 @@ class Data(ct.Structure): # process event def print_event(cpu, data, size): event = ct.cast(data, ct.POINTER(Data)).contents - global start_ts - global prev_ts - global delta - global cont + global initial_ts # split return value into FD and errno columns if event.ret >= 0: @@ -157,25 +152,21 @@ def print_event(cpu, data, size): fd_s = -1 err = - event.ret - if start_ts == 0: - prev_ts = start_ts + if not initial_ts: + initial_ts = event.ts - if start_ts == 1: - delta = float(delta) + (event.ts - prev_ts) + if args.failed and (event.ret >= 0): + return - if (args.failed and (event.ret >= 0)): - start_ts = 1 - prev_ts = event.ts + if args.name and args.name not in event.comm: return if args.timestamp: - print("%-14.9f" % (delta / 1000000), end="") + delta = event.ts - initial_ts + print("%-14.9f" % (float(delta) / 1000000), end="") print("%-6d %-16s %4d %3d %s" % (event.pid, event.comm, - fd_s, err, event.fname)) - - prev_ts = event.ts - start_ts = 1 + fd_s, err, event.fname)) # loop with callback to print_event b["events"].open_perf_buffer(print_event) diff --git a/tools/opensnoop_example.txt b/tools/opensnoop_example.txt index d84f16a360d5..b297e3346c2d 100644 --- a/tools/opensnoop_example.txt +++ b/tools/opensnoop_example.txt @@ -89,6 +89,37 @@ The ERR column is the system error number. Error number 2 is ENOENT: no such file or directory. +The -n option can be used to filter on process name using partial matches: + +# ./opensnoop -n ed + +PID COMM FD ERR PATH +2679 sed 3 0 /etc/ld.so.cache +2679 sed 3 0 /lib/x86_64-linux-gnu/libselinux.so.1 +2679 sed 3 0 /lib/x86_64-linux-gnu/libc.so.6 +2679 sed 3 0 /lib/x86_64-linux-gnu/libpcre.so.3 +2679 sed 3 0 /lib/x86_64-linux-gnu/libdl.so.2 +2679 sed 3 0 /lib/x86_64-linux-gnu/libpthread.so.0 +2679 sed 3 0 /proc/filesystems +2679 sed 3 0 /usr/lib/locale/locale-archive +2679 sed -1 2 +2679 sed 3 0 /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache +2679 sed 3 0 /dev/null +2680 sed 3 0 /etc/ld.so.cache +2680 sed 3 0 /lib/x86_64-linux-gnu/libselinux.so.1 +2680 sed 3 0 /lib/x86_64-linux-gnu/libc.so.6 +2680 sed 3 0 /lib/x86_64-linux-gnu/libpcre.so.3 +2680 sed 3 0 /lib/x86_64-linux-gnu/libdl.so.2 +2680 sed 3 0 /lib/x86_64-linux-gnu/libpthread.so.0 +2680 sed 3 0 /proc/filesystems +2680 sed 3 0 /usr/lib/locale/locale-archive +2680 sed -1 2 +^C + +This caught the 'sed' command because it partially matches 'ed' that's passed +to the '-n' option. + + USAGE message: # ./opensnoop -h