rwtop revision 1.1.1.1 1 #!/usr/bin/ksh
2 #
3 # rwtop - display top read/write bytes by process.
4 # Written using DTrace (Solaris 10 3/05).
5 #
6 # This is measuring reads and writes at the application level. This matches
7 # read and write system calls.
8 #
9 # $Id: rwtop,v 1.1.1.1 2015/09/30 22:01:07 christos Exp $
10 #
11 # USAGE: rwtop [-cC] [-j|-Z] [-n name] [-p pid]
12 # [-t top] [interval [count]]
13 #
14 # rwtop # default output, 5 second samples
15 #
16 # -C # don't clear the screen
17 # -c # print counts
18 # -j # print project ID
19 # -Z # print zone ID
20 # -n name # this process name only
21 # -p PID # this PID only
22 # -t top # print top number only
23 # eg,
24 # rwtop 1 # 1 second samples
25 # rwtop -t 10 # print top 10 only
26 # rwtop -n bash # monitor processes named "bash"
27 # rwtop -C 5 12 # print 12 x 5 second samples
28 #
29 # FIELDS:
30 # ZONE Zone ID
31 # PROJ Project ID
32 # UID User ID
33 # PID Process ID
34 # PPID Parent Process ID
35 # CMD Process name
36 # D Direction, Read or Write
37 # BYTES Total bytes during sample
38 # app_r total reads during sample, Kbytes
39 # app_w total writes during sample, Kbytes
40 #
41 # SEE ALSO: iotop
42 #
43 # INSPIRATION: top(1) by William LeFebvre
44 #
45 # COPYRIGHT: Copyright (c) 2005, 2006 Brendan Gregg.
46 #
47 # CDDL HEADER START
48 #
49 # The contents of this file are subject to the terms of the
50 # Common Development and Distribution License, Version 1.0 only
51 # (the "License"). You may not use this file except in compliance
52 # with the License.
53 #
54 # You can obtain a copy of the license at Docs/cddl1.txt
55 # or http://www.opensolaris.org/os/licensing.
56 # See the License for the specific language governing permissions
57 # and limitations under the License.
58 #
59 # CDDL HEADER END
60 #
61 # Author: Brendan Gregg [Sydney, Australia]
62 #
63 # 24-Jul-2005 Brendan Gregg Created this.
64 # 20-Apr-2006 " " Last update.
65
66
67 ##############################
68 # --- Process Arguments ---
69 #
70
71 ### default variables
72 opt_name=0; opt_pid=0; opt_clear=1; opt_proj=0; opt_zone=0
73 opt_def=1; opt_bytes=1; filter=0; pname=.; pid=0
74 opt_top=0; opt_count=0; interval=5; count=-1; top=0
75
76 ### process options
77 while getopts Cchn:p:jt:Z name
78 do
79 case $name in
80 C) opt_clear=0 ;;
81 c) opt_count=1; opt_bytes=0 ;;
82 n) opt_name=1; pname=$OPTARG ;;
83 p) opt_pid=1; pid=$OPTARG ;;
84 j) opt_proj=1; opt_def=0 ;;
85 t) opt_top=1; top=$OPTARG ;;
86 Z) opt_zone=1; opt_def=0 ;;
87 h|?) cat <<-END >&2
88 USAGE: rwtop [-cC] [-j|-Z] [-n name] [-p pid]
89 [-t top] [interval [count]]
90
91 -C # don't clear the screen
92 -c # print counts
93 -j # print project ID
94 -Z # print zone ID
95 -n name # this process name only
96 -p PID # this PID only
97 -t top # print top number only
98 eg,
99 rwtop # default output, 5 second samples
100 rwtop 1 # 1 second samples
101 rwtop -t 10 # print top 10 only
102 rwtop -n bash # monitor processes named "bash"
103 rwtop -C 5 12 # print 12 x 5 second samples
104 END
105 exit 1
106 esac
107 done
108
109 shift $(( $OPTIND - 1 ))
110
111 ### option logic
112 if [[ "$1" > 0 ]]; then
113 interval=$1; shift
114 fi
115 if [[ "$1" > 0 ]]; then
116 count=$1; shift
117 fi
118 if (( opt_proj && opt_zone )); then
119 opt_proj=0
120 fi
121 if (( opt_name || opt_pid )); then
122 filter=1
123 fi
124 if (( opt_clear )); then
125 clearstr=`clear`
126 else
127 clearstr=.
128 fi
129
130
131
132 #################################
133 # --- Main Program, DTrace ---
134 #
135 /usr/sbin/dtrace -n '
136 /*
137 * Command line arguments
138 */
139 inline int OPT_def = '$opt_def';
140 inline int OPT_proj = '$opt_proj';
141 inline int OPT_zone = '$opt_zone';
142 inline int OPT_clear = '$opt_clear';
143 inline int OPT_bytes = '$opt_bytes';
144 inline int OPT_count = '$opt_count';
145 inline int OPT_name = '$opt_name';
146 inline int OPT_pid = '$opt_pid';
147 inline int OPT_top = '$opt_top';
148 inline int INTERVAL = '$interval';
149 inline int COUNTER = '$count';
150 inline int FILTER = '$filter';
151 inline int TOP = '$top';
152 inline int PID = '$pid';
153 inline string NAME = "'$pname'";
154 inline string CLEAR = "'$clearstr'";
155
156 #pragma D option quiet
157
158 /*
159 * Print header
160 */
161 dtrace:::BEGIN
162 {
163 /* starting values */
164 counts = COUNTER;
165 secs = INTERVAL;
166 app_r = 0;
167 app_w = 0;
168
169 printf("Tracing... Please wait.\n");
170 }
171
172 /*
173 * Check event is being traced
174 */
175 sysinfo:::readch,
176 sysinfo:::writech
177 /pid != $pid/
178 {
179 /* default is to trace unless filtering, */
180 this->ok = FILTER ? 0 : 1;
181
182 /* check each filter, */
183 (OPT_name == 1 && NAME == execname)? this->ok = 1 : 1;
184 (OPT_pid == 1 && PID == pid) ? this->ok = 1 : 1;
185 }
186
187 /*
188 * Increment tallys
189 */
190 sysinfo:::readch
191 /this->ok/
192 {
193 app_r += arg0;
194 }
195 sysinfo:::writech
196 /this->ok/
197 {
198 app_w += arg0;
199 }
200
201 /*
202 * Process event
203 */
204 sysinfo:::readch,
205 sysinfo:::writech
206 /this->ok/
207 {
208 /* choose statistic to track */
209 this->value = OPT_bytes ? arg0 : 1;
210
211 /*
212 * Save details
213 */
214 OPT_def ? @out[uid, pid, ppid, execname,
215 probename == "readch" ? "R" : "W"] = sum(this->value) : 1;
216 OPT_proj ? @out[curpsinfo->pr_projid, pid, ppid, execname,
217 probename == "readch" ? "R" : "W"] = sum(this->value) : 1;
218 OPT_zone ? @out[curpsinfo->pr_zoneid, pid, ppid, execname,
219 probename == "readch" ? "R" : "W"] = sum(this->value) : 1;
220
221 this->ok = 0;
222 }
223
224 /*
225 * Timer
226 */
227 profile:::tick-1sec
228 {
229 secs--;
230 }
231
232 /*
233 * Print Report
234 */
235 profile:::tick-1sec
236 /secs == 0/
237 {
238 /* fetch 1 min load average */
239 this->load1a = `hp_avenrun[0] / 65536;
240 this->load1b = ((`hp_avenrun[0] % 65536) * 100) / 65536;
241
242 /* convert counters to Kbytes */
243 app_r /= 1024;
244 app_w /= 1024;
245
246 /* print status */
247 OPT_clear ? printf("%s", CLEAR) : 1;
248 printf("%Y, load: %d.%02d, app_r: %6d KB, app_w: %6d KB\n\n",
249 walltimestamp, this->load1a, this->load1b, app_r, app_w);
250
251 /* print headers */
252 OPT_def ? printf(" UID ") : 1;
253 OPT_proj ? printf(" PROJ ") : 1;
254 OPT_zone ? printf(" ZONE ") : 1;
255 printf("%6s %6s %-16s %1s",
256 "PID", "PPID", "CMD", "D");
257 OPT_bytes ? printf(" %16s\n", "BYTES") : 1;
258 OPT_count ? printf(" %16s\n", "COUNT") : 1;
259
260 /* truncate to top lines if needed */
261 OPT_top ? trunc(@out, TOP) : 1;
262
263 /* print data */
264 printa("%5d %6d %6d %-16s %1s %16@d\n", @out);
265 printf("\n");
266
267 /* clear data */
268 trunc(@out);
269 app_r = 0;
270 app_w = 0;
271 secs = INTERVAL;
272 counts--;
273 }
274
275 /*
276 * End of program
277 */
278 profile:::tick-1sec
279 /counts == 0/
280 {
281 exit(0);
282 }
283
284 /*
285 * Cleanup for Ctrl-C
286 */
287 dtrace:::END
288 {
289 trunc(@out);
290 }
291 '
292
293