Home | History | Annotate | Line # | Download | only in Zones
      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