rwtop revision 235368
1218822Sdim#!/usr/bin/ksh 278828Sobrien# 360484Sobrien# rwtop - display top read/write bytes by process. 460484Sobrien# Written using DTrace (Solaris 10 3/05). 560484Sobrien# 660484Sobrien# This is measuring reads and writes at the application level. This matches 760484Sobrien# read and write system calls. 860484Sobrien# 960484Sobrien# $Id: rwtop 3 2007-08-01 10:50:08Z brendan $ 1060484Sobrien# 1160484Sobrien# USAGE: rwtop [-cC] [-j|-Z] [-n name] [-p pid] 1260484Sobrien# [-t top] [interval [count]] 1360484Sobrien# 1460484Sobrien# rwtop # default output, 5 second samples 1560484Sobrien# 1660484Sobrien# -C # don't clear the screen 1760484Sobrien# -c # print counts 1860484Sobrien# -j # print project ID 1960484Sobrien# -Z # print zone ID 2060484Sobrien# -n name # this process name only 2160484Sobrien# -p PID # this PID only 2260484Sobrien# -t top # print top number only 2360484Sobrien# eg, 2460484Sobrien# rwtop 1 # 1 second samples 2560484Sobrien# rwtop -t 10 # print top 10 only 2660484Sobrien# rwtop -n bash # monitor processes named "bash" 2760484Sobrien# rwtop -C 5 12 # print 12 x 5 second samples 2860484Sobrien# 2960484Sobrien# FIELDS: 3060484Sobrien# ZONE Zone ID 3160484Sobrien# PROJ Project ID 3260484Sobrien# UID User ID 3360484Sobrien# PID Process ID 3460484Sobrien# PPID Parent Process ID 3560484Sobrien# CMD Process name 3660484Sobrien# D Direction, Read or Write 3760484Sobrien# BYTES Total bytes during sample 3860484Sobrien# app_r total reads during sample, Kbytes 3960484Sobrien# app_w total writes during sample, Kbytes 4060484Sobrien# 4160484Sobrien# SEE ALSO: iotop 4260484Sobrien# 4360484Sobrien# INSPIRATION: top(1) by William LeFebvre 4460484Sobrien# 4560484Sobrien# COPYRIGHT: Copyright (c) 2005, 2006 Brendan Gregg. 4660484Sobrien# 4760484Sobrien# CDDL HEADER START 4860484Sobrien# 4960484Sobrien# The contents of this file are subject to the terms of the 5060484Sobrien# Common Development and Distribution License, Version 1.0 only 5160484Sobrien# (the "License"). You may not use this file except in compliance 5260484Sobrien# with the License. 5360484Sobrien# 5460484Sobrien# You can obtain a copy of the license at Docs/cddl1.txt 5560484Sobrien# or http://www.opensolaris.org/os/licensing. 5660484Sobrien# See the License for the specific language governing permissions 5760484Sobrien# and limitations under the License. 5860484Sobrien# 5960484Sobrien# CDDL HEADER END 6060484Sobrien# 6160484Sobrien# Author: Brendan Gregg [Sydney, Australia] 6260484Sobrien# 6360484Sobrien# 24-Jul-2005 Brendan Gregg Created this. 6460484Sobrien# 20-Apr-2006 " " Last update. 6560484Sobrien 6660484Sobrien 6760484Sobrien############################## 6860484Sobrien# --- Process Arguments --- 6960484Sobrien# 7060484Sobrien 7160484Sobrien### default variables 7260484Sobrienopt_name=0; opt_pid=0; opt_clear=1; opt_proj=0; opt_zone=0 7360484Sobrienopt_def=1; opt_bytes=1; filter=0; pname=.; pid=0 7460484Sobrienopt_top=0; opt_count=0; interval=5; count=-1; top=0 7560484Sobrien 7660484Sobrien### process options 7760484Sobrienwhile getopts Cchn:p:jt:Z name 7860484Sobriendo 7960484Sobrien case $name in 8060484Sobrien C) opt_clear=0 ;; 8160484Sobrien c) opt_count=1; opt_bytes=0 ;; 8260484Sobrien n) opt_name=1; pname=$OPTARG ;; 8360484Sobrien p) opt_pid=1; pid=$OPTARG ;; 8460484Sobrien j) opt_proj=1; opt_def=0 ;; 8560484Sobrien t) opt_top=1; top=$OPTARG ;; 8660484Sobrien Z) opt_zone=1; opt_def=0 ;; 8760484Sobrien h|?) cat <<-END >&2 8860484Sobrien USAGE: rwtop [-cC] [-j|-Z] [-n name] [-p pid] 8960484Sobrien [-t top] [interval [count]] 9060484Sobrien 9160484Sobrien -C # don't clear the screen 9260484Sobrien -c # print counts 9360484Sobrien -j # print project ID 9460484Sobrien -Z # print zone ID 9560484Sobrien -n name # this process name only 9660484Sobrien -p PID # this PID only 9760484Sobrien -t top # print top number only 9860484Sobrien eg, 9960484Sobrien rwtop # default output, 5 second samples 10060484Sobrien rwtop 1 # 1 second samples 10160484Sobrien rwtop -t 10 # print top 10 only 10260484Sobrien rwtop -n bash # monitor processes named "bash" 10360484Sobrien rwtop -C 5 12 # print 12 x 5 second samples 10460484Sobrien END 10560484Sobrien exit 1 10660484Sobrien esac 10760484Sobriendone 10860484Sobrien 10960484Sobrienshift $(( $OPTIND - 1 )) 11060484Sobrien 11160484Sobrien### option logic 11260484Sobrienif [[ "$1" > 0 ]]; then 11360484Sobrien interval=$1; shift 11460484Sobrienfi 11560484Sobrienif [[ "$1" > 0 ]]; then 11660484Sobrien count=$1; shift 11760484Sobrienfi 11860484Sobrienif (( opt_proj && opt_zone )); then 11960484Sobrien opt_proj=0 12060484Sobrienfi 12160484Sobrienif (( opt_name || opt_pid )); then 12260484Sobrien filter=1 12360484Sobrienfi 12460484Sobrienif (( opt_clear )); then 12560484Sobrien clearstr=`clear` 12660484Sobrienelse 12760484Sobrien clearstr=. 12860484Sobrienfi 12960484Sobrien 13060484Sobrien 13160484Sobrien 13260484Sobrien################################# 13360484Sobrien# --- Main Program, DTrace --- 13460484Sobrien# 13560484Sobrien/usr/sbin/dtrace -n ' 13660484Sobrien /* 13760484Sobrien * Command line arguments 13860484Sobrien */ 13960484Sobrien inline int OPT_def = '$opt_def'; 14060484Sobrien inline int OPT_proj = '$opt_proj'; 14160484Sobrien inline int OPT_zone = '$opt_zone'; 14260484Sobrien inline int OPT_clear = '$opt_clear'; 14360484Sobrien inline int OPT_bytes = '$opt_bytes'; 14460484Sobrien inline int OPT_count = '$opt_count'; 14560484Sobrien inline int OPT_name = '$opt_name'; 14660484Sobrien inline int OPT_pid = '$opt_pid'; 14760484Sobrien inline int OPT_top = '$opt_top'; 14860484Sobrien inline int INTERVAL = '$interval'; 14960484Sobrien inline int COUNTER = '$count'; 15060484Sobrien inline int FILTER = '$filter'; 15160484Sobrien inline int TOP = '$top'; 15260484Sobrien inline int PID = '$pid'; 15360484Sobrien inline string NAME = "'$pname'"; 15460484Sobrien inline string CLEAR = "'$clearstr'"; 15560484Sobrien 15660484Sobrien #pragma D option quiet 15760484Sobrien 15860484Sobrien /* 15960484Sobrien * Print header 16060484Sobrien */ 16160484Sobrien dtrace:::BEGIN 16260484Sobrien { 16360484Sobrien /* starting values */ 16460484Sobrien counts = COUNTER; 165130561Sobrien secs = INTERVAL; 16660484Sobrien app_r = 0; 16760484Sobrien app_w = 0; 16860484Sobrien 16960484Sobrien printf("Tracing... Please wait.\n"); 17060484Sobrien } 17160484Sobrien 17260484Sobrien /* 17360484Sobrien * Check event is being traced 17460484Sobrien */ 17560484Sobrien sysinfo:::readch, 17660484Sobrien sysinfo:::writech 17760484Sobrien /pid != $pid/ 17860484Sobrien { 17960484Sobrien /* default is to trace unless filtering, */ 18060484Sobrien this->ok = FILTER ? 0 : 1; 18160484Sobrien 18260484Sobrien /* check each filter, */ 18360484Sobrien (OPT_name == 1 && NAME == execname)? this->ok = 1 : 1; 18460484Sobrien (OPT_pid == 1 && PID == pid) ? this->ok = 1 : 1; 18560484Sobrien } 18660484Sobrien 18760484Sobrien /* 18860484Sobrien * Increment tallys 18960484Sobrien */ 19060484Sobrien sysinfo:::readch 19160484Sobrien /this->ok/ 19260484Sobrien { 19360484Sobrien app_r += arg0; 19460484Sobrien } 19560484Sobrien 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