[comp.sources.misc] v02i010: survey - unix system usage profile report

dave@sea375.UUCP (David A. Wilson) (01/20/88)

Comp.sources.misc: Volume 2, Issue 10
Submitted-By: David A. Wilson <dave@sea375.UUCP>
Archive-name: survey

[Not portable to System V directly.  /etc/avenrun hook?  ++bsa]

Survey, is a utility I use to generate a simple plot of system load
and number of users by time. I find it a very useful system management tool.
Survey requires the BSD uptime(1) command.

[I adapted this from a posting several years ago, I do not recall who
the originator was. This is almost a complete rewrite.]

Below is a sample of the output:(line width & scale are command line options)
['L' is load average value, 'U' is number of users logged on.]

Tue Nov  3 00:01:02 PST 1987 uptime19871103
         0                1                2                3                4
         |                |                |                |                |
  9:45pm L
 10:00pm L
 10:15pm L
 10:30pm           L      U
 10:45pm               L  U
 11:00pm                 LU
 11:15pm                 LU
 11:30pm                  L
 11:45pm                  L

Also included is, namedate(1), which I use to generate the current date
in a numeric, but human readable form. It makes a date of the form
YYYYMMDD, which sorts cronologically. I use it mostly to generate dated
filenames.

If you find any problems please tell me about them. If you port it to
any non-BSD system, please send me the changes.

David A. Wilson
...uw-beaver!tikal!slab!sea375!dave  

#------- CUT HERE -----
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	load_chart/README
#	load_chart/survey
#	load_chart/namedate.1
#	load_chart/namedate.c
# This archive created: Sat Nov  7 14:34:21 1987
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(498 characters)'
if test -f 'README'
then
	echo shar: over-writing existing file "'README'"
