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# 20-Apr-2006, ver 0.71 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 65 66############################## 67# --- Process Arguments --- 68# 69 70### default variables 71opt_name=0; opt_pid=0; opt_clear=1; opt_proj=0; opt_zone=0 72opt_def=1; opt_bytes=1; filter=0; pname=.; pid=0 73opt_top=0; opt_count=0; interval=5; count=-1; top=0 74 75### process options 76while getopts Cchn:p:jt:Z name 77do 78 case $name in 79 C) opt_clear=0 ;; 80 c) opt_count=1; opt_bytes=0 ;; 81 n) opt_name=1; pname=$OPTARG ;; 82 p) opt_pid=1; pid=$OPTARG ;; 83 j) opt_proj=1; opt_def=0 ;; 84 t) opt_top=1; top=$OPTARG ;; 85 Z) opt_zone=1; opt_def=0 ;; 86 h|?) cat <<-END >&2 87 USAGE: rwtop [-cC] [-j|-Z] [-n name] [-p pid] 88 [-t top] [interval [count]] 89 90 -C # don't clear the screen 91 -c # print counts 92 -j # print project ID 93 -Z # print zone ID 94 -n name # this process name only 95 -p PID # this PID only 96 -t top # print top number only 97 eg, 98 rwtop # default output, 5 second samples 99 rwtop 1 # 1 second samples 100 rwtop -t 10 # print top 10 only 101 rwtop -n bash # monitor processes named "bash" 102 rwtop -C 5 12 # print 12 x 5 second samples 103 END 104 exit 1 105 esac 106done 107 108shift $(( $OPTIND - 1 )) 109 110### option logic 111if [[ "$1" > 0 ]]; then 112 interval=$1; shift 113fi 114if [[ "$1" > 0 ]]; then 115 count=$1; shift 116fi 117if (( opt_proj && opt_zone )); then 118 opt_proj=0 119fi 120if (( opt_name || opt_pid )); then 121 filter=1 122fi 123if (( opt_clear )); then 124 clearstr=`clear` 125else 126 clearstr=. 127fi 128 129 130 131################################# 132# --- Main Program, DTrace --- 133# 134/usr/sbin/dtrace -n ' 135 /* 136 * Command line arguments 137 */ 138 inline int OPT_def = '$opt_def'; 139 inline int OPT_proj = '$opt_proj'; 140 inline int OPT_zone = '$opt_zone'; 141 inline int OPT_clear = '$opt_clear'; 142 inline int OPT_bytes = '$opt_bytes'; 143 inline int OPT_count = '$opt_count'; 144 inline int OPT_name = '$opt_name'; 145 inline int OPT_pid = '$opt_pid'; 146 inline int OPT_top = '$opt_top'; 147 inline int INTERVAL = '$interval'; 148 inline int COUNTER = '$count'; 149 inline int FILTER = '$filter'; 150 inline int TOP = '$top'; 151 inline int PID = '$pid'; 152 inline string NAME = "'$pname'"; 153 inline string CLEAR = "'$clearstr'"; 154 155 #pragma D option quiet 156 157 /* 158 * Print header 159 */ 160 dtrace:::BEGIN 161 { 162 /* starting values */ 163 counts = COUNTER; 164 secs = INTERVAL; 165 app_r = 0; 166 app_w = 0; 167 168 printf("Tracing... Please wait.\n"); 169 } 170 171 /* 172 * Check event is being traced 173 */ 174 sysinfo:::readch, 175 sysinfo:::writech 176 /pid != $pid/ 177 { 178 /* default is to trace unless filtering, */ 179 this->ok = FILTER ? 0 : 1; 180 181 /* check each filter, */ 182 (OPT_name == 1 && NAME == strstr(NAME,execname))? this->ok = 1 : 1; 183 (OPT_name == 1 && execname == strstr(execname, NAME))? 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