[comp.sources.d] A local use of perl

bin@rhesus.primate.wisc.edu (Brain in Neutral) (04/24/88)

My humble submission:

Here's a perl script I use here to summarize the mail traffic on
my machine.  I'm sure the level of perl-fluency is pretty barbaric,
since I'm just learning it, but that's how it goes.  Basically, the
script below takes information from the /usr/spool/mqueue/syslog
file, crunches it up and spits out a summary of the number and size
of messages, by category:  local -> local, local -> remote, remote -> local
and remote -> remote.

A message appears in the summary only if there is a from= line matched
by a to= line which has status "Sent" (i.e, those with to= lines having
status "host unknown" or something are considered incomplete).

A local address is considered to be either a user name by itself,
or of the form user@machine, where machine is either rhesus.primate.wisc.edu
(the fully qualified name) or rhesus (the short name).  If that machine
is found, it's stripped off.  Remote names then are those with @ % or ! in
them.

My use of this is to look especially at the volume of local->remote and
remote->local traffic.  I expect this to increase over time as my now-rather-
naive users become aware of the possibilities for inter-machine mail,
in particular, collaboration on manuscripts with colleagues at geographically
distant sites.

Save in a file called "mailstat", chmod to 755.
--- cut here ---
#!/usr/local/perl

#	mailstat - generate rudimentary mail traffic statistics

#	input should be the syslog sendmail lines, but only the columns
#	following the "sendmail:" column.  That should look like:
#	AAnnnnn from=...
#	AAnnnnn to=...
#	^	^
#	msgid	type

#	On Ultrix 1.2 do this:
#	grep sendmail /usr/adm/mqueue/syslog | cut -d" " -f7- | mailstat

#	does not work properly for multiple recipient messages (to=x,y,z)

#	22 April 1988	Paul DuBois	dubois@rhesus.primate.wisc.edu

#	----

#	get the host name (assumes Internet style) so can recognize address
#	with that host as local names and not remote.  Sometimes the host
#	is given as just the short form, so figure that out as the first
#	part of the long name.  Presumably there should be some effort
#	to determine the uucp name as well for similar purposes, but that's
#	not done here.

open (tmp, "hostname|");
$host = <tmp>;
chop ($host);
$shorthost = $host;
$shorthost =~ s/\..*//;
close (tmp);

$sent = 0;
$received = 0;
@id = ();
@from = ();
@size = ();
@to = ();

while (<>)				# for each line...
{
	chop;				# toss newline
	@f = split;			# split into fields
	$mid = $f[0];			# message id
	$type = $f[1];			# message type (message-id, from, to)
	$type =~ y/A-Z/a-z/;		# make sure lowercase
	$mid =~ s/://;			# toss colon
	$id{$mid} = $mid;		# record number
	if ($type =~ /^from/)		# who the message is from
	{
		$type =~ s/^from=(.*),/$1/;	# strip from= and comma
		$type =~ s/^<(.*)>$/$1/;	# strip < > if present
		$type =~ s/@$host//;		# strip local host if present
		$type =~ s/@$shorthost//;	# ditto with short form
		$from{$mid} = $type;		# save sender name
		$f[2] =~ s/^size=(.*),/$1/;	# message size
		$size{$mid} = $f[2];		# save size
		$sent++;
	}
	elsif ($type =~ /^to/)		# who the message is to
	{
		unless ($f[3] =~ /Sent/)	# skip if not Sent (don't want
		{				# "host unknown", etc.)
			next;
		}
		$type =~ s/^to=(.*),/$1/;	# strip to= and comma
		$type =~ s/^<(.*)>$/$1/;	# strip < > if present
		$type =~ s/@$host//;		# strip local host if present
		$type =~ s/@$shorthost//;	# ditto with short form
		$to{$mid} = $type;		# save recipient name
		$received++;
	}
}

#	loop through information, figure out how many of each type of
#	message were found, and compute stats on each

$in = 0;			# incomplete message (either no from or no to)
$nll = $nlr = $nrl = $nrr = 0;	# number of each kind
$sll = $slr = $srl = $srr = 0;	# size of each kind
@keys = keys (id);
for ($i = 0; $i <= $#keys; $i++)
{
	#print $i, " ", $keys[$i], " ";
	#print "from=", $from{$keys[$i]}, " ", "to=", $to{$keys[$i]}, "\n";
	$f = $from{$keys[$i]};
	$t = $to{$keys[$i]};
	$s = $size{$keys[$i]};
	if ($f eq "" || $t eq "")
	{
		#print "incomplete\n";
		$in++;
		next;
	}
	if ($f =~ /[@%!]/)		# remote from
	{
		if ($t =~ /[@%!]/)	# remote to
		{
			#print "remote/remote\n";
			$nrr++;
			$srr += $s;
		}
		else			# local to
		{
			#print "remote/local\n";
			$nrl++;
			$srl += $s;
		}
	}
	else				# local from
	{
		if ($t =~ /[@%!]/)	# remote to
		{
			#print "local/remote\n";
			$nlr++;
			$slr += $s;
		}
		else			# local to
		{
			#print "local/local\n";
			$nll++;
			$sll += $s;
		}
	}
}

sub stats
{
	printf "%s	%4d	%7d	", $_[0], $_[1], $_[2];
	if ($_[1] > 0)
	{
		$_[1] = $_[2]/$_[1];
	}
	printf "%9.2f\n", $_[1];
}

#print "Messages sent: ", $sent, "\n";
#print "Messages received: ", $received, "\n";
print "Messages failed, still queued, or sent by system: ", $in, "\n";

print "message		number	total	bytes/\n";
print "type		msgs	bytes	msg\n";

do stats ("local/local:", $nll, $sll);
do stats ("local/remote:", $nlr, $slr);
do stats ("remote/local:", $nrl, $srl);
do stats ("remote/remote:", $nrr, $srr);
do stats ("total:	", $nll+$nlr+$nrl+$nrr, $sll+$slr+$srl+$srr);