fluent-plugin-perf-tools 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rubocop.yml +26 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CODE_OF_CONDUCT.md +84 -0
  7. data/Gemfile +5 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +43 -0
  10. data/Rakefile +17 -0
  11. data/bin/console +15 -0
  12. data/bin/setup +8 -0
  13. data/fluent-plugin-perf-tools.gemspec +48 -0
  14. data/lib/fluent/plugin/in_perf_tools.rb +42 -0
  15. data/lib/fluent/plugin/perf_tools/cachestat.rb +65 -0
  16. data/lib/fluent/plugin/perf_tools/command.rb +30 -0
  17. data/lib/fluent/plugin/perf_tools/version.rb +9 -0
  18. data/lib/fluent/plugin/perf_tools.rb +11 -0
  19. data/perf-tools/LICENSE +339 -0
  20. data/perf-tools/README.md +205 -0
  21. data/perf-tools/bin/bitesize +1 -0
  22. data/perf-tools/bin/cachestat +1 -0
  23. data/perf-tools/bin/execsnoop +1 -0
  24. data/perf-tools/bin/funccount +1 -0
  25. data/perf-tools/bin/funcgraph +1 -0
  26. data/perf-tools/bin/funcslower +1 -0
  27. data/perf-tools/bin/functrace +1 -0
  28. data/perf-tools/bin/iolatency +1 -0
  29. data/perf-tools/bin/iosnoop +1 -0
  30. data/perf-tools/bin/killsnoop +1 -0
  31. data/perf-tools/bin/kprobe +1 -0
  32. data/perf-tools/bin/opensnoop +1 -0
  33. data/perf-tools/bin/perf-stat-hist +1 -0
  34. data/perf-tools/bin/reset-ftrace +1 -0
  35. data/perf-tools/bin/syscount +1 -0
  36. data/perf-tools/bin/tcpretrans +1 -0
  37. data/perf-tools/bin/tpoint +1 -0
  38. data/perf-tools/bin/uprobe +1 -0
  39. data/perf-tools/deprecated/README.md +1 -0
  40. data/perf-tools/deprecated/execsnoop-proc +150 -0
  41. data/perf-tools/deprecated/execsnoop-proc.8 +80 -0
  42. data/perf-tools/deprecated/execsnoop-proc_example.txt +46 -0
  43. data/perf-tools/disk/bitesize +175 -0
  44. data/perf-tools/examples/bitesize_example.txt +63 -0
  45. data/perf-tools/examples/cachestat_example.txt +58 -0
  46. data/perf-tools/examples/execsnoop_example.txt +153 -0
  47. data/perf-tools/examples/funccount_example.txt +126 -0
  48. data/perf-tools/examples/funcgraph_example.txt +2178 -0
  49. data/perf-tools/examples/funcslower_example.txt +110 -0
  50. data/perf-tools/examples/functrace_example.txt +341 -0
  51. data/perf-tools/examples/iolatency_example.txt +350 -0
  52. data/perf-tools/examples/iosnoop_example.txt +302 -0
  53. data/perf-tools/examples/killsnoop_example.txt +62 -0
  54. data/perf-tools/examples/kprobe_example.txt +379 -0
  55. data/perf-tools/examples/opensnoop_example.txt +47 -0
  56. data/perf-tools/examples/perf-stat-hist_example.txt +149 -0
  57. data/perf-tools/examples/reset-ftrace_example.txt +88 -0
  58. data/perf-tools/examples/syscount_example.txt +297 -0
  59. data/perf-tools/examples/tcpretrans_example.txt +93 -0
  60. data/perf-tools/examples/tpoint_example.txt +210 -0
  61. data/perf-tools/examples/uprobe_example.txt +321 -0
  62. data/perf-tools/execsnoop +292 -0
  63. data/perf-tools/fs/cachestat +167 -0
  64. data/perf-tools/images/perf-tools_2016.png +0 -0
  65. data/perf-tools/iolatency +296 -0
  66. data/perf-tools/iosnoop +296 -0
  67. data/perf-tools/kernel/funccount +146 -0
  68. data/perf-tools/kernel/funcgraph +259 -0
  69. data/perf-tools/kernel/funcslower +248 -0
  70. data/perf-tools/kernel/functrace +192 -0
  71. data/perf-tools/kernel/kprobe +270 -0
  72. data/perf-tools/killsnoop +263 -0
  73. data/perf-tools/man/man8/bitesize.8 +70 -0
  74. data/perf-tools/man/man8/cachestat.8 +111 -0
  75. data/perf-tools/man/man8/execsnoop.8 +104 -0
  76. data/perf-tools/man/man8/funccount.8 +76 -0
  77. data/perf-tools/man/man8/funcgraph.8 +166 -0
  78. data/perf-tools/man/man8/funcslower.8 +129 -0
  79. data/perf-tools/man/man8/functrace.8 +123 -0
  80. data/perf-tools/man/man8/iolatency.8 +116 -0
  81. data/perf-tools/man/man8/iosnoop.8 +169 -0
  82. data/perf-tools/man/man8/killsnoop.8 +100 -0
  83. data/perf-tools/man/man8/kprobe.8 +162 -0
  84. data/perf-tools/man/man8/opensnoop.8 +113 -0
  85. data/perf-tools/man/man8/perf-stat-hist.8 +111 -0
  86. data/perf-tools/man/man8/reset-ftrace.8 +49 -0
  87. data/perf-tools/man/man8/syscount.8 +96 -0
  88. data/perf-tools/man/man8/tcpretrans.8 +93 -0
  89. data/perf-tools/man/man8/tpoint.8 +140 -0
  90. data/perf-tools/man/man8/uprobe.8 +168 -0
  91. data/perf-tools/misc/perf-stat-hist +223 -0
  92. data/perf-tools/net/tcpretrans +311 -0
  93. data/perf-tools/opensnoop +280 -0
  94. data/perf-tools/syscount +192 -0
  95. data/perf-tools/system/tpoint +232 -0
  96. data/perf-tools/tools/reset-ftrace +123 -0
  97. data/perf-tools/user/uprobe +390 -0
  98. 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