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