Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

(code) Net::SNMP, Bandwidth, GnuPlot, PNG, PostScript, Excel

by ybiC (Prior)
on Oct 29, 2001 at 22:26 UTC ( [id://121950]=sourcecode: print w/replies, xml ) Need Help??
Category: Networking Code
Author/Contact Info ybiC
Description: Query SNMP-enabled devices for interface (in|out)put octets, ifSpeed, ifName.   Creates chart of %bandwidth vs. time in PNM, PNG, and/or PostScript formats.   Raw data in CSV, tab-delimited, and/or Excel formats.

Intended for spotchecks or periodic monitoring of individual interfaces.   Tools like MRTG, MCSview, SNMPc, CWSI do well for large number of ports.

Sample graph output temporarily on my homenode pix.   As always... critique, comments, and suggestions are welcome and appreciated.

Usage:
snmpiio.pl target ifIndex iterations delay outdir

target: an IPaddress, DNS name, or FQDN.
ifIndex: SNMP parameter specifying port or interface.
iterations: how many queries you wish to run. (minimum 3, default 4)
delay: seconds to wait between iterations. (minimum 10, default 30)
outdir: destination dir for outfile. No trailing '/'. (default '.')

Example:
snmpiio.pl routerC 7 600 30 MyString /datadir

From a Perlish standpoint, this has been an exercise in hashes instead of arrays, return values, constants, eval, ${var}blah, and STDOUT hot.   Is a significant rewrite of "(code)) Net::SNMP bandwidth query (deprecated by node 121950)".

P.S.   I did not copy this idea from djw's "Ethernet Utilization".   Honest, I didn't, I swear.   Hey, put that phone down!   No, wait - don't call vroom!   ;^D

Update: 2001-10-31 corrected a tyop and clarified verbage in the Description

#!/usr/bin/perl -w


# snmpiio.pl

# pod at tail


$|++;
use strict;
use Net::SNMP;
use Tie::IxHash;


use constant SECS_PER_MIN  => 60;
use constant SECS_PER_HR   => 3600;
use constant SECS_PER_DAY  => 86400;
use constant SECS_PER_WEEK => 604800;


######################################################################
+####
# Edit defaults, options, and binaries to suit your environment:
######################################################################
+####
my $target  = shift or Usage();
my $ifIndex = shift or Usage();
my $iters   = (shift or 4);
my $delay   = (shift or 30);
my $outdir  = (shift or '.');
my %opt =(
   community => 'public',
   tmpdir    => '/tmp',
   timeout   => 15,
   port      => 161,
   p2p       => '-compression 9',
);


# Chart::Graph uses system(gnuplot). I borrowed some ideas from it.
# Maybe can use GD (no system calls) when Debian 3.0 releases.
my %bin = (
   gnp => '/usr/bin/gnuplot',
   p2p => '/usr/bin/pnmtopng',
   prt => '/usr/local/bin/pdq',
);


######################################################################
+####
# Muck over the input:
######################################################################
+####
# These are standard OIDs, so should work 'most anywhere.
tie my %oid, "Tie::IxHash";
%oid = (
   ifName      => ".1.3.6.1.2.1.31.1.1.1.1.$ifIndex",
   ifSpeed     => ".1.3.6.1.2.1.2.2.1.5.$ifIndex",
   ifInOctets  => ".1.3.6.1.2.1.2.2.1.10.$ifIndex",
   ifOutOctets => ".1.3.6.1.2.1.2.2.1.16.$ifIndex",
);


# date-stamped filenames for uniquity.
my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
my %stamp;
$stamp{start} = DateTime();
$stamp{ymd}   = sprintf("%04d%02d%02d",$year+1900,$mon+1,$mday);
tie my %file, "Tie::IxHash";
%file = (
   gnpOpt => "$opt{tmpdir}/$target-$ifIndex-$stamp{ymd}.gnpOpt",
   tmp    => "$outdir/$target-$ifIndex-$stamp{ymd}.tmp",
   csv    => "$outdir/$target-$ifIndex-$stamp{ymd}.csv",
   xls    => "$outdir/$target-$ifIndex-$stamp{ymd}.xls",
   tab    => "$outdir/$target-$ifIndex-$stamp{ymd}.tab",
   ps     => "$outdir/$target-$ifIndex-$stamp{ymd}.ps",
   pnm    => "$outdir/$target-$ifIndex-$stamp{ymd}.pnm",
   png    => "$outdir/$target-$ifIndex-$stamp{ymd}.png",
);


# Sanity-checks, not untainting:
Usage() unless (
   $target  =~ (/\w+/) and
   $ifIndex =~ (/\d+/) and
   $iters   =~ (/\d+/) and
   $delay   =~ (/\d+/) and
   $outdir  =~ (/.*/)
);
unless($iters >= 3) { 
   print "\n\nSorry, minimum iterations allowed is 3.\n\n";
   exit 1;
}
unless($delay >= 10) { 
   print "\n\nSorry, minimum delay allowed is 10.\n\n";
   exit 1;
}
unless(-d $outdir) { 
   print "\n\nSorry, $outdir isn't an existing directory.\n\n";
   exit 1;
}
unless(-w $outdir) { 
   print "\n\nSorry, you don't have write perms for $outdir.\n\n";
   exit 1;
}


# Provide estimate of total runtime:
my %run;
$run{secs} = $iters * $delay;
$run{est}  = $run{secs};
$run{unit} = 'seconds';

if($run{secs} > SECS_PER_MIN) {
   $run{est} = $run{secs}/SECS_PER_MIN;
   $run{est} = sprintf("%.0f",$run{est});
   if($run{est} == 1.0) {
      $run{est}  = 1;
      $run{unit} = 'minute';
   } else { $run{unit} = 'minutes'; }
}
if($run{secs} > SECS_PER_HR) {
   $run{est} = $run{secs}/SECS_PER_HR;
   $run{est} = sprintf("%.1f",$run{est});
   if($run{est} == 1.0) {
      $run{est}  = 1;
      $run{unit} = 'hour';
   } else { $run{unit} = 'hours'; }
}
if($run{secs} > SECS_PER_DAY) {
   $run{est} = $run{secs}/SECS_PER_DAY;
   $run{est} = sprintf("%.1f",$run{est});
   if($run{est} == 1.0) {
      $run{est}  = 1;
      $run{unit} = 'day';
   } else { $run{unit} = 'days'; }
}
if($run{secs} > SECS_PER_WEEK) {
   $run{est} = $run{secs}/SECS_PER_WEEK;
   $run{est} = sprintf("%.1f",$run{est});
   if($run{est} == 1.0) {
      $run{est}  = 1;
      $run{unit} = 'week';
   } else { $run{unit} = 'weeks'; }
}


# Files writable only by this user for security purposes:
# Delete pre-existing out file because subsequent writes append:
print "\nStart run of $0\n",
      "  $stamp{start}\n",
      "  $target  ifIndex $ifIndex\n",
      "  $iters runs at ${delay} second intervals\n",
      "  $run{est} $run{unit} estimated runtime\n",
      ;
umask oct 133;
print "    Clean up old file(s)...\n";
for(keys %file){ Unlink($file{$_}, 'verbose'); }


# Leading '#' so gnuplot will ignore non-data header:
print "    Print csv header...";
open (CSV, ">$file{csv}") or die "Error opening $file{csv}: $!";
print (CSV "# EpochSec,\%rcvUtil,\%xmitUtil,\n") or die
   "Error printing to $file{csv}: $!";
close CSV or die "Error closing $file{csv}: $!";
print "  done!\n";


######################################################################
+####
# Get down to business:
######################################################################
+####
print "    Query target device... ";
my $i = 1;
for(1..$iters) {
   open (TMP, ">>$file{tmp}") or die "Error opening $file{tmp}: $!";

   # Prepend epoch seconds to each csv line:
   $stamp{epoch} = time;
   print(TMP "$stamp{epoch},") or die "Error printing to $file{tmp}: $
+!";

   # Here's where da *real* stuf happens: 
   my $session = Net::SNMP->session(
      -hostname  => $target,
      -community => $opt{community},
      -port      => $opt{port},
      -timeout   => $opt{timeout},
   );
   unless (defined($session)) {
      print TMP ("SNMP SESSION ERROR,")
         or die "Error printing to $file{tmp}: $!";
   }
   for my $value(keys %oid) {
      if (defined(my $response = $session->get_request($oid{$value})))
+ {
         print(TMP $response->{$oid{$value}})
            or die "Error printing to $file{tmp}: $!";
      }
      else { print (TMP '0') or die "Error printing to $file{tmp}: $!"
+; }
      print (TMP ',') or die "Error printing to $file{tmp}: $!";
   }
   $session->close();

   # Activity indicator:
   # One line per iteration:
   # End of iteration:
   # Delay between iterations, but not after last iteration:
   ## print '.';
   print (TMP "\n") or die "Error printing to $file{tmp}: $!";
   close TMP or die "Error closing $file{tmp}: $!";
   sleep $delay unless($i==$iters);
   $i++;
}
print "  done!\n";


# $ifName is global so available later, outside of this block.
my $ifName;
print "    Calculate receive and transmit %utilization...";
{
   # Contained block to limit 'print csv with $,':
   # Initialize prior array to 0 to avoid annoying 'not numeric' error
+:
   local $, = ',';
   my @prior = (0) x 5;
   open (TMP, "<$file{tmp}")  or die "Error opening $file{tmp}: $!";
   open (CSV, ">>$file{csv}") or die "Error opening $file{csv}: $!";
   while(<TMP>) {
      chomp;
      my @data = split ',';
      # Subtract epochSecs for deltaTime:
      # Protect against 'divide by zero' error:
      my $time      = $data[0];
      my $priortime = $prior[0];
      my $dtime     = $time - $priortime;
      next unless $dtime;
      $ifName           = $data[1];
      my $ifSpeed       = $data[2];
      my $inBytes       = $data[3];
      my $outBytes      = $data[4];
      my $priorInBytes  = $prior[3];
      my $priorOutBytes = $prior[4];
      # Handle counter-roll-over-to-zero in approximate fashion,
      # and prevent 'divide by zero' error if no OID response:
      $priorInBytes  = 1 if(   
         ($inBytes  < $priorInBytes) or ($priorInBytes  == 0)
      );
      $priorOutBytes  = 1 if( 
         ($outBytes  < $priorOutBytes) or ($priorOutBytes  == 0)
      );
      $ifSpeed = 1 if($ifSpeed == 0);
      my $rBytes  = $inBytes - $priorInBytes;
      my $xBytes  = $outBytes - $priorOutBytes;
      my $rutil   = CalcUtil($rBytes,$dtime,$ifSpeed);
      my $xutil   = CalcUtil($xBytes,$dtime,$ifSpeed);
      # No valid data (delta) on first iteration, so skip it.
      if($prior[2] > 0) { 
         print CSV "$time,$rutil,$xutil,\n"
            or die "Error printing to $file{csv}: $!";
      }
      # Set current values for 'prior' on next iteration:
      @prior = @data;
   }
   close (TMP) or die "Error closing $file{tmp}: $!";
   close (CSV) or die "Error closing $file{csv}: $!";
}
($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
$stamp{done} = DateTime();
print "  done!\n";


######################################################################
+####
# Output formatting:
######################################################################
+####
if(-x $bin{gnp} && -B _) {
   # Tab-delimited for feeding to gnuplot:
   print "    Create tab-delimited outfile from csv...";
   open (CSV, "<$file{csv}")  or die "Error opening $file{csv}: $!";
   open (TAB, ">>$file{tab}") or die "Error opening $file{tab}: $!";
   while(<CSV>) {
      s/,/    /g;
      print TAB or die "Error printing to $file{tab}: $!";
   }
   close (CSV) or die "Error closing $file{csv}: $!";
   close (TAB) or die "Error closing $file{tab}: $!";
   print "  done!\n";

   # Create option file for gnuplot:
   #   "plot \"$file{tab}\" using 1:2, \"$file{tab}\" using 1:3, \"$fi
+le{tab}\" using 1:4",
   print "    Create gnuplot option file...";
   my @gnpOpt = (
      'set data style lines',
      "set title \"$target port $ifName ifIndex $ifIndex  -  $iters ru
+ns at $delay second intervals\"",
      "set key title \"Receive, Transmit\"",
      "set xlabel \"$stamp{start}  through  $stamp{done}\"",
      'set ylabel "%bandwidth"',
      'set grid',
      'set noxtics',
      'set terminal postscript',
      "set output \"$file{ps}\"",
      "plot \"$file{tab}\" using 1:2, \"$file{tab}\" using 1:3",
      'set terminal pbm',
      "set output \"$file{pnm}\"",
      'replot',
      'set terminal postscript',
      "set output \"|$bin{prt}\"",
      'replot',
   );
   open (GNPOPT, ">$file{gnpOpt}") or die "Error opening $file{gnpOpt}
+: $!";
   for(@gnpOpt){
      print (GNPOPT "$_\n") or die "Error printing to $file{gnuOpt}: $
+!";
   }
   close GNPOPT or die "Error closing $file{gnpOpt}: $!";
   print "  done!\n";

   # Create chartfiles from tab-delim data with gnuplot:
   if ((-r $file{gnpOpt} && -T _) and (-x $bin{gnp})) {
      print "    Create PNM+PS graphs from tab-delimited...";
      system("$bin{gnp} $file{gnpOpt}")
         and die "Error running $bin{gnp}: $?";
      print "  done!\n";
   }

   # Create PNG from PNM with pnmtopng: 
   if ((-r $file{pnm} && -B _) and (-x $bin{p2p})) {
      print "    Create PNG graph from PNM...";
      system("$bin{p2p} $opt{p2p} $file{pnm} > $file{png}")
         and die "  Error running $bin{p2p}: $?";
      print "  done!\n";
   }
}


# Create xls from csv *if* Spreadsheet::WriteExcel module installed.
my $have_SWE;
BEGIN {
   $have_SWE = 0;
   eval { require Spreadsheet::WriteExcel };
   unless ($@) {
      Spreadsheet::WriteExcel->import();
      $have_SWE = 1;
   }
}
if ($have_SWE == 1) {
   print "    Create xls outfile from csv...";
   open (CSVFILE, $file{csv}) or die "Error opening $file{csv}: $!";
   my $workbook  = Spreadsheet::WriteExcel -> new($file{xls});
   my $worksheet = $workbook -> addworksheet();
   my $row      = 0;
   while (<CSVFILE>) {
      chomp;
      my @field = split(',', $_);
      my $column = 0;
      foreach my $token (@field) {
         $worksheet -> write($row, $column, $token);
         $column++;
      }
      $row++;
   }
   my $format1 = $workbook -> addformat();
   $format1   -> set_bold();
   $format1   -> set_align('center');
   $format1   -> set_bg_color('tan');
   $worksheet -> set_row(0, undef, $format1);
   $workbook  -> close() or die "Error closing $workbook: $!";
   print "  done!\n";
}


######################################################################
+####
# Conditional cleanup of temp files:
######################################################################
+####
print "    Clean up temp file(s)...\n";
if(-e $file{csv} && -B_){
   Unlink($file{gnpOpt}, 'verbose');
   Unlink($file{tmp},    'verbose');
}
if(-e $file{xls} && -B_){
   Unlink($file{csv}, 'verbose');
}
if(-e $file{ps} && -T_){
   Unlink($file{xls}, 'verbose');
   Unlink($file{tab}, 'verbose');
   Unlink($file{pnm}, 'verbose');
}
if(-e $file{png} && -B_){
   Unlink($file{ps},  'verbose');
}


# Bring it on home:
print "Run complete of $0.\n",
      "  $stamp{done}\n";
for(keys %file){
   print "  $file{$_}\n" if(-e $file{$_});
}
print "\n\n";
exit 0;


######################################################################
+#####
# Subroutines:
######################################################################
+#####
# for Start/Done times
sub DateTime {
   my $DateTime = sprintf(
      "%04d-%02d-%02d %02d:%02d:%02d",
      $year+1900,$mon+1,$mday,$hour,$min,$sec
   );
}
######################################################################
+#####
# Octets to %bandwidth calculations:
sub CalcUtil {
   my $Bytes  = $_[0];
   my $secs   = $_[1];
   my $speed  = $_[2];
   my $MBytes = $Bytes / 1048576;
   my $Mbits  = $MBytes * 8;
   my $Mbps   = $Mbits / $secs;
   # * 100      convert decimal to percent
   # * 1000000  move decimal point to match $speed
   # * 1.048576 bits per Megabit
   my $util   = ($Mbps * 100 * 1000000) / ($speed * 1.048576);
   # Avoid reported util > %100 after 1 or more no response:
   $util /= 2 while $util > 100;
   # Round output, but not @data(next iteration's @prior):
   my $utilRound   = sprintf("%.3f",$util);
}
######################################################################
+#####
# Delete outfiles from prior run (if same name as this run):
sub Unlink {
   my $file = $_[0];
   my $echo = $_[1];
   if (-e $file && -w _) {
      print "      unlink $file" if ($echo eq 'verbose');
      unlink $file or die "Error unlinking $file: $!";
      print " -- *poof*\n" if ($echo eq 'verbose');
   }
}
######################################################################
+#####
sub Usage {
   print "


Ooot!
You forgot to enter necessary information, or entered bad information!


Usage:
snmpiio.pl target iterations delay ifIndex outdir

target:     an IPaddress, DNS name, or FQDN.
ifIndex:    SNMP parameter specifying port or interface.
iterations: how many queries you wish to run.      (minimum 3, default
+ 4)
delay:      seconds to wait between iterations.  (minimum 10, default 
+30)
outdir:     destination dir for outfile.  No trailing '/'.  (default '
+.')


Example:
snmpiio.pl routerC 7 600 30 /datadir


This script              $0
Net::Snmp                $Net::SNMP::VERSION
Tie::IxHash              $Tie::IxHash::VERSION
Spreadsheet::WriteExcel  $Spreadsheet::WriteExcel::VERSION
Perl                     $]
Local OS                 $^O


";
   exit 1;
}
######################################################################
+#####


=head1 NAME

 snmpiio.pl

=head1 SYNOPSIS

 Query SNMP-enabled devices for interface (in|out)put octets.
 Output files in csv, tab-delimited, pnm, and png formats.

 Intended for spotchecks or periodic monitoring of individual interfac
+es.
 Tools like MRTG, MCSview, SNMPc, CWSI do well for large number of por
+ts.

 snmpiio.pl target iterations delay ifIndex outdir

 target:     an IPaddress, DNS name, or FQDN.
 ifIndex:    SNMP parameter specifying port or interface.
 iterations: how many queries you wish to run.      (minimum 3, defaul
+t 4)
 delay:      seconds to wait between iterations.  (minimum 10, default
+ 30)
 outdir:     destination dir for outfile.  No trailing '/'.  (default 
+'.')

 Example:
 snmpiio.pl routerC 7 600 30 MyString /datadir

 Assorted conversions:
 2880 iterations  30 sec delay = 24 hours
 8640 iterations  30 sec delay = 3 days
 20160 iterations 30 sec delay = 7 days
 40320 iterations 30 sec delay = 14 days

 100Mbps = 12.5MBps

 1GB     = 8,589,934,592 bits (1,073,741,824 * 8)
 1MB     = 8,388,608 bits     (1,048,576 * 8)
 1KB     = 8,192 bits         (1024 * 8)

 1Gb     = 1,073,741,824 bits (1024-e3)
 1Mb     = 1,048,576 bits     (1024-e2)
 1Kb     = 1,024 bits         (1024-e1)

 ifInOctets+ifOutOctets      = Bytes
 ((Bytes*8)/1024)/seconds    = Kbps
 ((Bytes*8)/1048576)/seconds = Mbps

=head1 TESTED

 Perl 5.00503      Debian 2.2r3

 Net::SNMP   3.6
 Tie::IxHash 1.21
 Spreadsheet::WriteExcel 0.31

 Gnuplot     3.71
 pnmtopng    2.37.4-1
 Excel 2000  9.0.3821 SR-1

=head1 UPDATED

 2001-10-29   11:00 CDT
   Post to PerlMonks.
   Fix time est errs - include $run{est} = $run{secs} in each if loop.
   Remove default value (2) for ifIndex, update Usage()+pod.
   Include ifIndex in gnuplot title.

 2001-10-26   16:40 CDT
   Hashimafy passel o'scalars so fewer global vars.
   Add "or die" where missing on couple print(FILE) lines.
   Easy-to-read estimate of run duration.
     Suggested by Zaxo:
      (cleaner syntax, but not quite the output wanted)
     print int($run-secs / SECS_PER_WEEK), ' week(s), ';
     print int($run-secs / SECS_PER_DAY),  ' day(s), ';
     print int($run-secs / SECS_PER_HR),   ' hour(s), ';
     print int($run-secs / SECS_PER_MIN),  ' minute(s), ';
   Minimum iterations of 3, to provide 2 data-points.
   Minimum delay of 10 seconds, to prevent target CPU saturation.
   Use named scalar instead of $data[0], $prior[0].
   Prevent %util > 100 (if no response 1 or more times).
   Calc + display HDX utilization (rcv + xmit).
   Retest Excel file.
   %files for all file handling to eliminate redundent data of arrays.
   Eliminate duplicate (start|done)stamp snippets with DateTime().
   Print Perl+module+OS versions at Usage().
   Replace @unlinkStart with keys of %file.
   Add $ifName so can print module/port in outfile header.
   STDOUT hot so messages appear promptly.
   Conditional Unlink of tempfiles at wrap-up.
   Round %util to 3 decimal points.
   Subamify duplicate bw calculations.
   Gnuplot key title.
   Additional filechecks in PNM, PNG creation.
   Process receive/transmit data separately.
   Print PostScript outfile with pdq.
   Automate output graph with gnuplot+pnmtopng.


 2001-10-18   16:45 CDT
   Separate $outdir -d and -w filechecks and messages.
   Use hash instead of array for OIDs: OID key=name, value=numeric OID
+.
   Prep for future gnuplot outfile:
     Add human-readable $startstamp and $donestamp.
     Change outfile to tab-delimited (was csv).
   Debug unwanted column 7 in outfile - epochsecs of endtime.
   Indenting to PerlStyle recommendation.
   Fix minor tyops.
   Rename to "snmpiio.pl" from "netsnmpiio.pl".
   Unlink .tmp at end of run.
   Confirm counter-roll-over-to-zero Does The Right Thing.
   No xls outfile if Spreadsheet::WriteExcel module not installed.
   Fix broken %util calculation.
   Correct minor tyops.
   Display MBytes transferred.
   Gracefully handle non-responsive (host|OID):
     (MBytes|Mbps|%Util) = -0.000
   Snmp query syntax cleaner.
   Don't print snmp query or session errors.
   Fix incorrect Bps calculations.
   Create xls outfile from csv.
   Correct error in Usage and pod.

 2001-08-13   10:35 CDT
   Gracefully handle counter-roll-over-to-zero;
     ~4,000,000,000 on CatOS 5.
     Cisco CatOS 5
     Report 'blade #/port #' instead of '10/100 utp ethernet (cat 3/5)
+'.
   Test with ActivePerl on Win2k.
   Fix sundry tyops.
   Post to PerlMonks networking code (requesting critique).
   Net::SNMP instead of UCD-SNMP system call:
   Initialize 'prior' array at '0' to
     eliminate annoying 'not numeric' message.
   Fix bad conversion math in pod.

 2001-08-11   22:50 CDT
   Add example temp+csv output to pod.
   Round Bps to 0 decimal places.
   Round %util to 4 decimal places (100ths of %).
   Utilization percentage calculations, corrected for MegaBytes.
   Bypass bogus first Bps output since no prior epochSec.
   Bps calculations from raw SNMP data.
   Query ifSpeed for %util calculations.
   Defaults for all input values except target.
   Sanity-check $outdir: letters, numbers, dots, dashes, underscores.
   Filetest for write in outdir and outdir *is* directory.
   Simplify iteration localtime syntax.
   Cleaner syntax for no sleep after last iteration.
   Debug errant commas in csv.
   Unsubify snmp query localtime+time since only called once.
   @raw array instead of initial temp file.
   Filename of target-ifIndex-yyyymmdd.csv.
   Add hostname,oid,ifIndex to csv output.
   Use PcTime return values (print the values in main).
   Add $outdir.
   Sanity-check input for (wordchars|numbers) as appropriate.
   More informative Usage().
   Input from commandline instead of hardcoded.
   Efforts to improve data structure.
   No sleep after last iteration.
   Leading-zero padded time/date in outfiles.
   yyyymmdd filenames w/sprintf.

 2001-08-08   16:00 CDT
   Initial working code.

=head1 TODOS

 Query + separate report:
   ifInDiscards, ifInErrors, icmpOutErrors, tcpInErrors, udpInErrors
 Query switch for host MAC+IP for outfile(s) header (SNMP::BridgeQuery
+).
   then
 Query DNS for host name for outfile(s) header (Net::DNS).
 Retest with Win2k + ActivePerl.
 Retest with Win2k + Cygwin + Perl5.6.
 Pod:Usage to automagically synchronize pod with Usage().
      available for < 5.6 ?
 Read params from external config file.

=head1 AUTHOR

 ybiC

=head1 CREDITS

 Thanks to:
 masem, merlyn, tachyon, HamNRye, tilly, lemming, wog, crazyinsomniac.
 Oh yeah, and to some guy named vroom.  ;^)

=cut

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://121950]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2024-03-19 09:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found