Created
August 30, 2015 05:03
-
-
Save scottchiefbaker/1db3b86b847aa16447a5 to your computer and use it in GitHub Desktop.
Monitor port bandwidth via SNMP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
use strict; | |
use Getopt::Long; | |
use Time::HiRes qw(time sleep); | |
use Net::SNMP; | |
#use Data::Dump::Color; | |
my $debug = 0; | |
my $delay = 3; # Default delay is 3 seconds | |
my $ok = GetOptions( | |
'debug' => \$debug, | |
'delay=i' => \$delay, | |
); | |
my @p = split(/@/,$ARGV[0]); | |
my $community = $p[0]; | |
my $host = $p[1]; | |
my $filter = $ARGV[1] || ""; | |
if (!$community || !$host) { | |
die(usage()); | |
} | |
print "Connecting to $host using $community\n"; | |
my $s = snmp_connect($host,$community); | |
my $ints = get_interface_names($s); | |
my $int_count = scalar(keys(%$ints)); | |
my $last = {}; | |
while(1) { | |
my $start = time(); | |
# Grab the interface stats | |
my $cur = get_interface_bandwidth($s); | |
# If we have previous data, output the bw | |
if (%$last) { | |
output_data($cur,$last); | |
} | |
my $elapsed = time() - $start; | |
my $remain = $delay - $elapsed; | |
if ($debug) { | |
printf("Sleeping for %0.2f seconds\n",$remain); | |
} | |
# Wait X seconds and grab the data again | |
sleep($remain); | |
$last = $cur; # Store the data to compare it | |
} | |
############################################################# | |
sub snmp_connect { | |
my ($host,$community) = @_; | |
my ($session, $error) = Net::SNMP->session( | |
-hostname => $host, | |
-community => $community, | |
-timeout => "30", | |
-port => "161" | |
); | |
if (!defined($session)) { | |
printf("ERROR: %s.\n", $error); | |
return undef; | |
} | |
return $session; | |
} | |
sub get_interface_bandwidth { | |
my $session = shift(); | |
my $start = time(); | |
# Get the output bytes | |
my $ret = {}; | |
my $out_oid = ".1.3.6.1.2.1.2.2.1.16"; | |
my $resp = $session->get_table($out_oid); | |
my $err = $session->error; | |
# Store each interface in a hash by name | |
foreach my $key(keys($resp)) { | |
my $bw = $resp->{$key}; | |
my $int_num = int_num($key); | |
my $int_name = $ints->{$int_num}; | |
$ret->{$int_name}->{out} = $bw; | |
} | |
if ($debug) { | |
my $total = sprintf("%0.2f",time() - $start); | |
print "Fetch out bandwidth took $total seconds\n"; | |
} | |
########################################################## | |
$start = time(); | |
# Get the input bytes | |
my $in_oid = ".1.3.6.1.2.1.2.2.1.17"; | |
my $resp = $session->get_table($in_oid); | |
my $err = $session->error; | |
# Store each interface in a hash by name | |
foreach my $key(keys($resp)) { | |
my $bw = $resp->{$key}; | |
my $int_num = int_num($key); | |
my $int_name = $ints->{$int_num}; | |
$ret->{$int_name}->{in} = $bw; | |
} | |
if ($debug) { | |
my $total = sprintf("%0.2f",time() - $start); | |
print "Fetch in bandwidth took $total seconds\n"; | |
} | |
return $ret; | |
} | |
sub get_interface_names { | |
my $session = shift(); | |
my $ret = {}; | |
my $oid = "1.3.6.1.2.1.2.2.1.2"; | |
my $start = time(); | |
my $response = $session->get_table($oid); | |
my $err = $session->error; | |
if ($debug) { | |
my $total = sprintf("%0.2f",time() - $start); | |
print "Fetch interface names took $total seconds\n"; | |
} | |
# We're maping the IDs to the name of the interface | |
foreach my $key(keys($response)) { | |
my $value = $response->{$key}; | |
my $int_num = int_num($key); | |
$ret->{$int_num} = $value; | |
} | |
return $ret; | |
} | |
# Convert an OID to an interface number | |
sub int_num { | |
my $str = shift(); | |
# Remove everything up to the LAST period | |
$str =~ s/.+\.//; | |
return $str; | |
} | |
sub output_data { | |
my ($cur,$last) = @_; | |
my @ints = sort(keys($cur)); | |
# Find the length of the longest interface name | |
my $max_len = 0; | |
foreach (@ints) { | |
my $len = length($_); | |
if ($len > $max_len) { | |
$max_len = $len; | |
} | |
} | |
my $date = mysql_date(1); | |
# Print the date header | |
print color("15bold"); | |
printf("$date\n"); | |
print "-" x length($date) . "\n"; | |
print color(); | |
# Loop through each interface, calculate the bytes between the | |
# previous data and now | |
foreach my $name (@ints) { | |
my $prev = $last->{$name}->{out}; | |
my $now = $cur->{$name}->{out}; | |
my $out_total = $now - $prev; | |
my $out_str = human_size(int($out_total / $delay)); | |
my $prev = $last->{$name}->{in}; | |
my $now = $cur->{$name}->{in}; | |
my $in_total = $now - $prev; | |
my $in_str = human_size(int($in_total / $delay)); | |
# If there is no filter, or the line matches the filter spit it out | |
if (!$filter || $name =~ /$filter/) { | |
my $open_color = color(14); | |
my $reset_color = color(); | |
printf("$open_color%-${max_len}s$reset_color = $out_str/$in_str\n",$name); | |
print color(); | |
} | |
} | |
print "\n"; | |
} | |
sub mysql_date { | |
my ($inc_time,$epoch) = @_; | |
$epoch ||= time(); | |
my @date = localtime($epoch); | |
my $ret = sprintf("%04d-%02d-%02d", $date[5] + 1900, $date[4] + 1, $date[3]); | |
if ($inc_time) { $ret .= sprintf(" %02d:%02d:%02d", $date[2], $date[1], $date[0]); } | |
return $ret; | |
} | |
sub usage { | |
return "Usage: $0 community\@hostname [filter]\n"; | |
} | |
# String format: '115', '165bold', '10_on_140', 'reset', 'on_173' | |
sub color { | |
my $str = shift(); | |
# If we're connected to a TTY don't do color | |
if (-t STDOUT == 0) { return ''; } | |
# No string sent in, so we just reset | |
if (!$str || $str eq 'reset') { | |
return "\e[0m"; | |
} | |
# Get foreground and bold | |
my ($fc,$bold) = $str =~ /^(\d+)(b|bold)?/g; | |
# Get the background color (if present) | |
my ($bc) = $str =~ /on_?(\d+)$/g; | |
my $ret = ''; | |
if ($bold) { $ret .= "\e[1m"; } | |
if ($fc) { $ret .= "\e[38;5;${fc}m"; } | |
if ($bc) { $ret .= "\e[48;5;${bc}m"; } | |
return $ret; | |
} | |
sub human_size { | |
my $size = shift(); | |
my $color = ''; | |
my $reset = color(); | |
if ($size > 1024**3) { | |
$color = color(12); # Blue | |
$size = sprintf("%.1fG",$size / 1024**3); | |
} elsif ($size > 1024**2) { | |
$color = color(10); # Green | |
$size = sprintf("%.1fM",$size / 1024**2); | |
} elsif ($size > 1024) { | |
$color = color(11); # Yellow | |
$size = sprintf("%.1fK",$size / 1024); | |
} elsif ($size >= 0) { | |
$color = color(9); # Red | |
$size = sprintf("%dB",$size); | |
} | |
$size = $color . $size . $reset; | |
return $size; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment