fluent-plugin-perf-tools 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|