#!/bin/sh # # This script takes vxstat output, converts it to gnuplot-friendly # data, and then generates the graphs. # # A standard way to get the vxstat output is to run: # # # vxstat -g -i 120 >vxstat. & # # Then, once you've collected a bunch of data, run it through # vxplot: # # (uses default png options in script) # # vxplot -t png vxstat.* # # (uses monochrome png settings for older png) # # vxplot -t "png monochrome; set size 1.5" vxstat.* # # Author: Todd Stansell # # $Id: vxplot,v 1.13 2004-04-13 00:23:47-07 todd Exp $ # BASE=`basename $0` PATH=.:$PATH:/usr/local/bin # most likely gnuplot is in /usr/local/bin outputdir=. # dir where output files should go no=false # run the command? DATA=4 # default data to gather (write ops/sec) AVE=5 # num of datapoints to average LINES=1440 # graph this number of data points # (48 hours with 120 sec data interval) ext=gif # default graph type complete=true # recreate datafile? tmpfile=/tmp/$$.tmpfile # general use tempfile USAGE="usage: $BASE [-n] [-q] [-h] [-d num] [-a num] [-o dir] file ... -n don't run commands -Q quick run (don't recreate datafile) -h help -t type change the graph type that gnuplot produces [$ext] (use 'png-color' if your gnuplot supports color with png) -l num number of data points to graph [$LINES] -a num number of data points to average (smoothing) [$AVE] -d num column number of vxstat data to graph [$DATA] -o dir directory to put graph [$outputdir] file vxstat data files" i=`echo -n a` if [ "X$i" = "Xa" ] ; then N='-n' X='' else N='' X='\c' fi echon () { echo $N "${@}$X" } cleanup() { if [ -n "$tmpfile" ] ; then rm -f $tmpfile fi } # # return true if $1 is a number greater than 0 # isnum(){ expr $1 : '^[0-9]*$' >/dev/null ; status=$? if [ "$status" -eq 0 ] ; then if [ "$1" -gt 0 ] ; then return 0 else echo "$1 must be greater than 0" >&2 return 1 fi else return $status fi } # # Try to figure out what the interval between datapoints is # in a given datafile. We only look at the hh:mm:ss entry, # which should almost always give us the right value. # getinterval() { # Sat Aug 11 10:41:33 2001 cat $1 | \ nawk 'BEGIN {n=0} /^[A-Z]/ && NF==5 { n=n+1 Time[n]=$4 if (n == 2) { split(Time[1],a,/:/) split(Time[2],b,/:/) seca=a[3]+(a[2]*60)+(a[1]*60*24) secb=b[3]+(b[2]*60)+(b[1]*60*24) printf "%d\n",secb-seca exit } }' } # # Convert vxstat datafile to a gnuplot format datafile # usage: vxstat2gnuplot datafile # # Variables used: # DATA = column of vxstat data to extract # AVE = number of datapoints to average (for smoothing) # # Notes: Currently extracts only volume data. # vxstat2gnuplot() { cat $1 | \ nawk ' BEGIN { mon["Jan"]=1 ; mon["Feb"]=2 ; mon["Mar"]=3 ; mon["Apr"]=4 ; mon["May"]=5 ; mon["Jun"]=6 ; mon["Jul"]=7 ; mon["Aug"]=8 ; mon["Sep"]=9 ; mon["Oct"]=10; mon["Nov"]=11; mon["Dec"]=12; test=2; data='$DATA'} /NAME/ { test=2 } # reset when we see headers NF==5 && test>0 { test=test-1 next } # skip timestamps NF==5 && test<1 { b=$2 split($4,a,/:/) ; printf "%04s/%02s/%02s %2s:%2s:%2s",$5,mon[b],$3,a[1],a[2],a[3] } # output date/time in gnuplot-happy format /^vol/ && test<1 { printf " %-7s",$data } # get stats for each vol /^$/ && test<1 { printf "\n" } # new set of data, so new line END { print "END" } # print known ending line # nuke last line, which may be incomplete ' | grep -v "END" | \ # Do a floating average thing to smooth out the lines # vxstat can produce a *very* jaggy graph without this. # (for each data point, average over the past 5 data points...) nawk ' BEGIN { i=0 ; ave='$AVE' } i=ave { printf "%s %s",$1,$2 for (x=3; x<=NF ; x++) { sum=0 for (y=1; y&2 $no || $cmd } ############################################# # BEGIN MAIN PROGRAM ############################################# while getopts nQht:l:d:a:d:o: c; do case $c in l|d|a) if isnum $OPTARG ; then case $c in l) LINES=$OPTARG ;; d) DATA=$OPTARG ;; a) AVE=$OPTARG ;; esac else echo "$OPTARG is not a valid number" >&2 exit 64 fi ;; n) no=true ;; Q) complete=false ;; t) ext=$OPTARG ;; o) outputdir="$OPTARG" ;; h) echo "$USAGE"; exit ;; esac done shift `expr $OPTIND - 1` if [ $# -eq 0 ] ; then echo "Please specify a datafile." echo "$USAGE" exit 1 fi if [ -z "$outputdir" -o ! -d $outputdir ] ; then echo "\"$outputdir\" is an invalid output directory." exit 1 else outputdir=`cd $outputdir && /bin/pwd` fi trap cleanup 1 2 3 5 15 for file in $@ ; do if [ ! -f $file ] ; then echo "$file does not exist." continue fi fname=`basename $file | sed -e 's/vxstat\.//'` gp=$outputdir/$fname.gp INTERVAL=`getinterval $file` # # Extract the data for the disk group # echo "Working on $file..." if $complete || [ ! -s $gp ] ; then echo " Converting datafile and using $LINES data points..." run vxstat2gnuplot $file | tail -${LINES}l >$tmpfile if [ ! -s $tmpfile ] ; then echo " no data...quitting." rm $tmpfile continue fi mv $tmpfile $gp echo fi LINES=`grep -c . $gp` echo " building plot.$fname..." run customplot $gp >$tmpfile cat $tmpfile | sed 's/^/ /' >&2 # show the plot file echo echo " creating graph..." gnuplot $tmpfile err=$? if [ $err -eq 0 ] ; then echo "graph created." else echo "gnuplot exited with error $err." fi rm -f $tmpfile $gp done