execsnoop port (hack) for Linux ftrace

This commit is contained in:
Brendan Gregg
2014-07-17 11:23:45 -07:00
parent f4443ee66b
commit 1dd19fe6c1
4 changed files with 260 additions and 0 deletions

View File

@@ -14,6 +14,7 @@ Using perf_events:
Using ftrace:
- [iosnoop](iosnoop): trace disk I/O with details including latency.
- [execsnoop](execsnoop): trace process exec() with command line argument details.
- kernel/[funccount](kernel/funccount): count kernel functions that match a string.
- kernel/[functrace](kernel/functrace): trace kernel functions that match a string.

View File

@@ -0,0 +1,46 @@
Demonstrations of execsnoop.
Here's execsnoop showing what's really executed by "man ls":
# ./execsnoop
TIME PID PPID ARGS
17:52:37 22406 25781 man ls
17:52:37 22413 22406 preconv -e UTF-8
17:52:37 22416 22406 pager -s
17:52:37 22415 22406 /bin/sh /usr/bin/nroff -mandoc -rLL=162n -rLT=162n -Tutf8
17:52:37 22414 22406 tbl
17:52:37 22419 22418 locale charmap
17:52:37 22420 22415 groff -mtty-char -Tutf8 -mandoc -rLL=162n -rLT=162n
17:52:37 22421 22420 troff -mtty-char -mandoc -rLL=162n -rLT=162n -Tutf8
17:52:37 22422 22420 grotty
These are short-lived processes, where the argument and PPID details are often
missed by execsnoop:
# ./execsnoop
TIME PID PPID ARGS
18:00:33 26750 1961 multilog <?>
18:00:33 26749 1972 multilog <?>
18:00:33 26749 1972 multilog <?>
18:00:33 26751 ? mkdir <?>
18:00:33 26749 1972 multilog <?>
18:00:33 26752 ? chown <?>
18:00:33 26750 1961 multilog <?>
18:00:33 26750 1961 multilog <?>
18:00:34 26753 1961 multilog <?>
18:00:34 26754 1972 multilog <?>
[...]
This will be fixed in a later version, but likely requires some kernel or
tracer changes first (fetching cmdline as the probe fires).
The previous examples were on Linux 3.14 and 3.16 kernels. Here's a 3.2 system
I'm running:
# ./execsnoop
ERROR: enabling tracepoint "sched:sched_process_exec" (tracepoint missing in this kernel version?) at ./execsnoop line 78.
This kernel version is missing the sched_process_exec probe, which is pretty
annoying.

143
execsnoop Executable file
View File

