#!/usr/bin/env perl # -*-Perl-*- # # iperf-logger - read iperf reports from e-mail and log to a file # # This script reads as input one or more e-mail messages containing # the results of an iperf bandwidth measurement, and produces a one-line # summary suitable for adding to a log file. # # By default the result is sent to stdout, but you can use the flag # -f filename to redirect to a file. This is needed, for example, # if iperf-logger is invoked by smrsh, because smrsh does not allow # command line output redirection (no ">" in a smrsh command line). # # In the future when iperf measurements are stored in a database # there will be an option to write each entry directly to the # database rather than to the flat file. # # # Eric Myers - 4 March 2004 # @(#) $Id: iperf-logger,v 1.6 2005/09/08 19:37:32 myers Exp myers $ ###################################################################### ##use strict; ##use warnings; use Date::Parse; # to parse date of measurement use Date::Format; # to format date for output to the log $/ = "\nFrom " ; # Break at e-mail message boundaries, not lines #################### # Options: #use Getopt::std # command line options #%options=(); #getopts("f:",\%options); require 'getopts.pl'; # perl4 works for me for now... &Getopts("f:"); $logfile = $opt_f; if ( $logfile && -w $logfile) { open(STDOUT,">> $logfile"); } #################### # Main Loop: while (<>) { # scan forward tor next message unit s|^From ||; # remove initial marker s|$/$|\n|; # remove end marker # Get received date from the first header line (the ^From line) ( $who, $RcvdDate ) = /^\s*(\S+)\s+(.*)\n/; ( $Body ) = /\n\n(.*)\z/s ; # maximal matching gets all but headers ( $Headers ) = $`; next if ( ! $Body ); # Parse the headers for date and sending host ( $Date ) = $Headers =~ /^Date: *(.*)/m; if ( ! $Date ) { $Date = $RcvdDate; } $dtime = str2time($Date); $datestr = time2str("%b %e %T", $dtime); ##print "> DATED $Date ==> $datestr \n"; ( $Host ) = $Headers =~ /^Subject: *iperf\@(\S+)/m; $client = $Host; ( $FQDN ) = $Headers =~ /^From: *\S+\@(\S+)/m; if ( $FQDN ) { $client = $FQDN; } # Parse the Body: ( $server, $proto, $port ) = $Body =~ /^Client connecting to (\S+), (\S+) port (\d+)/m; if ( ! $server ) { ( $server ) = $Headers =~ m|\nSubject: .*/iperf -c (\S+)|m; } if ( $proto == "TCP" ) { ( $tcpwin, $Unit ) = $Body =~ /^TCP window size: ([\d\.]+)\s+(\SB)yte/m; $tcpwin = $tcpwin . $Unit; } # Time interval ( $interval, $Unit ) = $Body =~ /\[ ID\] Interval .*\n\[ \d\]\s+0.0-([\d\.]+)\s+(\S)ec/m; $interval = $interval . $Unit; # Transfer ( $transfer, $Unit ) = $Body =~ /\[ ID\].* Transfer .*\n\[ \d\].*\s([\d\.]+)\s+(\SB)ytes/m; $transfer = $transfer . $Unit; # Bandwidth: ( $bw, $Unit ) = $Body =~ m|\n\[ ID\].* Bandwidth.*\n\[ \d\].*\s([\d\.]+)\s+(\S*b)its/sec|m; if ( $bw ) {$bw = $bw . $Unit . "/s";} # host and client names... if ( ! $Host ) { $Host = "unknown"; $ErrCount{"host unknown\n"}++; } if( ! $client) { $client = $Host; $ErrCount{"client unknown\n"}++; } # Report measured bandwidth if ( $bw ) { print "$datestr $Host iperf: $client to $server $proto $bw in $interval $transfer/$tcpwin \n"; } # ...or report errors: elsif ( $Body =~ /error: .*\n/m ) { print "$datestr $Host iperf: $client to $server $&"; $ErrCount{$&}++; } elsif ( $Body =~ /connect failed: .*\n/m ) { print "$datestr $Host iperf: $client to $server $&"; $ErrCount{$&}++; } else { ## print STDERR "> ERROR: cannot parse this message body: \n$Body"; $ErrCount{"cannot parse\n"}++; } } # Summary of Error counting: if ( %ErrCount ) { print STDERR "COUNT\tERROR MESSAGE: \n"; foreach $msg (sort keys(%ErrCount)) { printf(STDERR "%5d\t%s", $ErrCount{$msg}, $msg); } } exit;