fi
sed 's/^X//' << \SHAR_EOF > 'README'
XTo run the cpu load and number of users report:
Xsurvey uptime* > loadyyyymm
X
XUsage: survey [fullscale=#] [width=#] uptime_files
X	fullscale	- max value of scale for data(default:see BEGIN{})
X			  if data exceeds fullscale output may exceed width
X	width - number of columns on a line(default:see BEGIN{})
X
XInstall into crontab:
X1 0 * * * date > /usr/local/adm/load_chart/uptime`/usr/local/bin/namedate`
X0,15,30,45 * * * * /usr/ucb/uptime >> /usr/local/adm/load_chart/uptime`/usr/local/bin/namedate`
X
SHAR_EOF
if test 498 -ne "`wc -c 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 498 characters)'
fi
echo shar: extracting "'survey'" '(3299 characters)'
if test -f 'survey'
then
	echo shar: over-writing existing file "'survey'"
fi
sed 's/^X//' << \SHAR_EOF > 'survey'
X#!/bin/awk -f
X# $Header: survey,v 1.7 87/11/07 14:12:42 dave Exp $
XBEGIN {
X	FS = ",";
X	ff = 12;
X	max = 0;
X	fullscale = 4;
X	width = 79;
X	unit = -1;
X	old_filename = "------";
X	blanks = "                                                                                ";
X}
X
X#skip blank lines
X/^$/	{ next; }
X
X#dates start in first column and first letter is always a CAP
X/^[A-Z]/	{ date = $1; next; }
X
X# Page break on a new file
X{
X	if ( FILENAME != old_filename )
X	{
X		# compute units here
X		# so user can set fullscale an width on command line
X		if ( unit < 0 )
X		{
X			unit = int((width-10)/fullscale);
X		}
X		old_filename = FILENAME;
X		printf( "%c\n%s %s\n", ff, date, FILENAME );
X		printf( "         0" );
X		for ( i=1; i<=fullscale; i++ )
X		{
X			numstr = sprintf( "%d", i );
X			printf( "%s%s", \
X				substr( blanks, 1, (unit-length(numstr)) ), \
X				numstr );
X		}
X		printf( "\n         |" );
X		for ( i=0; i<fullscale; i++ )
X		{
X			printf( "%s|", substr( blanks, 1, unit-1 ) );
X		}
X		printf( "\n" );
X	} 
X
X	# the load average for the last 15min period is always the last field
X	if ( NF == 5 )
X	{
X		avg = $NF;
X		user_field = $2;
X	}
X	else
X	{
X		avg = $NF;
X		user_field = $3;
X	}
X	time = substr($0, 1, 8);
X	if ( exist[time] != 1 )
X	{
X		exist[time] = 1;
X		t[++max] = time;
X	}
X	# compute position for user & loadavg
X	nsplit = split( user_field, xusers, " " );
X	pusers = int( unit * xusers[1] );
X	lavg = int(avg * unit);
X
X	sum[time] += avg;
X	count[time]++;
X	users_sum[ time ] += xusers[1];
X
X	# test for max users and max average
X	if ( avg > max_avg )
X	{
X		max_avg = avg;
X		max_avg_date = date;
X		max_avg_time = time;
X	}
X	if ( xusers[1] > max_users )
X	{
X		max_users = xusers[1];
X		max_users_date = date;
X		max_users_time = time;
X	}
X
X	#find max of pusers and lavg
X	if ( pusers > lavg )
X	{
X		printf( "%8s %s%s%s%s\n", \
X			time, substr( blanks, 1, lavg ), "L", \
X			substr( blanks, 0, pusers-lavg-1 ), "U" );
X	}
X	else if ( pusers < lavg )
X	{
X		printf( "%8s %s%s%s%s\n", \
X			time, substr( blanks, 1, pusers ), \
X			"U", substr( blanks, 0, lavg-pusers-1 ), "L" );
X	}
X	else
X	{
X		printf( "%8s %s%s\n", time, substr( blanks, 1, lavg ), "L" );
X	}
X}
X
XEND {
X	printf( "%c\nAVERAGE\n", ff );
X	printf( "         0" );
X	for ( i=1; i<=fullscale; i++ )
X	{
X		numstr = sprintf( "%d", i );
X		printf( "%s%s", substr( blanks, 1, (unit-length(numstr)) ), \
X			numstr );
X	}
X	printf( "\n         |" );
X	for ( i=0; i<fullscale; i++ )
X	{
X		printf( "%s|", substr( blanks, 1, unit-1 ) );
X	}
X	printf( "\n" );
X
X	for ( j = 1; j <= max; j++ )
X	{
X		time = t[j];
X		if (count[time] == 0)
X		{
X			avg = 0;
X			user_avg = 0;
X		}
X		else
X		{
X			avg = sum[time]/count[time];
X			user_avg = users_sum[time]/count[time];
X		}
X		pusers = int( unit * user_avg );
X		lavg = int(avg * unit);
X		#find max of pusers and lavg
X		if ( pusers > lavg )
X		{
X			printf( "%8s %s%s%s%s\n", \
X				time, substr( blanks, 1, lavg ), "L", \
X				substr( blanks, 0, pusers-lavg-1 ), "U" );
X		}
X		else if ( pusers < lavg )
X		{
X			printf( "%8s %s%s%s%s\n", \
X				time, substr( blanks, 1, pusers ), "U", \
X				substr( blanks, 0, lavg-pusers-1 ), "L" );
X		}
X		else
X		{
X			printf( "%8s %s%s\n", \
X				time, substr( blanks, 1, lavg ), "L" );
X		}
X	}
X	print "";
X	print "max_load = ", max_avg, max_avg_date, max_avg_time;
X	print "max_users = ", max_users, max_users_date, max_users_time;
X}
SHAR_EOF
if test 3299 -ne "`wc -c 'survey'`"
then
	echo shar: error transmitting "'survey'" '(should have been 3299 characters)'
fi
chmod +x 'survey'
echo shar: extracting "'namedate.1'" '(604 characters)'
if test -f 'namedate.1'
then
	echo shar: over-writing existing file "'namedate.1'"
fi
sed 's/^X//' << \SHAR_EOF > 'namedate.1'
X.TH NAMEDATE 1 VAX/11
X.UC 4
X.SH NAME
Xnamedate \- print a string followed by current date
X.SH SYNOPSIS
X.B namedate
X.RB "[ name ]"
X.SH DESCRIPTION
XIf no argument is given, the current date is printed.
XIf an argument is given, the argument followed immediately by
Xthe current date is printed. The format of the date is:
X.I 'yyyymmdd'
X, where
X.I yyyy
Xis the four digits of the year;
X.I mm
Xis the month number; and
X.I dd
Xis the day number in the month.
XFor example:
X.IP
X.B
Xnamedate junk
X.PP
Xprints
X.B junk19820429.
X.PP
X.B namedate
Xwith no argument is equivalent to 
X.B namedate
X"".
X.SH AUTHOR
XDavid A. Wilson
SHAR_EOF
if test 604 -ne "`wc -c 'namedate.1'`"
then
	echo shar: error transmitting "'namedate.1'" '(should have been 604 characters)'
fi
echo shar: extracting "'namedate.c'" '(1052 characters)'
if test -f 'namedate.c'
then
	echo shar: over-writing existing file "'namedate.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'namedate.c'
X#include <stdio.h>
X#include <sys/time.h>
X/* namedate ---
X *	Given a string as the parameter, it writes to stdout a string
X *	composed of the input string with a the current date appended
X *	to the end of the string. The format of the output string is:
X *		'namestringYYYYMMDD'
X *	where 'namestring' is the first parameter to namedate, 'YYYY'
X *	is the full year number, 'MM' is the month number, 'DD' is the
X *	day of the month number.
X*/
Xmain( ac, av )
Xint ac;
Xchar *av[];
X{
X	char *name;			/* name string */
X	long	c;			/* time counter value */
X	struct tm *s;		/* decoded time structure */
X
X	/* check for valid number of args */
X	switch ( ac )
X	{
X	case 0:
X	case 1: name = (char *)0; break;	/* null name */
X	case 2: name = av[1]; break;		/* use arg 1 string */
X	default: fprintf( stderr, "Usage: namedate name\n" ); exit(1);
X	}
X
X	/* get time counter */
X	c = time(0);
X
X	/* decode into time structure */
X	s = localtime( &c );
X
X	/* print out the name parameter and date */
X	printf( "%s%04d%02d%02d\n",
X		name, s->tm_year+1900, s->tm_mon+1, s->tm_mday );
X}
SHAR_EOF
if test 1052 -ne "`wc -c 'namedate.c'`"
then
	echo shar: error transmitting "'namedate.c'" '(should have been 1052 characters)'
fi
#	End of shell archive
exit 0
-- 
	David A. Wilson
	uw-beaver!tikal!slab!sea375!dave