@@ -0,0 +1,143 @@
#!/usr/bin/perl
#
# execsnoop - trace process exec() with arguments.
# Written using Linux ftrace.
#
# This shows the execution of new processes, especially short-lived ones that
# can be missed by sampling tools such as top(1).
#
# USAGE: ./execsnoop [-h] [-n name]
#
# REQUIREMENTS: FTRACE CONFIG, sched:sched_process_exec tracepoint (you may
# already have these on recent kernels), and Perl.
#
# This traces exec() from the fork()->exec() sequence, which means it won't
# catch new processes that only fork(), and, it will catch processes that
# re-exec. This instruments sched:sched_process_exec without buffering, and then
# in user-space (this program) reads PPID and process arguments asynchronously
# from /proc.
#
# If the process traced is very short-lived, this program may miss reading
# arguments and PPID details. In that case, "<?>" and "?" will be printed
# respectively. This program is best-effort, and should be improved in the
# future when other kernel capabilities are made available.
#
# From perf-tools: https://github.com/brendangregg/perf-tools
#
# See the execsnoop(8) man page (in perf-tools) for more info.
#
# COPYRIGHT: Copyright (c) 2014 Brendan Gregg.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# (http://www.gnu.org/copyleft/gpl.html)
#
# 07-Jul-2014 Brendan Gregg Created this.
use strict;
use warnings;
use POSIX qw(strftime);
use Getopt::Long;
my $tracing = "/sys/kernel/debug/tracing";
my $flock = "/var/tmp/.ftrace-lock";
my $tpdir = "sched/sched_process_exec";
my $tptext = $tpdir; $tptext =~ s/\//:/;
local $SIG{INT} = \&cleanup;
local $SIG{QUIT} = \&cleanup;
local $SIG{TERM} = \&cleanup;
local $SIG{PIPE} = \&cleanup;
$| = 1;
### options
my ($name, $help);
GetOptions("name=s" => \$name,
"help" => \$help)
or usage();
usage() if $help;
sub usage {
print STDERR "USAGE: execsnoop [-h] [-n name]\n";
print STDERR " eg,\n";
print STDERR " execsnoop -n ls # show \"ls\" cmds only.\n";
exit;
}
sub ldie {
unlink $flock;
die @_;
}
sub writeto {
my ($string, $file) = @_;
open FILE, ">$file" or return 0;
print FILE $string or return 0;
close FILE or return 0;
}
### ftrace lock
if (-e $flock) {
open FLOCK, $flock; my $fpid = <FLOCK>; chomp $fpid; close FLOCK;
die "ERROR: ftrace may be in use by PID $fpid ($flock)";
}
writeto "$$", $flock or die "ERROR: unable to write $flock.";
### setup and begin tracing
chdir "$tracing" or ldie "ERROR: accessing tracing. Root? Kernel has FTRACE?";
writeto "nop", "current_tracer" or ldie "ERROR: disabling current_tracer.";
writeto "1", "events/$tpdir/enable" or ldie "ERROR: enabling tracepoint " .
"\"$tptext\" (tracepoint missing in this kernel version?)";
open TPIPE, "trace_pipe" or warn "ERROR: opening trace_pipe.";
printf "%-8s %6s %6s %s\n", "TIME", "PID", "PPID", "ARGS";
while (<TPIPE>) {
my ($taskpid, $rest) = split;
my ($task, $pid) = $taskpid =~ /(.*)-(\d+)/;
next if (defined $name and $name ne $task);
my $args = "$task <?>";
if (open CMDLINE, "/proc/$pid/cmdline") {
my $arglist = <CMDLINE>;
if (defined $arglist) {
$arglist =~ s/\000/ /g;
$args = $arglist;
}
close CMDLINE;
}
my $ppid = "?";
if (open STAT, "/proc/$pid/stat") {
my $fields = <STAT>;
if (defined $fields) {
$ppid = (split ' ', $fields)[3];
}
close STAT;
}
my $now = strftime "%H:%M:%S", localtime;
printf "%-8s %6s %6s %s\n", $now, $pid, $ppid, $args;
}
### end tracing
cleanup();
sub cleanup {
print "\nEnding tracing...\n";
close TPIPE;
writeto "0", "events/$tpdir/enable" or
ldie "ERROR: disabling \"$tptext\"";
writeto "", "trace";
unlink $flock;
exit;
}

70
man/man8/execsnoop.8 Normal file
View File

@@ -0,0 +1,70 @@
.TH execsnoop 8 "2014-07-07" "USER COMMANDS"
.SH NAME
execsnoop \- trace process exec() with arguments. Uses Linux ftrace.
.SH SYNOPSIS
.B execsnoop
[\-h] [\-n name]
.SH DESCRIPTION
execsnoop traces process execution, showing PID, PPID, and argument details
if possible.
This traces exec() from the fork()->exec() sequence, which means it won't
catch new processes that only fork(), and, it will catch processes that
re-exec. This instruments sched:sched_process_exec without buffering, and then
in user-space (this program) reads PPID and process arguments asynchronously
from /proc.
If the process traced is very short-lived, this program may miss reading
arguments and PPID details. In that case, "<?>" and "?" will be printed
respectively.
This program is best-effort (a hack), and should be improved in the future when
other kernel capabilities are made available. It may be useful in the meantime.
Since this uses ftrace, only the root user can use this tool.
.SH REQUIREMENTS
FTRACE CONFIG, sched:sched_process_exec tracepoint (you may already have these
on recent kernels), and Perl.
.PP
.SH OPTIONS
\-n name
Only show processes that match this name. This is filtered in user space.
.TP
\-h
Print usage message.
.SH FIELDS
.TP
TIME
Time of process exec(): HH:MM:SS.
.TP
PID
Process ID.
.TP
PPID
Parent process ID, if this was able to be read (may be missed for short-lived
processes). If it is unable to be read, "?" is printed.
.TP
ARGS
Command line arguments, if these were able to be read in time (may be missed
for short-lived processes). If they are unable to be read, "<?>" is printed.
.PP
.SH OVERHEAD
This reads and processes exec() events in user space as they occur. Since the
rate of exec() is expected to be low (< 500/s), the overhead is expected to
be small or negligible.
.PP
.SH SOURCE
This is from the perf-tools collection.
.PP
https://github.com/brendangregg/perf-tools
.PP
Also look under the examples directory for a text file containing example
usage, output, and commentary for this tool.
.SH OS
Linux
.SH STABILITY
Unstable - in development.
.SH AUTHOR
Brendan Gregg
.SH SEE ALSO
top(1)