fluent-plugin-perf-tools 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rubocop.yml +26 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +17 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/fluent-plugin-perf-tools.gemspec +48 -0
- data/lib/fluent/plugin/in_perf_tools.rb +42 -0
- data/lib/fluent/plugin/perf_tools/cachestat.rb +65 -0
- data/lib/fluent/plugin/perf_tools/command.rb +30 -0
- data/lib/fluent/plugin/perf_tools/version.rb +9 -0
- data/lib/fluent/plugin/perf_tools.rb +11 -0
- data/perf-tools/LICENSE +339 -0
- data/perf-tools/README.md +205 -0
- data/perf-tools/bin/bitesize +1 -0
- data/perf-tools/bin/cachestat +1 -0
- data/perf-tools/bin/execsnoop +1 -0
- data/perf-tools/bin/funccount +1 -0
- data/perf-tools/bin/funcgraph +1 -0
- data/perf-tools/bin/funcslower +1 -0
- data/perf-tools/bin/functrace +1 -0
- data/perf-tools/bin/iolatency +1 -0
- data/perf-tools/bin/iosnoop +1 -0
- data/perf-tools/bin/killsnoop +1 -0
- data/perf-tools/bin/kprobe +1 -0
- data/perf-tools/bin/opensnoop +1 -0
- data/perf-tools/bin/perf-stat-hist +1 -0
- data/perf-tools/bin/reset-ftrace +1 -0
- data/perf-tools/bin/syscount +1 -0
- data/perf-tools/bin/tcpretrans +1 -0
- data/perf-tools/bin/tpoint +1 -0
- data/perf-tools/bin/uprobe +1 -0
- data/perf-tools/deprecated/README.md +1 -0
- data/perf-tools/deprecated/execsnoop-proc +150 -0
- data/perf-tools/deprecated/execsnoop-proc.8 +80 -0
- data/perf-tools/deprecated/execsnoop-proc_example.txt +46 -0
- data/perf-tools/disk/bitesize +175 -0
- data/perf-tools/examples/bitesize_example.txt +63 -0
- data/perf-tools/examples/cachestat_example.txt +58 -0
- data/perf-tools/examples/execsnoop_example.txt +153 -0
- data/perf-tools/examples/funccount_example.txt +126 -0
- data/perf-tools/examples/funcgraph_example.txt +2178 -0
- data/perf-tools/examples/funcslower_example.txt +110 -0
- data/perf-tools/examples/functrace_example.txt +341 -0
- data/perf-tools/examples/iolatency_example.txt +350 -0
- data/perf-tools/examples/iosnoop_example.txt +302 -0
- data/perf-tools/examples/killsnoop_example.txt +62 -0
- data/perf-tools/examples/kprobe_example.txt +379 -0
- data/perf-tools/examples/opensnoop_example.txt +47 -0
- data/perf-tools/examples/perf-stat-hist_example.txt +149 -0
- data/perf-tools/examples/reset-ftrace_example.txt +88 -0
- data/perf-tools/examples/syscount_example.txt +297 -0
- data/perf-tools/examples/tcpretrans_example.txt +93 -0
- data/perf-tools/examples/tpoint_example.txt +210 -0
- data/perf-tools/examples/uprobe_example.txt +321 -0
- data/perf-tools/execsnoop +292 -0
- data/perf-tools/fs/cachestat +167 -0
- data/perf-tools/images/perf-tools_2016.png +0 -0
- data/perf-tools/iolatency +296 -0
- data/perf-tools/iosnoop +296 -0
- data/perf-tools/kernel/funccount +146 -0
- data/perf-tools/kernel/funcgraph +259 -0
- data/perf-tools/kernel/funcslower +248 -0
- data/perf-tools/kernel/functrace +192 -0
- data/perf-tools/kernel/kprobe +270 -0
- data/perf-tools/killsnoop +263 -0
- data/perf-tools/man/man8/bitesize.8 +70 -0
- data/perf-tools/man/man8/cachestat.8 +111 -0
- data/perf-tools/man/man8/execsnoop.8 +104 -0
- data/perf-tools/man/man8/funccount.8 +76 -0
- data/perf-tools/man/man8/funcgraph.8 +166 -0
- data/perf-tools/man/man8/funcslower.8 +129 -0
- data/perf-tools/man/man8/functrace.8 +123 -0
- data/perf-tools/man/man8/iolatency.8 +116 -0
- data/perf-tools/man/man8/iosnoop.8 +169 -0
- data/perf-tools/man/man8/killsnoop.8 +100 -0
- data/perf-tools/man/man8/kprobe.8 +162 -0
- data/perf-tools/man/man8/opensnoop.8 +113 -0
- data/perf-tools/man/man8/perf-stat-hist.8 +111 -0
- data/perf-tools/man/man8/reset-ftrace.8 +49 -0
- data/perf-tools/man/man8/syscount.8 +96 -0
- data/perf-tools/man/man8/tcpretrans.8 +93 -0
- data/perf-tools/man/man8/tpoint.8 +140 -0
- data/perf-tools/man/man8/uprobe.8 +168 -0
- data/perf-tools/misc/perf-stat-hist +223 -0
- data/perf-tools/net/tcpretrans +311 -0
- data/perf-tools/opensnoop +280 -0
- data/perf-tools/syscount +192 -0
- data/perf-tools/system/tpoint +232 -0
- data/perf-tools/tools/reset-ftrace +123 -0
- data/perf-tools/user/uprobe +390 -0
- metadata +349 -0
@@ -0,0 +1,248 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
#
|
3
|
+
# funcslower - trace kernel functions slower than a threshold (microseconds).
|
4
|
+
# Uses Linux ftrace.
|
5
|
+
#
|
6
|
+
# This uses the Linux ftrace function graph profiler to time kernel functions
|
7
|
+
# and filter them based on a latency threshold. This is a proof of concept using
|
8
|
+
# Linux ftrace capabilities on older kernels.
|
9
|
+
#
|
10
|
+
# USAGE: funcslower [-aChHPt] [-p PID] [-d secs] funcstring latency_us
|
11
|
+
#
|
12
|
+
# Run "funcslower -h" for full usage.
|
13
|
+
#
|
14
|
+
# REQUIREMENTS: FTRACE function graph, which you may already have available
|
15
|
+
# and enabled in recent kernels. And awk.
|
16
|
+
#
|
17
|
+
# The output format is the same as the ftrace function graph trace format,
|
18
|
+
# described in the kernel source under Documentation/trace/ftrace.txt.
|
19
|
+
# Note that the output may be shuffled when different CPU buffers are read;
|
20
|
+
# check the CPU column for changes, or include timestamps (-t) and post sort.
|
21
|
+
#
|
22
|
+
# WARNING: This uses dynamic tracing of kernel functions, and could cause
|
23
|
+
# kernel panics or freezes. Test, and know what you are doing, before use.
|
24
|
+
#
|
25
|
+
# OVERHEADS: Timing and filtering is performed in-kernel context, costing
|
26
|
+
# lower overheads than post-processing in user space. If you trace frequent
|
27
|
+
# events (eg, pick a common function and a low threshold), you might want to
|
28
|
+
# try the "-d secs" option, which buffers events in-kernel instead of printing
|
29
|
+
# them live.
|
30
|
+
#
|
31
|
+
# From perf-tools: https://github.com/brendangregg/perf-tools
|
32
|
+
#
|
33
|
+
# COPYRIGHT: Copyright (c) 2014 Brendan Gregg.
|
34
|
+
#
|
35
|
+
# This program is free software; you can redistribute it and/or
|
36
|
+
# modify it under the terms of the GNU General Public License
|
37
|
+
# as published by the Free Software Foundation; either version 2
|
38
|
+
# of the License, or (at your option) any later version.
|
39
|
+
#
|
40
|
+
# This program is distributed in the hope that it will be useful,
|
41
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
42
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
43
|
+
# GNU General Public License for more details.
|
44
|
+
#
|
45
|
+
# You should have received a copy of the GNU General Public License
|
46
|
+
# along with this program; if not, write to the Free Software Foundation,
|
47
|
+
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
48
|
+
#
|
49
|
+
# (http://www.gnu.org/copyleft/gpl.html)
|
50
|
+
#
|
51
|
+
# 12-Jul-2014 Brendan Gregg Created this.
|
52
|
+
|
53
|
+
### default variables
|
54
|
+
tracing=/sys/kernel/debug/tracing
|
55
|
+
flock=/var/tmp/.ftrace-lock
|
56
|
+
opt_duration=0; duration=; opt_pid=0; pid=; opt_tid=0; tid=
|
57
|
+
pidtext=; opt_headers=0; opt_proc=0; opt_time=0; opt_cpu=0
|
58
|
+
trap ':' INT QUIT TERM PIPE HUP # sends execution to end tracing section
|
59
|
+
|
60
|
+
function usage {
|
61
|
+
cat <<-END >&2
|
62
|
+
USAGE: funcslower [-aChHPt] [-p PID] [-L TID] [-d secs] funcstring latency_us
|
63
|
+
-a # all info (same as -HPt)
|
64
|
+
-C # measure on-CPU time only
|
65
|
+
-d seconds # trace duration, and use buffers
|
66
|
+
-h # this usage message
|
67
|
+
-H # include column headers
|
68
|
+
-p PID # trace when this pid is on-CPU
|
69
|
+
-L TID # trace when this thread is on-CPU
|
70
|
+
-P # show process names & PIDs
|
71
|
+
-t # show timestamps
|
72
|
+
eg,
|
73
|
+
funcslower vfs_read 10000 # trace vfs_read() slower than 10 ms
|
74
|
+
|
75
|
+
See the man page and example file for more info.
|
76
|
+
END
|
77
|
+
exit
|
78
|
+
}
|
79
|
+
|
80
|
+
function warn {
|
81
|
+
if ! eval "$@"; then
|
82
|
+
echo >&2 "WARNING: command failed \"$@\""
|
83
|
+
fi
|
84
|
+
}
|
85
|
+
|
86
|
+
function end {
|
87
|
+
# disable tracing
|
88
|
+
echo 2>/dev/null
|
89
|
+
echo "Ending tracing..." 2>/dev/null
|
90
|
+
cd $tracing
|
91
|
+
|
92
|
+
(( opt_time )) && warn "echo nofuncgraph-abstime > trace_options"
|
93
|
+
(( opt_proc )) && warn "echo nofuncgraph-proc > trace_options"
|
94
|
+
(( opt_cpu )) && warn "echo sleep-time > trace_options"
|
95
|
+
|
96
|
+
warn "echo nop > current_tracer"
|
97
|
+
(( opt_pid )) && warn "echo > set_ftrace_pid"
|
98
|
+
warn "echo > set_ftrace_filter"
|
99
|
+
warn "echo > set_graph_function"
|
100
|
+
warn "echo 0 > tracing_thresh"
|
101
|
+
warn "echo > trace"
|
102
|
+
|
103
|
+
(( wroteflock )) && warn "rm $flock"
|
104
|
+
}
|
105
|
+
|
106
|
+
function die {
|
107
|
+
echo >&2 "$@"
|
108
|
+
exit 1
|
109
|
+
}
|
110
|
+
|
111
|
+
function edie {
|
112
|
+
# die with a quiet end()
|
113
|
+
echo >&2 "$@"
|
114
|
+
exec >/dev/null 2>&1
|
115
|
+
end
|
116
|
+
exit 1
|
117
|
+
}
|
118
|
+
|
119
|
+
### process options
|
120
|
+
while getopts aCd:hHp:L:Pt opt
|
121
|
+
do
|
122
|
+
case $opt in
|
123
|
+
a) opt_headers=1; opt_proc=1; opt_time=1 ;;
|
124
|
+
C) opt_cpu=1; ;;
|
125
|
+
d) opt_duration=1; duration=$OPTARG ;;
|
126
|
+
p) opt_pid=1; pid=$OPTARG ;;
|
127
|
+
L) opt_tid=1; tid=$OPTARG ;;
|
128
|
+
H) opt_headers=1; ;;
|
129
|
+
P) opt_proc=1; ;;
|
130
|
+
t) opt_time=1; ;;
|
131
|
+
h|?) usage ;;
|
132
|
+
esac
|
133
|
+
done
|
134
|
+
shift $(( $OPTIND - 1 ))
|
135
|
+
|
136
|
+
### option logic
|
137
|
+
(( $# < 2 )) && usage
|
138
|
+
(( opt_pid && opt_tid )) && edie "ERROR: You can use -p or -L but not both."
|
139
|
+
funcs="$1"
|
140
|
+
shift
|
141
|
+
thresh=$1
|
142
|
+
(( opt_pid )) && pidtext=" for PID $pid"
|
143
|
+
(( opt_tid )) && pidtext=" for TID $tid"
|
144
|
+
printf "Tracing \"$funcs\"$pidtext slower than $thresh us"
|
145
|
+
if (( opt_duration )); then
|
146
|
+
echo " for $duration seconds..."
|
147
|
+
else
|
148
|
+
echo "... Ctrl-C to end."
|
149
|
+
fi
|
150
|
+
|
151
|
+
## select awk
|
152
|
+
if (( opt_duration )); then
|
153
|
+
[[ -x /usr/bin/mawk ]] && awk=mawk || awk=awk
|
154
|
+
else
|
155
|
+
# workarounds for mawk/gawk fflush behavior
|
156
|
+
if [[ -x /usr/bin/gawk ]]; then
|
157
|
+
awk=gawk
|
158
|
+
elif [[ -x /usr/bin/mawk ]]; then
|
159
|
+
awk="mawk -W interactive"
|
160
|
+
else
|
161
|
+
awk=awk
|
162
|
+
fi
|
163
|
+
fi
|
164
|
+
|
165
|
+
### check permissions
|
166
|
+
cd $tracing || die "ERROR: accessing tracing. Root user? Kernel has FTRACE?
|
167
|
+
debugfs mounted? (mount -t debugfs debugfs /sys/kernel/debug)"
|
168
|
+
|
169
|
+
### ftrace lock
|
170
|
+
[[ -e $flock ]] && die "ERROR: ftrace may be in use by PID $(cat $flock) $flock"
|
171
|
+
echo $$ > $flock || die "ERROR: unable to write $flock."
|
172
|
+
wroteflock=1
|
173
|
+
|
174
|
+
### setup and commence tracing
|
175
|
+
sysctl -q kernel.ftrace_enabled=1 # doesn't set exit status
|
176
|
+
read mode < current_tracer
|
177
|
+
[[ "$mode" != "nop" ]] && edie "ERROR: ftrace active (current_tracer=$mode)"
|
178
|
+
if ! echo $thresh > tracing_thresh; then
|
179
|
+
edie "ERROR: setting tracing_thresh to $thresh. Exiting."
|
180
|
+
fi
|
181
|
+
if (( opt_pid )); then
|
182
|
+
echo '' > set_ftrace_pid
|
183
|
+
# ftrace expects kernel pids, which are thread ids
|
184
|
+
for tid in /proc/$pid/task/*; do
|
185
|
+
if ! echo ${tid##*/} >> set_ftrace_pid; then
|
186
|
+
edie "ERROR: setting -p $pid (PID exist?). Exiting."
|
187
|
+
fi
|
188
|
+
done
|
189
|
+
fi
|
190
|
+
if (( opt_tid )); then
|
191
|
+
if ! echo $tid > set_ftrace_pid; then
|
192
|
+
edie "ERROR: setting -L $tid (TID exist?). Exiting."
|
193
|
+
fi
|
194
|
+
fi
|
195
|
+
if ! echo "$funcs" > set_ftrace_filter; then
|
196
|
+
edie "ERROR: enabling \"$funcs\" filter. Function exist? Exiting."
|
197
|
+
fi
|
198
|
+
if ! echo "$funcs" > set_graph_function; then
|
199
|
+
edie "ERROR: enabling \"$funcs\" graph. Exiting."
|
200
|
+
fi
|
201
|
+
if ! echo function_graph > current_tracer; then
|
202
|
+
edie "ERROR: setting current_tracer to \"function_graph\". Exiting."
|
203
|
+
fi
|
204
|
+
if (( opt_cpu )); then
|
205
|
+
if ! echo nosleep-time > trace_options; then
|
206
|
+
edie "ERROR: setting -C (nosleep-time). Exiting."
|
207
|
+
fi
|
208
|
+
fi
|
209
|
+
# the following must be done after setting current_tracer
|
210
|
+
if (( opt_time )); then
|
211
|
+
if ! echo funcgraph-abstime > trace_options; then
|
212
|
+
edie "ERROR: setting -t (funcgraph-abstime). Exiting."
|
213
|
+
fi
|
214
|
+
fi
|
215
|
+
if (( opt_proc )); then
|
216
|
+
if ! echo funcgraph-proc > trace_options; then
|
217
|
+
edie "ERROR: setting -P (funcgraph-proc). Exiting."
|
218
|
+
fi
|
219
|
+
fi
|
220
|
+
|
221
|
+
### setup output filter
|
222
|
+
cat=cat
|
223
|
+
if (( opt_proc )); then
|
224
|
+
# remove proc change entries, since PID is included. example:
|
225
|
+
# ------------------------------------------
|
226
|
+
# 0) supervi-1699 => supervi-1693
|
227
|
+
# ------------------------------------------
|
228
|
+
#
|
229
|
+
cat=$awk' "/(^ ---|^$)/ || \$3 == \"=>\" { next } { print \$0 }"'
|
230
|
+
fi
|
231
|
+
|
232
|
+
### print trace buffer
|
233
|
+
warn "echo > trace"
|
234
|
+
if (( opt_duration )); then
|
235
|
+
sleep $duration
|
236
|
+
if (( opt_headers )); then
|
237
|
+
$cat trace
|
238
|
+
else
|
239
|
+
$cat trace | grep -v '^#'
|
240
|
+
fi
|
241
|
+
else
|
242
|
+
# trace_pipe lack headers, so fetch them from trace
|
243
|
+
(( opt_headers )) && cat trace
|
244
|
+
eval $cat trace_pipe
|
245
|
+
fi
|
246
|
+
|
247
|
+
### end tracing
|
248
|
+
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
#
|
3
|
+
# functrace - trace kernel function calls matching specified wildcards.
|
4
|
+
# Uses Linux ftrace.
|
5
|
+
#
|
6
|
+
# This is a proof of concept using Linux ftrace capabilities on older kernels.
|
7
|
+
#
|
8
|
+
# USAGE: functrace [-hH] [-p PID] [-L TID] [-d secs] funcstring
|
9
|
+
# eg,
|
10
|
+
# functrace '*sleep' # trace all functions ending in "sleep"
|
11
|
+
#
|
12
|
+
# Run "functrace -h" for full usage.
|
13
|
+
#
|
14
|
+
# The output format is the same as the ftrace function trace format, described
|
15
|
+
# in the kernel source under Documentation/trace/ftrace.txt.
|
16
|
+
#
|
17
|
+
# The "-d duration" mode leaves the trace data in the kernel buffer, and
|
18
|
+
# only reads it at the end. If the trace data is large, beware of exhausting
|
19
|
+
# buffer space (/sys/kernel/debug/tracing/buffer_size_kb) and losing data.
|
20
|
+
#
|
21
|
+
# Also beware of feedback loops: tracing tcp* functions over an ssh session,
|
22
|
+
# or writing ext4* functions to an ext4 file system. For the former, tcp
|
23
|
+
# trace data could be redirected to a file (as in the usage message). For
|
24
|
+
# the latter, trace to the screen or a different file system.
|
25
|
+
#
|
26
|
+
# WARNING: This uses dynamic tracing of kernel functions, and could cause
|
27
|
+
# kernel panics or freezes. Test, and know what you are doing, before use.
|
28
|
+
#
|
29
|
+
# OVERHEADS: This can generate a lot of trace data quickly, depending on the
|
30
|
+
# frequency of the traced events. Such data will cause performance overheads.
|
31
|
+
# This also works without buffering by default, printing function events
|
32
|
+
# as they happen (uses trace_pipe), context switching and consuming CPU to do
|
33
|
+
# so. If needed, you can try the "-d secs" option, which buffers events
|
34
|
+
# instead, reducing overhead. If you think the buffer option is losing events,
|
35
|
+
# try increasing the buffer size (buffer_size_kb).
|
36
|
+
#
|
37
|
+
# From perf-tools: https://github.com/brendangregg/perf-tools
|
38
|
+
#
|
39
|
+
# COPYRIGHT: Copyright (c) 2014 Brendan Gregg.
|
40
|
+
#
|
41
|
+
# This program is free software; you can redistribute it and/or
|
42
|
+
# modify it under the terms of the GNU General Public License
|
43
|
+
# as published by the Free Software Foundation; either version 2
|
44
|
+
# of the License, or (at your option) any later version.
|
45
|
+
#
|
46
|
+
# This program is distributed in the hope that it will be useful,
|
47
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
48
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
49
|
+
# GNU General Public License for more details.
|
50
|
+
#
|
51
|
+
# You should have received a copy of the GNU General Public License
|
52
|
+
# along with this program; if not, write to the Free Software Foundation,
|
53
|
+
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
54
|
+
#
|
55
|
+
# (http://www.gnu.org/copyleft/gpl.html)
|
56
|
+
#
|
57
|
+
# 12-Jul-2014 Brendan Gregg Created this.
|
58
|
+
|
59
|
+
### default variables
|
60
|
+
tracing=/sys/kernel/debug/tracing
|
61
|
+
flock=/var/tmp/.ftrace-lock
|
62
|
+
opt_duration=0; duration=; opt_pid=0; pid=; opt_tid=0; tid=; pidtext=
|
63
|
+
opt_headers=0
|
64
|
+
trap ':' INT QUIT TERM PIPE HUP # sends execution to end tracing section
|
65
|
+
|
66
|
+
function usage {
|
67
|
+
cat <<-END >&2
|
68
|
+
USAGE: functrace [-hH] [-p PID] [-L TID] [-d secs] funcstring
|
69
|
+
-d seconds # trace duration, and use buffers
|
70
|
+
-h # this usage message
|
71
|
+
-H # include column headers
|
72
|
+
-p PID # trace when this pid is on-CPU
|
73
|
+
-L TID # trace when this thread is on-CPU
|
74
|
+
eg,
|
75
|
+
functrace do_nanosleep # trace the do_nanosleep() function
|
76
|
+
functrace '*sleep' # trace functions ending in "sleep"
|
77
|
+
functrace -p 198 'vfs*' # trace "vfs*" funcs for PID 198
|
78
|
+
functrace 'tcp*' > out # trace all "tcp*" funcs to out file
|
79
|
+
functrace -d 1 'tcp*' > out # trace 1 sec, then write out file
|
80
|
+
|
81
|
+
See the man page and example file for more info.
|
82
|
+
END
|
83
|
+
exit
|
84
|
+
}
|
85
|
+
|
86
|
+
function warn {
|
87
|
+
if ! eval "$@"; then
|
88
|
+
echo >&2 "WARNING: command failed \"$@\""
|
89
|
+
fi
|
90
|
+
}
|
91
|
+
|
92
|
+
function end {
|
93
|
+
# disable tracing
|
94
|
+
echo 2>/dev/null
|
95
|
+
echo "Ending tracing..." 2>/dev/null
|
96
|
+
cd $tracing
|
97
|
+
warn "echo nop > current_tracer"
|
98
|
+
(( opt_pid || opt_tid )) && warn "echo > set_ftrace_pid"
|
99
|
+
warn "echo > set_ftrace_filter"
|
100
|
+
warn "echo > trace"
|
101
|
+
(( wroteflock )) && warn "rm $flock"
|
102
|
+
}
|
103
|
+
|
104
|
+
function die {
|
105
|
+
echo >&2 "$@"
|
106
|
+
exit 1
|
107
|
+
}
|
108
|
+
|
109
|
+
function edie {
|
110
|
+
# die with a quiet end()
|
111
|
+
echo >&2 "$@"
|
112
|
+
exec >/dev/null 2>&1
|
113
|
+
end
|
114
|
+
exit 1
|
115
|
+
}
|
116
|
+
|
117
|
+
### process options
|
118
|
+
while getopts d:hHp:L: opt
|
119
|
+
do
|
120
|
+
case $opt in
|
121
|
+
d) opt_duration=1; duration=$OPTARG ;;
|
122
|
+
p) opt_pid=1; pid=$OPTARG ;;
|
123
|
+
L) opt_tid=1; tid=$OPTARG ;;
|
124
|
+
H) opt_headers=1; ;;
|
125
|
+
h|?) usage ;;
|
126
|
+
esac
|
127
|
+
done
|
128
|
+
shift $(( $OPTIND - 1 ))
|
129
|
+
|
130
|
+
### option logic
|
131
|
+
(( $# == 0 )) && usage
|
132
|
+
(( opt_pid && opt_tid )) && edie "ERROR: You can use -p or -L but not both."
|
133
|
+
funcs="$1"
|
134
|
+
(( opt_pid )) && pidtext=" for PID $pid"
|
135
|
+
(( opt_tid )) && pidtext=" for TID $pid"
|
136
|
+
if (( opt_duration )); then
|
137
|
+
echo "Tracing \"$funcs\"$pidtext for $duration seconds..."
|
138
|
+
else
|
139
|
+
echo "Tracing \"$funcs\"$pidtext... Ctrl-C to end."
|
140
|
+
fi
|
141
|
+
|
142
|
+
### check permissions
|
143
|
+
cd $tracing || die "ERROR: accessing tracing. Root user? Kernel has FTRACE?
|
144
|
+
debugfs mounted? (mount -t debugfs debugfs /sys/kernel/debug)"
|
145
|
+
|
146
|
+
### ftrace lock
|
147
|
+
[[ -e $flock ]] && die "ERROR: ftrace may be in use by PID $(cat $flock) $flock"
|
148
|
+
echo $$ > $flock || die "ERROR: unable to write $flock."
|
149
|
+
wroteflock=1
|
150
|
+
|
151
|
+
### setup and commence tracing
|
152
|
+
sysctl -q kernel.ftrace_enabled=1 # doesn't set exit status
|
153
|
+
read mode < current_tracer
|
154
|
+
[[ "$mode" != "nop" ]] && edie "ERROR: ftrace active (current_tracer=$mode)"
|
155
|
+
if (( opt_pid )); then
|
156
|
+
echo > set_ftrace_pid
|
157
|
+
# ftrace expects kernel pids, which are thread ids
|
158
|
+
for tid in /proc/$pid/task/*; do
|
159
|
+
if ! echo ${tid##*/} >> set_ftrace_pid; then
|
160
|
+
edie "ERROR: setting -p $pid (PID exist?). Exiting."
|
161
|
+
fi
|
162
|
+
done
|
163
|
+
fi
|
164
|
+
if (( opt_tid )); then
|
165
|
+
if ! echo $tid > set_ftrace_pid; then
|
166
|
+
edie "ERROR: setting -L $tid (TID exist?). Exiting."
|
167
|
+
fi
|
168
|
+
fi
|
169
|
+
if ! echo "$funcs" > set_ftrace_filter; then
|
170
|
+
edie "ERROR: enabling \"$funcs\". Exiting."
|
171
|
+
fi
|
172
|
+
if ! echo function > current_tracer; then
|
173
|
+
edie "ERROR: setting current_tracer to \"function\". Exiting."
|
174
|
+
fi
|
175
|
+
|
176
|
+
### print trace buffer
|
177
|
+
warn "echo > trace"
|
178
|
+
if (( opt_duration )); then
|
179
|
+
sleep $duration
|
180
|
+
if (( opt_headers )); then
|
181
|
+
cat trace
|
182
|
+
else
|
183
|
+
grep -v '^#' trace
|
184
|
+
fi
|
185
|
+
else
|
186
|
+
# trace_pipe lack headers, so fetch them from trace
|
187
|
+
(( opt_headers )) && cat trace
|
188
|
+
cat trace_pipe
|
189
|
+
fi
|
190
|
+
|
191
|
+
### end tracing
|
192
|
+
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
#
|
3
|
+
# kprobe - trace a given kprobe definition. Kernel dynamic tracing.
|
4
|
+
# Written using Linux ftrace.
|
5
|
+
#
|
6
|
+
# This will create, trace, then destroy a given kprobe definition. See
|
7
|
+
# Documentation/trace/kprobetrace.txt in the Linux kernel source for the
|
8
|
+
# syntax of a kprobe definition, and "kprobe -h" for examples. With this tool,
|
9
|
+
# the probe alias is optional (it will become to kprobe:<funcname> if not
|
10
|
+
# specified).
|
11
|
+
#
|
12
|
+
# USAGE: ./kprobe [-FhHsv] [-d secs] [-p pid] [-L tid] kprobe_definition [filter]
|
13
|
+
#
|
14
|
+
# Run "kprobe -h" for full usage.
|
15
|
+
#
|
16
|
+
# I wrote this because I kept testing different custom kprobes at the command
|
17
|
+
# line, and wanted a way to automate the steps.
|
18
|
+
#
|
19
|
+
# WARNING: This uses dynamic tracing of kernel functions, and could cause
|
20
|
+
# kernel panics or freezes, depending on the function traced. Test in a lab
|
21
|
+
# environment, and know what you are doing, before use.
|
22
|
+
#
|
23
|
+
# REQUIREMENTS: FTRACE and KPROBE CONFIG, which you may already have on recent
|
24
|
+
# kernel versions.
|
25
|
+
#
|
26
|
+
# From perf-tools: https://github.com/brendangregg/perf-tools
|
27
|
+
#
|
28
|
+
# See the kprobe(8) man page (in perf-tools) for more info.
|
29
|
+
#
|
30
|
+
# COPYRIGHT: Copyright (c) 2014 Brendan Gregg.
|
31
|
+
#
|
32
|
+
# This program is free software; you can redistribute it and/or
|
33
|
+
# modify it under the terms of the GNU General Public License
|
34
|
+
# as published by the Free Software Foundation; either version 2
|
35
|
+
# of the License, or (at your option) any later version.
|
36
|
+
#
|
37
|
+
# This program is distributed in the hope that it will be useful,
|
38
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
39
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
40
|
+
# GNU General Public License for more details.
|
41
|
+
#
|
42
|
+
# You should have received a copy of the GNU General Public License
|
43
|
+
# along with this program; if not, write to the Free Software Foundation,
|
44
|
+
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
45
|
+
#
|
46
|
+
# (http://www.gnu.org/copyleft/gpl.html)
|
47
|
+
#
|
48
|
+
# 22-Jul-2014 Brendan Gregg Created this.
|
49
|
+
|
50
|
+
### default variables
|
51
|
+
tracing=/sys/kernel/debug/tracing
|
52
|
+
flock=/var/tmp/.ftrace-lock; wroteflock=0
|
53
|
+
opt_duration=0; duration=; opt_pid=0; pid=; opt_tid=0; tid=
|
54
|
+
opt_filter=0; filter=; opt_view=0; opt_headers=0; opt_stack=0; dmesg=2
|
55
|
+
debug=0; opt_force=0
|
56
|
+
trap ':' INT QUIT TERM PIPE HUP # sends execution to end tracing section
|
57
|
+
|
58
|
+
function usage {
|
59
|
+
cat <<-END >&2
|
60
|
+
USAGE: kprobe [-FhHsv] [-d secs] [-p PID] [-L TID] kprobe_definition [filter]
|
61
|
+
-F # force. trace despite warnings.
|
62
|
+
-d seconds # trace duration, and use buffers
|
63
|
+
-p PID # PID to match on events
|
64
|
+
-L TID # thread id to match on events
|
65
|
+
-v # view format file (don't trace)
|
66
|
+
-H # include column headers
|
67
|
+
-s # show kernel stack traces
|
68
|
+
-h # this usage message
|
69
|
+
|
70
|
+
Note that these examples may need modification to match your kernel
|
71
|
+
version's function names and platform's register usage.
|
72
|
+
eg,
|
73
|
+
kprobe p:do_sys_open
|
74
|
+
# trace open() entry
|
75
|
+
kprobe r:do_sys_open
|
76
|
+
# trace open() return
|
77
|
+
kprobe 'r:do_sys_open \$retval'
|
78
|
+
# trace open() return value
|
79
|
+
kprobe 'r:myopen do_sys_open \$retval'
|
80
|
+
# use a custom probe name
|
81
|
+
kprobe 'p:myopen do_sys_open mode=%cx:u16'
|
82
|
+
# trace open() file mode
|
83
|
+
kprobe 'p:myopen do_sys_open filename=+0(%si):string'
|
84
|
+
# trace open() with filename
|
85
|
+
kprobe -s 'p:myprobe tcp_retransmit_skb'
|
86
|
+
# show kernel stacks
|
87
|
+
kprobe 'p:do_sys_open file=+0(%si):string' 'file ~ "*stat"'
|
88
|
+
# opened files ending in "stat"
|
89
|
+
|
90
|
+
See the man page and example file for more info.
|
91
|
+
END
|
92
|
+
exit
|
93
|
+
}
|
94
|
+
|
95
|
+
function warn {
|
96
|
+
if ! eval "$@"; then
|
97
|
+
echo >&2 "WARNING: command failed \"$@\""
|
98
|
+
fi
|
99
|
+
}
|
100
|
+
|
101
|
+
function end {
|
102
|
+
# disable tracing
|
103
|
+
echo 2>/dev/null
|
104
|
+
echo "Ending tracing..." 2>/dev/null
|
105
|
+
cd $tracing
|
106
|
+
warn "echo 0 > events/kprobes/$kname/enable"
|
107
|
+
if (( opt_filter )); then
|
108
|
+
warn "echo 0 > events/kprobes/$kname/filter"
|
109
|
+
fi
|
110
|
+
warn "echo -:$kname >> kprobe_events"
|
111
|
+
(( opt_stack )) && warn "echo 0 > options/stacktrace"
|
112
|
+
warn "echo > trace"
|
113
|
+
(( wroteflock )) && warn "rm $flock"
|
114
|
+
}
|
115
|
+
|
116
|
+
function die {
|
117
|
+
echo >&2 "$@"
|
118
|
+
exit 1
|
119
|
+
}
|
120
|
+
|
121
|
+
function edie {
|
122
|
+
# die with a quiet end()
|
123
|
+
echo >&2 "$@"
|
124
|
+
exec >/dev/null 2>&1
|
125
|
+
end
|
126
|
+
exit 1
|
127
|
+
}
|
128
|
+
|
129
|
+
### process options
|
130
|
+
while getopts Fd:hHp:L:sv opt
|
131
|
+
do
|
132
|
+
case $opt in
|
133
|
+
F) opt_force=1 ;;
|
134
|
+
d) opt_duration=1; duration=$OPTARG ;;
|
135
|
+
p) opt_pid=1; pid=$OPTARG ;;
|
136
|
+
L) opt_tid=1; tid=$OPTARG ;;
|
137
|
+
H) opt_headers=1 ;;
|
138
|
+
s) opt_stack=1 ;;
|
139
|
+
v) opt_view=1 ;;
|
140
|
+
h|?) usage ;;
|
141
|
+
esac
|
142
|
+
done
|
143
|
+
shift $(( $OPTIND - 1 ))
|
144
|
+
(( $# )) || usage
|
145
|
+
kprobe=$1
|
146
|
+
shift
|
147
|
+
if (( $# )); then
|
148
|
+
opt_filter=1
|
149
|
+
filter=$1
|
150
|
+
fi
|
151
|
+
|
152
|
+
### option logic
|
153
|
+
(( opt_pid + opt_filter + opt_tid > 1 )) && \
|
154
|
+
die "ERROR: use at most one of -p, -L, or filter."
|
155
|
+
(( opt_duration && opt_view )) && die "ERROR: use either -d or -v."
|
156
|
+
if (( opt_pid )); then
|
157
|
+
# convert to filter
|
158
|
+
opt_filter=1
|
159
|
+
# ftrace common_pid is thread id from user's perspective
|
160
|
+
for tid in /proc/$pid/task/*; do
|
161
|
+
filter="$filter || common_pid == ${tid##*/}"
|
162
|
+
done
|
163
|
+
filter=${filter:3} # trim leading ' || ' (four characters)
|
164
|
+
fi
|
165
|
+
if (( opt_tid )); then
|
166
|
+
opt_filter=1
|
167
|
+
filter="common_pid == $tid"
|
168
|
+
fi
|
169
|
+
if [[ "$kprobe" != p:* && "$kprobe" != r:* ]]; then
|
170
|
+
echo >&2 "ERROR: invalid kprobe definition (should start with p: or r:)"
|
171
|
+
usage
|
172
|
+
fi
|
173
|
+
#
|
174
|
+
# parse the following:
|
175
|
+
# r:do_sys_open
|
176
|
+
# r:my_sys_open do_sys_open
|
177
|
+
# r:do_sys_open %ax
|
178
|
+
# r:do_sys_open $retval %ax
|
179
|
+
# r:my_sys_open do_sys_open $retval %ax
|
180
|
+
# r:do_sys_open rval=$retval
|
181
|
+
# r:my_sys_open do_sys_open rval=$retval
|
182
|
+
# r:my_sys_open do_sys_open rval=$retval %ax
|
183
|
+
# ... and examples from USAGE message
|
184
|
+
#
|
185
|
+
krest=${kprobe#*:}
|
186
|
+
kname=${krest%% *}
|
187
|
+
set -- $krest
|
188
|
+
if [[ $2 == "" || $2 == *[=%\$]* ]]; then
|
189
|
+
# if probe name unspecified, default to function name
|
190
|
+
ktype=${kprobe%%:*}
|
191
|
+
kprobe="$ktype:$kname $krest"
|
192
|
+
fi
|
193
|
+
if (( debug )); then
|
194
|
+
echo "kname: $kname, kprobe: $kprobe"
|
195
|
+
fi
|
196
|
+
|
197
|
+
### check permissions
|
198
|
+
cd $tracing || die "ERROR: accessing tracing. Root user? Kernel has FTRACE?
|
199
|
+
debugfs mounted? (mount -t debugfs debugfs /sys/kernel/debug)"
|
200
|
+
|
201
|
+
## check function
|
202
|
+
set -- $kprobe
|
203
|
+
fname=$2
|
204
|
+
if (( !opt_force )) && ! grep -w $fname available_filter_functions >/dev/null \
|
205
|
+
2>&1
|
206
|
+
then
|
207
|
+
echo >&2 "ERROR: func $fname not in $PWD/available_filter_functions."
|
208
|
+
printf >&2 "Either it doesn't exist, or, it might be unsafe to kprobe. "
|
209
|
+
echo >&2 "Exiting. Use -F to override."
|
210
|
+
exit 1
|
211
|
+
fi
|
212
|
+
|
213
|
+
if (( !opt_view )); then
|
214
|
+
if (( opt_duration )); then
|
215
|
+
echo "Tracing kprobe $kname for $duration seconds (buffered)..."
|
216
|
+
else
|
217
|
+
echo "Tracing kprobe $kname. Ctrl-C to end."
|
218
|
+
fi
|
219
|
+
fi
|
220
|
+
|
221
|
+
### ftrace lock
|
222
|
+
[[ -e $flock ]] && die "ERROR: ftrace may be in use by PID $(cat $flock) $flock"
|
223
|
+
echo $$ > $flock || die "ERROR: unable to write $flock."
|
224
|
+
wroteflock=1
|
225
|
+
|
226
|
+
### setup and begin tracing
|
227
|
+
echo nop > current_tracer
|
228
|
+
if ! echo "$kprobe" >> kprobe_events; then
|
229
|
+
echo >&2 "ERROR: adding kprobe \"$kprobe\"."
|
230
|
+
if (( dmesg )); then
|
231
|
+
echo >&2 "Last $dmesg dmesg entries (might contain reason):"
|
232
|
+
dmesg | tail -$dmesg | sed 's/^/ /'
|
233
|
+
fi
|
234
|
+
edie "Exiting."
|
235
|
+
fi
|
236
|
+
if (( opt_view )); then
|
237
|
+
cat events/kprobes/$kname/format
|
238
|
+
edie ""
|
239
|
+
fi
|
240
|
+
if (( opt_filter )); then
|
241
|
+
if ! echo "$filter" > events/kprobes/$kname/filter; then
|
242
|
+
edie "ERROR: setting filter or -p. Exiting."
|
243
|
+
fi
|
244
|
+
fi
|
245
|
+
if (( opt_stack )); then
|
246
|
+
if ! echo 1 > options/stacktrace; then
|
247
|
+
edie "ERROR: enabling stack traces (-s). Exiting"
|
248
|
+
fi
|
249
|
+
fi
|
250
|
+
if ! echo 1 > events/kprobes/$kname/enable; then
|
251
|
+
edie "ERROR: enabling kprobe $kname. Exiting."
|
252
|
+
fi
|
253
|
+
|
254
|
+
### print trace buffer
|
255
|
+
warn "echo > trace"
|
256
|
+
if (( opt_duration )); then
|
257
|
+
sleep $duration
|
258
|
+
if (( opt_headers )); then
|
259
|
+
cat trace
|
260
|
+
else
|
261
|
+
grep -v '^#' trace
|
262
|
+
fi
|
263
|
+
else
|
264
|
+
# trace_pipe lack headers, so fetch them from trace
|
265
|
+
(( opt_headers )) && cat trace
|
266
|
+
cat trace_pipe
|
267
|
+
fi
|
268
|
+
|
269
|
+
### end tracing
|
270
|
+
end
|