#!/usr/bin/perl -w # shoint.pl # pod at tail use strict; use Net::Telnet::Cisco; use Term::ReadKey; use Tie::IxHash; use Time::localtime; use vars qw( $loops $port $delay $cisco $pass $enable ); my %parm =( errmode => 'return', timeout => '10', ); my %file = ( tmp0 => 'shoint.tmp0', tmp1 => 'shoint.tmp1', tmp2 => 'shoint.tmp2', log => 'shoint.csv', ); my @tmpfiles = ( $file{tmp0}, $file{tmp1}, $file{tmp2}, ); ###################################################################### +#### print( "\n", " Record bandwidth utilization on one port of a Cisco switch for +set length of time.\n", " Output file in CSV format for easy importing.\n\n", " CTRL+C at any time to interupt.\n\n", ); &CLEANUP(); ###################################################################### +#### tie my %inprompts, "Tie::IxHash"; %inprompts = ( ' Name or IP:' => 'cisco', ' Blade/port:' => 'port', ' Iterations:' => 'loops', ' Seconds delay:' => 'delay', ); print " Prompting for switch info...\n"; tie my %otherins, "Tie::IxHash"; for my $inprompt (keys %inprompts) { print " $inprompt "; chomp(my $input = <STDIN>); $otherins{$inprompts{$inprompt}} = $input; } print "\n"; $cisco = ($otherins{'cisco'}); $port = ($otherins{'port'}); $loops = ($otherins{'loops'}); $delay = ($otherins{'delay'}); if ($cisco eq "") { die "Sorry, you must enter *something* for switch name/IP.\n\n" }; if ($port eq "") { die "Sorry, you must enter *something* for blade/port.\n\n" }; unless ($loops eq int($loops) and $loops > 0) { die "Sorry, you must enter a positive non-zero integer for \"itera +tions\".\n\n" }; unless ($delay eq int($delay) and $delay >=0) { die "Sorry, you must enter a positive integer for \"delay\".\n\n" }; ###################################################################### +#### my $duRun = $loops * 1.5; # KB my $duEnd = $loops/10; # KB print "$duRun KB disk space will be used (then freed up) during progra +m run.\n"; print "$duEnd KB disk space will be used when program finished.\n"; # add 1sec/loop to prevent divide-by-zero warning if $delay=0 my $runsec = ($loops * $delay) + ($loops); my $runmin = $runsec/60; my $runhr = $runmin/60; my $runday = $runhr/24; my $runweek = $runday/7; print "Runtime "; # Display runtime in largest possible unit of time that shows > 0 my $run = $runsec and my $unit = "second(s)" if ($runsec >= 1 and $r +unmin < 1); $run = $runmin and $unit = "minute(s)" if ($runmin >= 1 and $r +unhr < 1); $run = $runhr and $unit = "hour(s)" if ($runhr >= 1 and $r +unday < 1); $run = $runday and $unit = "day(s)" if ($runday >= 1 and $r +unweek < 1); $run = $runweek and $unit = "week(s)" if ($runweek >= 1); printf("%.1f $unit\n",$run); # round to 1 decimal place ###################################################################### +#### tie my %passprompts, "Tie::IxHash"; %passprompts = ( ' Password:' => 'pass', ' Enable:' => 'enable', ); print "\n", " Prompting for password and enable... (no screen echo)\n", " Type carefully - backspaces not accepted.\n"; tie my %passwds, "Tie::IxHash"; for my $passprompt (keys %passprompts) { print " $passprompt "; ReadMode('noecho'); # don't echo to screen. chomp(my $input = <STDIN>); $passwds{$passprompts{$passprompt}} = $input; ReadMode(0); # re-activate screen echo. print "\n"; } print "\n"; $pass = ($passwds{"pass"}); $enable = ($passwds{"enable"}); if ($pass eq "") { die "Sorry, you must enter *something* for Password.\n\n" }; if ($enable eq "") { die "Sorry, you must enter *something* for Enable pass.\n\n" }; print "Starting switchport input/output rate check.\n"; print "Running $loops iterations at $delay second intervals\n"; &PCTIME(); print "Please wait...\n\n"; ###################################################################### +#### my @commands = ( 'set leng 0', 'sho ntp', "sho int $port", 'disa', ); # 'term leng 0', # 'sho clo', for(my $i=1; $i<=$loops; $i++) { if (my $cs=Net::Telnet::Cisco->new( host => $cisco, timeout => $parm{timeout}, errmode => $parm{errmode}, input_log => $file{tmp0}, ) ) { $cs->login('',$pass); # vty login if ($cs->enable($enable)) { # privilaged mode foreach my $command (@commands) { my @output = $cs->cmd($command); } } else { warn " shoint.pl: Enable failed: " . $cs->errmsg; } # if privilaged mode failed $cs->close; # exit session # if multiple Cisco sessions, append each to same tmpfile open (TMP0, "<$file{tmp0}") or die " shoint.pl: Can't open $file{tmp0} RO: $!"; open (TMP1, ">>$file{tmp1}") or die " shoint.pl: Can't open $file{tmp1} for append: $! +"; while (<TMP0>) { print TMP1 $_; } close (TMP0) or die " shoint.pl: Can't close $file{tmp0}: $!"; close (TMP1) or die " shoint.pl: Can't close $file{tmp1}: $!"; } else { warn " shoint.pl: D'oh! Telnet connection failed"; } # if +telnet connection fails sleep $delay; } ###################################################################### +#### &PARSE(); # Extract desired text from output &CLEANUP(); # Unlink tempfiles print "Completed switchport input/output rate check.\n"; print "Results at $file{log}\n"; &PCTIME(); ###################################################################### +#### # subroutines start here ###################################################################### +#### sub CLEANUP { foreach my $tmpfile(@tmpfiles) { if (-e $tmpfile && -o _) { unlink ($tmpfile) or warn " shoint.pl: Can't unlink $tmpfile: $!"; } } } ###################################################################### +#### sub PCTIME { printf "PC localtime %d:%d:%d %d-%d-%d\n\n", localtime -> hour(), localtime -> min(), localtime -> sec(), localtime -> mon()+1, localtime -> mday(), localtime -> year()+1900, } ###################################################################### +#### sub PARSE { my @keep = ('CST', '5 minute', ); my @strip = (', \d+ packets/sec', '^\s+$', ); # Extract lines w/desired text and write to temp file open (TMP1, "<$file{tmp1}") or die " shoint.pl: Can't open $file{tmp1 +} RO: $!"; open (TMP2, ">$file{tmp2}") or die " shoint.pl: Can't open $file{tmp2 +} WO: $!"; while (<TMP1>) { foreach my $keep(@keep) { if (/$keep/) { print TMP2 $_; } } } close (TMP1) or warn " shoint.pl: Can't close $file{tmp1 +}: $!"; close (TMP2) or die " shoint.pl: Can't close $file{tmp2 +}: $!"; # Strip unwanted text strings and write to output file open (TMP2, "<$file{tmp2}") or die " shoint.pl: Can't open $file{tmp +2} RO: $!"; open (LOG, ">$file{log}") or die " shoint.pl: Can't open $file{log +} WO: $!"; while (<TMP2>) { foreach my $strip(@strip) { s/$strip//g; } s/ 5 minute/5 minute/g; # strip unwanted spaces s/CST /CST,/g; # csv-ify timestamp s/2001/2001,/g; # csv-ify datestamp s/ bits\/sec/,/g; # csv-ify and strip "bps" fro +m rate number s/put rate/put rate \(bps\),/g; # csv-ify and insert "bps" in +to rate descr chomp if (/(CST|input)/); # merge each iteration into o +ne line print LOG $_; } close (TMP2) or warn " shoint.pl: Can't close $file{tmp2} +: $!"; close (LOG) or die " shoint.pl: Can't close $file{log}: + $!"; } ###################################################################### +#### =head1 Name shoint.pl =head1 Summary Automate logging of 5 minute input & output rates for individual Cisc +o IOS device ports. Does *not* work with CatOS switches like 2948g, 4000, 5000, 6000 fami +lies ~100 bytes of data generated for each iteration (after tmpfiles unlin +ked) ~1.5KB per iteration while running (before tmpfiles unlinked) =head1 Usage shoint.pl<enter> (script prompts for all needed info) =head1 Tested with: Perl 5.00503 on Debian 2.2 "Espy" against: Cisco Catalyst 3524xl IOS 12.0 2924xl IOS 11.28sa5 =head1 Comments Only works if device has standard Cisco prompts: ">", "#", "(enable)" Would rather use SNMP instead of telnet, but no easy way to automate +mapping of Cisco "blade/port" to SNMP "intName" 8^( =head1 Updated 2001-04-30 17:20 Un-subify for fewer global vars. Hashamafy passel o' scalars. 2001-01-11 Initial working code. =head1 ToDos Mixed-case subroutine names w/o ampersan. Unlink files from prior runs. Better error handling if bad switchname or password entered Use Proc::Daemon to background, allow disconnect of initiating sessio +n Use File::Slurp to append log - avoid race condition? Use File::Temp for tmpfiles =head1 Author [ybiC] =head1 Credits [tye] and [chipmunk] for suggestions on how to join output file lines +. Several monks whose names I forget for CB suggestions on integer-chec +king input. =cut

In reply to (code)) The Going input/output Rate (deprecated by node 121950) by ybiC

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.