1 1.1 christos #!/usr/bin/ksh 2 1.1 christos # 3 1.1 christos # zvmstat - print vmstat style info per Zone. 4 1.1 christos # This uses DTrace (Solaris 10 3/05). 5 1.1 christos # 6 1.1 christos # This program must be run from the global zone as root. 7 1.1 christos # 8 1.1 christos # $Id: zvmstat,v 1.1.1.1 2015/09/30 22:01:09 christos Exp $ 9 1.1 christos # 10 1.1 christos # USAGE: zvmstat [-ht] [interval [count]] 11 1.1 christos # 12 1.1 christos # zvmstat # default output 13 1.1 christos # -t # print times 14 1.1 christos # eg, 15 1.1 christos # zvmstat 1 # print every 1 second 16 1.1 christos # zvmstat 10 5 # print 5 x 10 second samples 17 1.1 christos # zvmstat -t 5 # print every 5 seconds with time 18 1.1 christos # 19 1.1 christos # 20 1.1 christos # FIELDS: 21 1.1 christos # re page reclaims 22 1.1 christos # mf minor faults 23 1.1 christos # fr pages freed 24 1.1 christos # sr scan rate 25 1.1 christos # epi executable pages paged in 26 1.1 christos # epo executable pages paged out 27 1.1 christos # epf executable pages freed 28 1.1 christos # api anonymous pages paged in 29 1.1 christos # apo anonymous pages paged out 30 1.1 christos # apf anonymous pages freed 31 1.1 christos # fpi filesystem pages paged in 32 1.1 christos # fpo filesystem pages paged out 33 1.1 christos # fpf filesystem pages freed 34 1.1 christos # 35 1.1 christos # NOTES: 36 1.1 christos # - Zone status should really be provided by Kstat, which currently 37 1.1 christos # provides system wide values, per CPU and per processor set, but not per 38 1.1 christos # zone. DTrace can fill this role in the meantime until Kstat supports zones. 39 1.1 christos # - First output does not contain summary since boot. 40 1.1 christos # 41 1.1 christos # SEE ALSO: prstat -Z 42 1.1 christos # 43 1.1 christos # COPYRIGHT: Copyright (c) 2005 Brendan Gregg. 44 1.1 christos # 45 1.1 christos # CDDL HEADER START 46 1.1 christos # 47 1.1 christos # The contents of this file are subject to the terms of the 48 1.1 christos # Common Development and Distribution License, Version 1.0 only 49 1.1 christos # (the "License"). You may not use this file except in compliance 50 1.1 christos # with the License. 51 1.1 christos # 52 1.1 christos # You can obtain a copy of the license at Docs/cddl1.txt 53 1.1 christos # or http://www.opensolaris.org/os/licensing. 54 1.1 christos # See the License for the specific language governing permissions 55 1.1 christos # and limitations under the License. 56 1.1 christos # 57 1.1 christos # CDDL HEADER END 58 1.1 christos # 59 1.1 christos # BUGS: 60 1.1 christos # - First output may not contain all zones due to how loops are achieved. 61 1.1 christos # Check for newer versions. 62 1.1 christos # 63 1.1 christos # Author: Brendan Gregg [Sydney, Australia] 64 1.1 christos # 65 1.1 christos # 11-May-2005 Brendan Gregg Created this. 66 1.1 christos # 26-Jul-2005 " " Improved code. 67 1.1 christos # 08-Jan-2006 " " Last update. 68 1.1 christos # 69 1.1 christos 70 1.1 christos 71 1.1 christos ############################## 72 1.1 christos # --- Process Arguments --- 73 1.1 christos # 74 1.1 christos 75 1.1 christos ### default variables 76 1.1 christos opt_time=0; interval=1; counts=1 77 1.1 christos 78 1.1 christos ### process options 79 1.1 christos while getopts ht name 80 1.1 christos do 81 1.1 christos case $name in 82 1.1 christos t) opt_time=1 ;; 83 1.1 christos h|?) cat <<-END >&2 84 1.1 christos USAGE: zvmstat [-ht] [interval [count]] 85 1.1 christos zvmstat # default output 86 1.1 christos -t # print times 87 1.1 christos eg, 88 1.1 christos zvmstat 1 # print every 1 second 89 1.1 christos zvmstat 10 5 # print 5 x 10 second samples 90 1.1 christos zvmstat -t 5 # print every 5 seconds with time 91 1.1 christos END 92 1.1 christos exit 1 93 1.1 christos esac 94 1.1 christos done 95 1.1 christos shift $(( OPTIND - 1 )) 96 1.1 christos 97 1.1 christos ### option logic 98 1.1 christos if (( "0$1" > 0 )); then 99 1.1 christos interval=$1; counts=-1; shift 100 1.1 christos fi 101 1.1 christos if (( "0$1" > 0 )); then 102 1.1 christos counts=$1; shift 103 1.1 christos fi 104 1.1 christos 105 1.1 christos 106 1.1 christos ################################# 107 1.1 christos # --- Main Program, DTrace --- 108 1.1 christos # 109 1.1 christos dtrace -n ' 110 1.1 christos #pragma D option quiet 111 1.1 christos #pragma D option destructive 112 1.1 christos #pragma D option switchrate=10 113 1.1 christos 114 1.1 christos /* 115 1.1 christos * Command line arguments 116 1.1 christos */ 117 1.1 christos inline int OPT_time = '$opt_time'; 118 1.1 christos inline int INTERVAL = '$interval'; 119 1.1 christos inline int COUNTER = '$counts'; 120 1.1 christos 121 1.1 christos /* 122 1.1 christos * Initialise variables 123 1.1 christos */ 124 1.1 christos dtrace:::BEGIN 125 1.1 christos { 126 1.1 christos secs = INTERVAL; 127 1.1 christos counts = COUNTER; 128 1.1 christos zonemax = 0; 129 1.1 christos listing = 1; 130 1.1 christos re[""] = 0; pi[""] = 0; po[""] = 0; 131 1.1 christos mf[""] = 0; sr[""] = 0; fr[""] = 0; 132 1.1 christos epi[""] = 0; epo[""] = 0; epf[""] = 0; 133 1.1 christos api[""] = 0; apo[""] = 0; apf[""] = 0; 134 1.1 christos fpi[""] = 0; fpo[""] = 0; fpf[""] = 0; 135 1.1 christos } 136 1.1 christos 137 1.1 christos /* 138 1.1 christos * Build zonelist array 139 1.1 christos * 140 1.1 christos * Here we want the output of a command to be saved into an array 141 1.1 christos * inside dtrace. This is done by running the command, sending the 142 1.1 christos * output to /dev/null, and by probing its write syscalls from dtrace. 143 1.1 christos * 144 1.1 christos * This is an example of a "scraper". 145 1.1 christos */ 146 1.1 christos 147 1.1 christos /* 148 1.1 christos * List zones 149 1.1 christos */ 150 1.1 christos dtrace:::BEGIN 151 1.1 christos { 152 1.1 christos /* run zoneadm */ 153 1.1 christos system("/usr/sbin/zoneadm list > /dev/null; echo END > /dev/null"); 154 1.1 christos } 155 1.1 christos 156 1.1 christos /* 157 1.1 christos * Scrape zone listing 158 1.1 christos */ 159 1.1 christos syscall::write:entry 160 1.1 christos /listing && (execname == "zoneadm") && 161 1.1 christos (curthread->t_procp->p_parent->p_ppid == $pid)/ 162 1.1 christos { 163 1.1 christos /* read zoneadm output */ 164 1.1 christos zonelist[zonemax] = stringof(copyin(arg1, arg2 - 1)); 165 1.1 christos 166 1.1 christos /* increment max number of zones */ 167 1.1 christos zonemax++; 168 1.1 christos } 169 1.1 christos 170 1.1 christos /* 171 1.1 christos * Finish scraping zones 172 1.1 christos */ 173 1.1 christos syscall::write:entry 174 1.1 christos /listing && (execname == "sh") && (ppid == $pid)/ 175 1.1 christos { 176 1.1 christos /* 177 1.1 christos * this end tag lets us know our zonelist has finished. 178 1.1 christos * thanks A. Packer. 179 1.1 christos */ 180 1.1 christos listing = stringof(copyin(arg1, arg2 - 1)) == "END" ? 0 : 1; 181 1.1 christos } 182 1.1 christos 183 1.1 christos /* 184 1.1 christos * Record vminfo counters 185 1.1 christos */ 186 1.1 christos vminfo:::pgrec { re[zonename] += arg0; } 187 1.1 christos vminfo:::as_fault { mf[zonename] += arg0; } 188 1.1 christos vminfo:::scan { sr[zonename] += arg0; } 189 1.1 christos vminfo:::execpgin { epi[zonename] += arg0; } 190 1.1 christos vminfo:::execpgout { epo[zonename] += arg0; } 191 1.1 christos vminfo:::execfree { epf[zonename] += arg0; fr[zonename] += arg0; } 192 1.1 christos vminfo:::anonpgin { api[zonename] += arg0; } 193 1.1 christos vminfo:::anonpgout { apo[zonename] += arg0; } 194 1.1 christos vminfo:::anonfree { apf[zonename] += arg0; fr[zonename] += arg0; } 195 1.1 christos vminfo:::fspgin { fpi[zonename] += arg0; } 196 1.1 christos vminfo:::fspgout { fpo[zonename] += arg0; } 197 1.1 christos vminfo:::fsfree { fpf[zonename] += arg0; fr[zonename] += arg0; } 198 1.1 christos 199 1.1 christos /* 200 1.1 christos * Timer 201 1.1 christos */ 202 1.1 christos profile:::tick-1sec 203 1.1 christos { 204 1.1 christos secs--; 205 1.1 christos } 206 1.1 christos 207 1.1 christos /* 208 1.1 christos * Check for exit 209 1.1 christos */ 210 1.1 christos profile:::tick-1sec 211 1.1 christos /counts == 0/ 212 1.1 christos { 213 1.1 christos exit(0); 214 1.1 christos } 215 1.1 christos 216 1.1 christos /* 217 1.1 christos * Print header line 218 1.1 christos */ 219 1.1 christos profile:::tick-1sec 220 1.1 christos /secs == 0/ 221 1.1 christos { 222 1.1 christos /* set counters */ 223 1.1 christos secs = INTERVAL; 224 1.1 christos counts--; 225 1.1 christos zonei = 0; 226 1.1 christos 227 1.1 christos /* print time */ 228 1.1 christos OPT_time ? printf("\n%Y,\n",walltimestamp) : 1; 229 1.1 christos 230 1.1 christos /* print output line */ 231 1.1 christos printf("%10s %4s %5s %4s %5s %4s %4s %4s %4s %4s %4s %4s %4s %4s\n", 232 1.1 christos "ZONE", "re", "mf", "fr", "sr", "epi", "epo", "epf", "api", "apo", 233 1.1 christos "apf", "fpi", "fpo", "fpf"); 234 1.1 christos 235 1.1 christos /* ensure zone writes are triggered */ 236 1.1 christos printf(" \b"); 237 1.1 christos } 238 1.1 christos 239 1.1 christos /* 240 1.1 christos * Print zone status line 241 1.1 christos * 242 1.1 christos * This is a fairly interesting function in that it loops over the keys in 243 1.1 christos * an associative array and prints out the values. DTrace cant really do 244 1.1 christos * loops, and generally doesnt need to. We "cheat" by generating writes 245 1.1 christos * in the above probe which in turn trigger the probe below which 246 1.1 christos * contains the contents of each loop. Dont do this at home! We are 247 1.1 christos * supposed to use aggreagations instead, wherever possible. 248 1.1 christos * 249 1.1 christos * This is an example of a "feedback loop". 250 1.1 christos */ 251 1.1 christos syscall::write:return 252 1.1 christos /pid == $pid && zonei < zonemax/ 253 1.1 christos { 254 1.1 christos /* fetch zonename */ 255 1.1 christos self->zone = zonelist[zonei]; 256 1.1 christos 257 1.1 christos /* print output */ 258 1.1 christos printf("%10s %4d %5d %4d %5d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n", 259 1.1 christos self->zone, re[self->zone], mf[self->zone], fr[self->zone], 260 1.1 christos sr[self->zone], epi[self->zone], epo[self->zone], 261 1.1 christos epf[self->zone], api[self->zone], apo[self->zone], 262 1.1 christos apf[self->zone], fpi[self->zone], fpo[self->zone], 263 1.1 christos fpf[self->zone]); 264 1.1 christos 265 1.1 christos /* clear values */ 266 1.1 christos re[self->zone] = 0; mf[self->zone] = 0; fr[self->zone] = 0; 267 1.1 christos sr[self->zone] = 0; epi[self->zone] = 0; epo[self->zone] = 0; 268 1.1 christos epf[self->zone] = 0; api[self->zone] = 0; apo[self->zone] = 0; 269 1.1 christos apf[self->zone] = 0; fpi[self->zone] = 0; fpo[self->zone] = 0; 270 1.1 christos fpf[self->zone] = 0; 271 1.1 christos self->zone = 0; 272 1.1 christos 273 1.1 christos /* go to next zone */ 274 1.1 christos zonei++; 275 1.1 christos } 276 1.1 christos ' 277 1.1 christos 278