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 3 2007-08-01 10:50:08Z brendan $ 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 72opt_name=0; opt_pid=0; opt_clear=1; opt_proj=0; opt_zone=0 73opt_def=1; opt_bytes=1; filter=0; pname=.; pid=0 74opt_top=0; opt_count=0; interval=5; count=-1; top=0 75 76### process options 77while getopts Cchn:p:jt:Z name 78do 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 107done 108 109shift $(( $OPTIND - 1 )) 110 111### option logic 112if [[ "$1" > 0 ]]; then 113 interval=$1; shift 114fi 115if [[ "$1" > 0 ]]; then 116 count=$1; shift 117fi 118if (( opt_proj && opt_zone )); then 119 opt_proj=0 120fi 121if (( opt_name || opt_pid )); then 122 filter=1 123fi 124if (( opt_clear )); then 125 clearstr=`clear` 126else 127 clearstr=. 128fi 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