#!/usr/bin/perl use strict; use warnings; $|++; ############################################################################## # Copyright (C) 2006 Rohan Almeida # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## # $Id: ibmonitor,v 1.26 2006/10/13 11:37:25 arc_of_ascent Exp $ use Time::HiRes qw/usleep gettimeofday tv_interval/; use Getopt::Long; use Term::ANSIColor; use Data::Dumper; # variables my $debug = 0; my $debug_file = 'ibmonitor-debug.log'; my $version = '1.4'; my $useReadKey = 0; my $firstpass = 1; my $avgpass; my @proc_data = (); my @tmp = (); my $clearstr = `clear`; my $interface = {}; my $interfaces_all = {}; my @interface_names = (); my @interface_names_copy = (); my %cmd_options = (); my ($inter, $direction); my $inputkey; my $key_mess = ''; my $maxbytes_cnt = (2**32) - 1; my $start_time; my %colors = (); my %movers = (); my $elapsed_time; my $ostr; my $ihelp = 0; my $ihelp_flg = 0; my ($i, @index); my ($t0, $t1, $t0_t1); # functions sub print_usage(); sub print_help(); sub create_interface($); sub get_proc_data(); sub trim($); sub alignstr($$$); sub init_interfaces_all(); sub reset_all(); sub debug_it($); sub show_help(); sub quit_it(); sub adjust_unit($); sub get_run_time($); sub process_userkey($); sub order_interfaces(); # Check for installation of Term-ReadKey module eval q/use Term::ReadKey;/; if (!$@) { $useReadKey = 1; } if ($debug) { open FH, ">$debug_file" or die "Can't write $debug_file in current directory: $!"; close FH; } %colors = ( 'max' => 'Red', 'avg' => 'Green', 'data' => 'Magenta', ); %cmd_options = ( 'bits' => 0, 'bytes' => 0, 'avg' => 0, 'max' => 0, 'interval' => 2, 'colors' => 1, 'data' => 0, 'help' => 0, 'version' => 0, 'dev' => '', 'file' => '/proc/net/dev', ); %movers = ( 'init' => 0, 'num' => 0, 'dir' => 0, ); # Parse command line options my $result = GetOptions ( 'bits' => \$cmd_options{'bits'}, 'bytes' => \$cmd_options{'bytes'}, 'avg' => \$cmd_options{'avg'}, 'max' => \$cmd_options{'max'}, 'interval=i' => \$cmd_options{'interval'}, 'colors!' => \$cmd_options{'colors'}, 'data' => \$cmd_options{'data'}, 'help' => \$cmd_options{'help'}, 'version' => \$cmd_options{'version'}, 'dev=s' => \$cmd_options{'dev'}, 'file=s' => \$cmd_options{'file'}, ); if (not $result) { print_usage(); exit 1; } if ($cmd_options{'interval'} == 0) { print STDERR "0 not allowed as interval.\n"; print_usage(); exit 1; } if (not -e $cmd_options{'file'}) { print STDERR 'file '.$cmd_options{'file'}.' does not exist.'."\n"; print STDERR "ibmonitor requires the /proc/net/dev file.\n"; print STDERR "See the README file provided with ibmonitor.\n"; exit 1; } if (`file $cmd_options{file}` !~ /empty/) { print STDERR "$cmd_options{file} does not appear to be a valid filetype\n"; exit 1; } if ($cmd_options{'help'}) { print_help(); exit 1; } if ($cmd_options{'version'}) { print STDERR "ibmonitor version $version\n"; exit 1; } if ($cmd_options{'bits'} == 0 && $cmd_options{'bytes'} == 0) { $cmd_options{'bits'} = 1; } init_interfaces_all(); $start_time = time(); # Change to raw mode. # ie. Disable control keys, and enables us to read a single keystroke if ($useReadKey) { eval q/ReadMode 'raw';/; } # Start the never-ending story! while (1) { $ostr = sprintf $clearstr; # print header $ostr .= sprintf alignstr('Interface', 10, 'r'); if ($cmd_options{'bits'} == 1 && $cmd_options{'bytes'} == 1) { $ostr .= sprintf alignstr('Received ', 22, 'r'); $ostr .= sprintf alignstr('Sent ', 22, 'r'); $ostr .= sprintf alignstr('Total ', 22, 'r'); $ostr .= sprintf "\n"; $ostr .= sprintf alignstr(' ', 10, 'r'); for (1 .. 3) { $ostr .= sprintf alignstr('Kbps', 12, 'r'); $ostr .= sprintf alignstr('KBps', 10, 'r'); } } elsif ($cmd_options{'bits'} == 1) { $ostr .= sprintf alignstr('Received', 12, 'r'); $ostr .= sprintf alignstr('Sent', 12, 'r'); $ostr .= sprintf alignstr('Total', 12, 'r'); $ostr .= sprintf "\n"; $ostr .= sprintf alignstr(' ', 10, 'r'); for (1 .. 3) { $ostr .= sprintf alignstr('Kbps', 12, 'r'); } } elsif ($cmd_options{'bytes'} == 1) { $ostr .= sprintf alignstr('Received', 10, 'r'); $ostr .= sprintf alignstr('Sent', 10, 'r'); $ostr .= sprintf alignstr('Total', 10, 'r'); $ostr .= sprintf "\n"; $ostr .= sprintf alignstr(' ', 10, 'r'); for (1 .. 3) { $ostr .= sprintf alignstr('KBps', 10, 'r'); } } $ostr .= sprintf "\n\n"; # Get data from /proc and populate interfaces hash @proc_data = get_proc_data(); $t0 = [gettimeofday]; for (@proc_data) { ($tmp[0], $tmp[1]) = map trim($_), split /:/; # Check if user wants to see some particular interface only (ie. --dev) if ($tmp[0] =~ /($cmd_options{'dev'})/) { create_interface($tmp[0]) if (not exists $interface->{$tmp[0]}); push @interface_names, $tmp[0] if (not grep /^$tmp[0]$/, @interface_names); $interface->{$tmp[0]}{'Received'}{'New'} = (split /\s+/, $tmp[1])[0]; $interface->{$tmp[0]}{'Sent'}{'New'} = (split /\s+/, $tmp[1])[8]; } } foreach $inter (keys %{$interface}) { delete $interface->{$inter} if (not grep /^$inter$/, @interface_names); } foreach $inter (@interface_names) { if (not grep /^$inter$/, @interface_names_copy) { push @interface_names_copy, $inter; } } # Arrange interface_names array according to user sort @index = (); for ($i=0;$i{$_}{'Received'}{'Old'} = $interface->{$_}{'Received'}{'New'}; $interface->{$_}{'Sent'}{'Old'} = $interface->{$_}{'Sent'}{'New'}; } $firstpass = 0; $avgpass = 1; @interface_names = sort @interface_names; if ($debug) { debug_it('Inside firstpass conditional:'); debug_it('Interval: '.$cmd_options{'interval'}); debug_it(Dumper($interface->{'ppp0'}{'Received'})); } print $ostr; } else { # reset interfaces_all hash foreach $direction (keys %{$interfaces_all}) { $interfaces_all->{$direction}{'Bandwidth'}{'Bps'} = 0; $interfaces_all->{$direction}{'Bandwidth'}{'KBps'} = 0; $interfaces_all->{$direction}{'Bandwidth'}{'Kbps'} = 0; } foreach $inter (@interface_names) { foreach $direction ('Received', 'Sent') { $interface->{$inter}{$direction}{'Bandwidth'}{'Bps'} = ($interface->{$inter}{$direction}{'New'} - $interface->{$inter}{$direction}{'Old'}) / $cmd_options{'interval'}; # Take care of negative values obtained, # due to the byte counter overflowing if ($interface->{$inter}{$direction}{'Bandwidth'}{'Bps'} < 0) { $interface->{$inter}{$direction}{'Bandwidth'}{'Bps'} = ($maxbytes_cnt - $interface->{$inter}{$direction}{'Old'} + $interface->{$inter}{$direction}{'New'}) / $cmd_options{'interval'}; } # Put new into old $interface->{$inter}{$direction}{'Old'} = $interface->{$inter}{$direction}{'New'}; } # Calulate total of received and sent $interface->{$inter}{'Total'}{'Bandwidth'}{'Bps'} = $interface->{$inter}{'Received'}{'Bandwidth'}{'Bps'} + $interface->{$inter}{'Sent'}{'Bandwidth'}{'Bps'}; foreach $direction (keys %{$interface->{$inter}}) { # Bandwidth in KBps $interface->{$inter}{$direction}{'Bandwidth'}{'KBps'} = sprintf('%.2f', $interface->{$inter}{$direction}{'Bandwidth'}{'Bps'} / 1024); # Max Bandwidth in KBps $interface->{$inter}{$direction}{'Bandwidth'}{'Max'}{'KBps'} = sprintf( '%.2f', ( $interface->{$inter}{$direction}{'Bandwidth'}{'KBps'} > $interface->{$inter}{$direction}{'Bandwidth'}{'Max'}{'KBps'}) ? $interface->{$inter}{$direction}{'Bandwidth'}{'KBps'} : $interface->{$inter}{$direction}{'Bandwidth'}{'Max'}{'KBps'} ); # Total data in KB $interface->{$inter}{$direction}{'Amount'}{'KB'} = sprintf('%.2f', $interface->{$inter}{$direction}{'Amount'}{'KB'} + $interface->{$inter}{$direction}{'Bandwidth'}{'KBps'} * $cmd_options{'interval'}); # Average bandwidth in KBps $interface->{$inter}{$direction}{'Bandwidth'}{'Avg'}{'KBps'} = sprintf('%.2f', $interface->{$inter}{$direction}{'Amount'}{'KB'} / get_run_time('s')); # Values in Kbps $interface->{$inter}{$direction}{'Bandwidth'}{'Kbps'} = sprintf('%.2f', $interface->{$inter}{$direction}{'Bandwidth'}{'KBps'} * 8); $interface->{$inter}{$direction}{'Bandwidth'}{'Avg'}{'Kbps'} = sprintf('%.2f', $interface->{$inter}{$direction}{'Bandwidth'}{'Avg'}{'KBps'} * 8); $interface->{$inter}{$direction}{'Bandwidth'}{'Max'}{'Kbps'} = sprintf('%.2f', $interface->{$inter}{$direction}{'Bandwidth'}{'Max'}{'KBps'} * 8); } # Sum of all interfaces foreach $direction (keys %{$interfaces_all}) { $interfaces_all->{$direction}{'Bandwidth'}{'KBps'} = sprintf('%.2f', $interfaces_all->{$direction}{'Bandwidth'}{'KBps'} + $interface->{$inter}{$direction}{'Bandwidth'}{'KBps'}); $interfaces_all->{$direction}{'Bandwidth'}{'Kbps'} = sprintf('%.2f', $interfaces_all->{$direction}{'Bandwidth'}{'Kbps'} + $interface->{$inter}{$direction}{'Bandwidth'}{'Kbps'}); } # Display the interface stats $ostr .= sprintf alignstr(" $inter", 10, 'l'); foreach $direction (sort keys %{$interface->{$inter}}) { # Bandwidth $ostr .= sprintf alignstr( $interface->{$inter}{$direction}{'Bandwidth'}{'Kbps'}, 12, 'r') if ($cmd_options{'bits'}); $ostr .= sprintf alignstr( $interface->{$inter}{$direction}{'Bandwidth'}{'KBps'}, 10, 'r') if ($cmd_options{'bytes'}); } $ostr .= sprintf "\n"; # Display the max stats if ($cmd_options{'max'}) { if ($cmd_options{'colors'}) { $ostr .= sprintf colored alignstr('|---- Max', 10, 'r'), $colors{'max'}; foreach $direction (sort keys %{$interface->{$inter}}) { $ostr .= sprintf colored alignstr( $interface->{$inter}{$direction}{'Bandwidth'}{'Max'}{'Kbps'}, 12, 'r'), $colors{'max'} if ($cmd_options{'bits'}); $ostr .= sprintf colored alignstr( $interface->{$inter}{$direction}{'Bandwidth'}{'Max'}{'KBps'}, 10, 'r'), $colors{'max'} if ($cmd_options{'bytes'}); } } else { $ostr .= sprintf alignstr('|---- Max', 10, 'r'); foreach $direction (sort keys %{$interface->{$inter}}) { $ostr .= sprintf alignstr( $interface->{$inter}{$direction}{'Bandwidth'}{'Max'}{'Kbps'}, 12, 'r') if ($cmd_options{'bits'}); $ostr .= sprintf alignstr( $interface->{$inter}{$direction}{'Bandwidth'}{'Max'}{'KBps'}, 10, 'r') if ($cmd_options{'bytes'}); } } $ostr .= sprintf "\n"; } # Display the avg stats if ($cmd_options{'avg'}) { if ($cmd_options{'colors'}) { $ostr .= sprintf colored alignstr('|---- Avg', 10, 'r'), $colors{'avg'}; foreach $direction (sort keys %{$interface->{$inter}}) { $ostr .= sprintf colored alignstr( $interface->{$inter}{$direction}{'Bandwidth'}{'Avg'}{'Kbps'}, 12, 'r'), $colors{'avg'} if ($cmd_options{'bits'}); $ostr .= sprintf colored alignstr( $interface->{$inter}{$direction}{'Bandwidth'}{'Avg'}{'KBps'}, 10, 'r'), $colors{'avg'} if ($cmd_options{'bytes'}); } } else { $ostr .= sprintf alignstr('|---- Avg', 10, 'r'); foreach $direction (sort keys %{$interface->{$inter}}) { $ostr .= sprintf alignstr( $interface->{$inter}{$direction}{'Bandwidth'}{'Avg'}{'Kbps'}, 12, 'r') if ($cmd_options{'bits'}); $ostr .= sprintf alignstr( $interface->{$inter}{$direction}{'Bandwidth'}{'Avg'}{'KBps'}, 10, 'r') if ($cmd_options{'bytes'}); } } $ostr .= sprintf "\n"; } # Display the interface data usage stats if ($cmd_options{'data'}) { if ($cmd_options{'colors'}) { $ostr .= sprintf colored alignstr('|- Amount', 10, 'r'), $colors{'data'}; foreach $direction (sort keys %{$interface->{$inter}}) { $ostr .= sprintf colored alignstr( adjust_unit($interface->{$inter}{$direction}{'Amount'}{'KB'}), 22, 'r'), $colors{'data'} if ($cmd_options{'bits'} && $cmd_options{'bytes'}); $ostr .= sprintf colored alignstr( adjust_unit($interface->{$inter}{$direction}{'Amount'}{'KB'}), 12, 'r'), $colors{'data'} if ($cmd_options{'bits'} && !$cmd_options{'bytes'}); $ostr .= sprintf colored alignstr( adjust_unit($interface->{$inter}{$direction}{'Amount'}{'KB'}), 10, 'r'), $colors{'data'} if ($cmd_options{'bytes'} && !$cmd_options{'bits'}); } } else { $ostr .= sprintf alignstr('|- Amount', 10, 'r'); foreach $direction (sort keys %{$interface->{$inter}}) { $ostr .= sprintf alignstr( adjust_unit($interface->{$inter}{$direction}{'Amount'}{'KB'}), 22, 'r') if ($cmd_options{'bits'} && $cmd_options{'bytes'}); $ostr .= sprintf alignstr( adjust_unit($interface->{$inter}{$direction}{'Amount'}{'KB'}), 12, 'r') if ($cmd_options{'bits'} && !$cmd_options{'bytes'}); $ostr .= sprintf alignstr( adjust_unit($interface->{$inter}{$direction}{'Amount'}{'KB'}), 10, 'r') if ($cmd_options{'bytes'} && !$cmd_options{'bits'}); } } $ostr .= sprintf "\n"; } $ostr .= sprintf "\n"; } # Stuff for all interfaces (interfaces_all hash) foreach $direction (keys %{$interfaces_all}) { # Total Data in KB for all interfaces $interfaces_all->{$direction}{'Amount'}{'KB'} = sprintf('%.2f', $interfaces_all->{$direction}{'Amount'}{'KB'} + $interfaces_all->{$direction}{'Bandwidth'}{'KBps'} * $cmd_options{'interval'}); # Average data in KBps $interfaces_all->{$direction}{'Bandwidth'}{'Avg'}{'KBps'} = sprintf('%.2f', $interfaces_all->{$direction}{'Amount'}{'KB'} / get_run_time('s')); # Average data in Kbps $interfaces_all->{$direction}{'Bandwidth'}{'Avg'}{'Kbps'} = sprintf('%.2f', $interfaces_all->{$direction}{'Bandwidth'}{'Avg'}{'KBps'} * 8); # Max of all interfaces in KBps $interfaces_all->{$direction}{'Bandwidth'}{'Max'}{'KBps'} = sprintf('%.2f', ($interfaces_all->{$direction}{'Bandwidth'}{'KBps'} > $interfaces_all->{$direction}{'Bandwidth'}{'Max'}{'KBps'}) ? $interfaces_all->{$direction}{'Bandwidth'}{'KBps'} : $interfaces_all->{$direction}{'Bandwidth'}{'Max'}{'KBps'}); # Max of all interfaces in Kbps $interfaces_all->{$direction}{'Bandwidth'}{'Max'}{'Kbps'} = sprintf('%.2f', ($interfaces_all->{$direction}{'Bandwidth'}{'Kbps'} > $interfaces_all->{$direction}{'Bandwidth'}{'Max'}{'Kbps'}) ? $interfaces_all->{$direction}{'Bandwidth'}{'Kbps'} : $interfaces_all->{$direction}{'Bandwidth'}{'Max'}{'Kbps'}); } # Display All Interfaces stats $ostr .= sprintf alignstr(' All', 10, 'l'); foreach $direction (sort keys %{$interfaces_all}) { $ostr .= sprintf alignstr($interfaces_all->{$direction}{'Bandwidth'}{'Kbps'}, 12, 'r') if ($cmd_options{'bits'}); $ostr .= sprintf alignstr($interfaces_all->{$direction}{'Bandwidth'}{'KBps'}, 10, 'r') if ($cmd_options{'bytes'}); } $ostr .= sprintf "\n"; # Display the max of all interfaces if ($cmd_options{'max'}) { if ($cmd_options{'colors'}) { $ostr .= sprintf colored alignstr('|---- Max', 10, 'r'), $colors{'max'}; foreach $direction (sort keys %{$interfaces_all}) { $ostr .= sprintf colored alignstr( $interfaces_all->{$direction}{'Bandwidth'}{'Max'}{'Kbps'}, 12, 'r'), $colors{'max'} if ($cmd_options{'bits'}); $ostr .= sprintf colored alignstr( $interfaces_all->{$direction}{'Bandwidth'}{'Max'}{'KBps'}, 10, 'r'), $colors{'max'} if ($cmd_options{'bytes'}); } } else { $ostr .= sprintf alignstr('|---- Max', 10, 'r'); foreach $direction (sort keys %{$interfaces_all}) { $ostr .= sprintf alignstr( $interfaces_all->{$direction}{'Bandwidth'}{'Max'}{'Kbps'}, 12, 'r') if ($cmd_options{'bits'}); $ostr .= sprintf alignstr( $interfaces_all->{$direction}{'Bandwidth'}{'Max'}{'KBps'}, 10, 'r') if ($cmd_options{'bytes'}); } } $ostr .= sprintf "\n"; } # Display the avg of all interfaces if ($cmd_options{'avg'}) { if ($cmd_options{'colors'}) { $ostr .= sprintf colored alignstr('|---- Avg', 10, 'r'), $colors{'avg'}; foreach $direction (sort keys %{$interfaces_all}) { $ostr .= sprintf colored alignstr( $interfaces_all->{$direction}{'Bandwidth'}{'Avg'}{'Kbps'}, 12, 'r'), $colors{'avg'} if ($cmd_options{'bits'}); $ostr .= sprintf colored alignstr( $interfaces_all->{$direction}{'Bandwidth'}{'Avg'}{'KBps'}, 10, 'r'), $colors{'avg'} if ($cmd_options{'bytes'}); } } else { $ostr .= sprintf alignstr('|---- Avg', 10, 'r'); foreach $direction (sort keys %{$interfaces_all}) { $ostr .= sprintf alignstr( $interfaces_all->{$direction}{'Bandwidth'}{'Avg'}{'Kbps'}, 12, 'r') if ($cmd_options{'bits'}); $ostr .= sprintf alignstr( $interfaces_all->{$direction}{'Bandwidth'}{'Avg'}{'KBps'}, 10, 'r') if ($cmd_options{'bytes'}); } } $ostr .= sprintf "\n"; } # Display the interfaces_all data usage stats if ($cmd_options{'data'}) { if ($cmd_options{'colors'}) { $ostr .= sprintf colored alignstr('|- Amount', 10, 'r'), $colors{'data'}; foreach $direction (sort keys %{$interfaces_all}) { $ostr .= sprintf colored alignstr( adjust_unit($interfaces_all->{$direction}{'Amount'}{'KB'}), 22, 'r'), $colors{'data'} if ($cmd_options{'bits'} && $cmd_options{'bytes'}); $ostr .= sprintf colored alignstr( adjust_unit($interfaces_all->{$direction}{'Amount'}{'KB'}), 12, 'r'), $colors{'data'} if ($cmd_options{'bits'} && !$cmd_options{'bytes'}); $ostr .= sprintf colored alignstr( adjust_unit($interfaces_all->{$direction}{'Amount'}{'KB'}), 10, 'r'), $colors{'data'} if (!$cmd_options{'bits'} && $cmd_options{'bytes'}); } } else { $ostr .= sprintf alignstr('|- Amount', 10, 'r'); foreach $direction (sort keys %{$interfaces_all}) { $ostr .= sprintf alignstr( adjust_unit($interfaces_all->{$direction}{'Amount'}{'KB'}), 22, 'r') if ($cmd_options{'bits'} && $cmd_options{'bytes'}); $ostr .= sprintf alignstr( adjust_unit($interfaces_all->{$direction}{'Amount'}{'KB'}), 12, 'r') if ($cmd_options{'bits'} && !$cmd_options{'bytes'}); $ostr .= sprintf alignstr( adjust_unit($interfaces_all->{$direction}{'Amount'}{'KB'}), 10, 'r') if (!$cmd_options{'bits'} && $cmd_options{'bytes'}); } } $ostr .= sprintf "\n"; } $elapsed_time = get_run_time(''); $ostr .= sprintf "\n"; if ($useReadKey) { $ostr .= sprintf ' Press \'q\' to quit...'; } else { $ostr .= sprintf ' Press ctrl+c to quit...'; } $ostr .= sprintf "\t\t".'Elapsed time: '.$elapsed_time; $ostr .= sprintf "\n"; if ($debug) { debug_it("avgpass: $avgpass"); debug_it('Interval: '.$cmd_options{'interval'}); debug_it("elapsed_time: $elapsed_time"); debug_it('%interface{\'ppp0\'}{\'Received\'} DUMP:'); debug_it(Dumper($interface->{'ppp0'}{'Received'})); } if ($key_mess ne '') { $ostr .= sprintf "\n $key_mess\n"; $key_mess = ''; } $avgpass++; if ($ihelp) { show_help(); } else { print $ostr; } if ($useReadKey) { eval q/$inputkey = ReadKey(0.000000001);/; if (defined($inputkey)) { # User has pressed some key. Better process it. process_userkey($inputkey); } } } # Clear interface names @interface_names_copy = @interface_names; @interface_names = (); # Sleep for interval seconds $t1 = [gettimeofday]; $t0_t1 = tv_interval $t0, $t1; if ($debug) { debug_it("\$t0_t1 = $t0_t1"); debug_it($cmd_options{'interval'} - $t0_t1); } usleep (($cmd_options{'interval'} - $t0_t1) * 1000000); } # End of never-ending story! :-) sub print_usage() { my $progname = `basename $0`; chop $progname; print STDERR "ibmonitor version $version\n"; print STDERR 'usage: '.$progname.' [--bits] [--bytes] [--max] [--avg] '."\n". "\t\t".'[--data] [--interval n] [--colors | --nocolors] '."\n". "\t\t".'[--dev regex] [--file proc] [--help] [--version]'."\n"; } sub create_interface($) { my $inter = shift; for my $direction ('Received', 'Sent', 'Total') { $interface->{$inter}{$direction}{'New'} = 0; $interface->{$inter}{$direction}{'Old'} = 0; $interface->{$inter}{$direction}{'Bandwidth'} = { 'Bps' => 0, 'KBps' => 0, 'Kbps' => 0, }; for my $type ('Max', 'Avg') { $interface->{$inter}{$direction}{'Bandwidth'}{$type} = { 'KBps' => 0, 'Kbps' => 0, }; } $interface->{$inter}{$direction}{'Amount'} = { 'KB' => 0, 'MB' => 0, 'GB' => 0, }; } } sub init_interfaces_all() { for my $dir ('Received', 'Sent', 'Total') { $interfaces_all->{$dir}{'Bandwidth'} = { 'Bps' => 0, 'KBps' => 0, 'Kbps' => 0, }; for my $type ('Max', 'Avg') { $interfaces_all->{$dir}{'Bandwidth'}{$type} = { 'KBps' => 0, 'Kbps' => 0, }; } $interfaces_all->{$dir}{'Amount'} = { 'KB' => 0, 'MB' => 0, 'GB' => 0, }; } } # get_proc_data # ------------- # Return array of lines from file /proc/net/dev # sub get_proc_data() { my @arr; #my $n_interfaces; open FH, "<$cmd_options{file}" or die "Couldn't open $cmd_options{file}!"; @arr = ; close FH; splice @arr, 0, 2; #$n_interfaces = scalar @arr; #if ($n_interfaces > $num_interfaces) { # An interface has been added/activated return @arr; } # trim # ---- # Remove leading/trailing whitespace from string # sub trim($) { my $str = $_[0]; $str =~ s/^\s+//; $str =~ s/\s+$//; return $str; } # alignstr # -------- # Align the string # arguments: # 1) the string to align # 2) field length # 3) l -> align left # m -> align center # r -> align right # sub alignstr($$$) { my ($str, $len, $pos) = @_; my $ret_str; my $num_spaces; my $left_spaces; my $right_spaces; $num_spaces = $len - length($str); if ($pos eq 'l') { # left align $ret_str = $str; $ret_str .= ' ' x $num_spaces; } elsif ($pos eq 'r') { # right align $ret_str = ' ' x $num_spaces; $ret_str .= $str; } elsif ($pos eq 'm') { # center align $left_spaces = int($num_spaces/2); $right_spaces = $num_spaces - $left_spaces; $ret_str = ' ' x $left_spaces; $ret_str .= $str; $ret_str .= ' ' x $right_spaces; } return $ret_str; } sub debug_it($) { my $content = $_[0]; open FH, ">>$debug_file"; print FH $content."\n"; close FH; } sub show_help() { # display list of interactive commands if ($useReadKey) { print $clearstr; my $tmpstr =< [q]uit 1-9 -> Set sleep time interval (in seconds) to the digit entered m -> Toggle display of [m]ax bandwidth a -> Toggle display of [a]verage bandwidth i -> Toggle display of values in KB[i]ts/sec (Kbps) y -> Toggle display of values in KB[y]tes/sec (KBps) d -> Toggle display of [d]ata transferred s -> Shift interface up/down. This should be followed by the interface number, and then the direction (u or d) r -> [r]eset all values ?/h -> This help screen Press Enter to resume monitoring... EOF print $tmpstr; } } sub quit_it() { # restore terminal mode to whatever it was if ($useReadKey) { eval q/ReadMode 'restore';/; print "\nQuitting...\n"; exit 0; } } sub reset_all() { foreach my $inter_r (keys %{$interface}) { foreach my $direction (keys %{$interface->{$inter_r}}) { foreach my $type ('Avg', 'Max') { foreach my $unit (keys %{$interface->{$inter_r}{$direction}{'Bandwidth'}{$type}}) { $interface->{$inter_r}{$direction}{'Bandwidth'}{$type}{$unit} = 0; } } foreach my $unit (keys %{$interface->{$inter_r}{$direction}{'Amount'}}) { $interface->{$inter_r}{$direction}{'Amount'}{$unit} = 0; } } } foreach my $direction (keys %{$interfaces_all}) { foreach my $type ('Avg', 'Max') { foreach my $unit (keys %{$interfaces_all->{$direction}{'Bandwidth'}{$type}}) { $interfaces_all->{$direction}{'Bandwidth'}{$type}{$unit} = 0; } } foreach my $unit (keys %{$interfaces_all->{$direction}{'Amount'}}) { $interfaces_all->{$direction}{'Amount'}{$unit} = 0; } } $avgpass = 1; $start_time = time(); } sub print_help() { my $output; print "\n"; print_usage(); # print full help with usage $output =< Show output values in KBits/sec. This is the default. --bytes -> Show output values in KBytes/sec --max -> Show maximum values per interface --avg -> Show average values per interface --interval n -> Set time interval as n seconds. The default is 2 seconds. --data -> Show data transferred in KB/MB/GB --colors -> Show some fancy coloring! (This is the default) --nocolors -> No fancy coloring please! --dev regex -> Show output from device which matches regex --file proc -> Specify which file to use in the proc filesystem for the interface byte counter --help -> Show help and exit --version -> Show version number and exit While the program is running, the following keys are recognized, which enables the user to change the output display format of the program. Note: ibmonitor responds directly to the single keystroke ie. the 'Enter' key need not be pressed q -> [q]uit 1-9 -> Set sleep time interval(in seconds) to the digit entered m -> Toggle display of [m]ax bandwidth a -> Toggle display of [a]verage bandwidth i -> Toggle display of values in KB[i]ts/sec (Kbps) y -> Toggle display of values in KB[y]tes/sec (KBps) d -> Toggle display of [d]ata transferred s -> Shift interface up/down. This should be followed by the interface number, and then the direction (u or d) r -> [r]eset all values ?/h -> help screen for interactive commands EOF print STDERR $output; } sub adjust_unit($) { my $amt = $_[0]; my $ret; if ($amt =~ /^\d{1,3}\b\.?/) { # return in KB $ret = $amt.' KB'; } elsif ($amt =~ /^\d{1,6}\b\.?/) { # return in MB $ret = sprintf('%.2f', ($amt / 1024)).' MB'; } elsif ($amt =~ /^\d{1,9}\b\.?/) { # return in GB $ret = sprintf('%.2f', ($amt / (1024*1024))).' GB'; } return $ret; } sub get_run_time($) { my $arg = shift; my $nowtime = time(); my $diff = $nowtime - $start_time; my ($sec, $min, $hour); my $ret; return $diff if ($arg eq 's'); $sec = $diff % 60; $min = ($diff / 60) % 60; $hour = ($diff / (60 * 60)) % 24; $ret = "$hour hrs, $min mins, $sec s"; return $ret; } sub process_userkey($) { my $ikey = $_[0]; if ($movers{'init'}) { $movers{'num'} = $ikey; $movers{'init'} = 0; if ($movers{'num'} !~ /\d/) { $key_mess = 'Need a number!'; $movers{'num'} = 0; } else { $key_mess = 'Interface to shift at position '.$ikey; } } elsif ($movers{'num'}) { $movers{'dir'} = $ikey; order_interfaces(); $movers{'num'} = 0; if ($movers{'dir'} eq 'u') { $key_mess = 'Shifting interface up'; } elsif ($movers{'dir'} eq 'd') { $key_mess = 'Shifting interface down'; } } elsif ($ihelp_flg) { if ($ikey eq "\n") { $ihelp = 0; $ihelp_flg = 0; } } elsif ($ikey eq '?' || $ikey eq 'h') { $ihelp = 1; $ihelp_flg = 1; } elsif ($ikey eq 'q') { quit_it(); } elsif ($ikey eq 'm') { $cmd_options{'max'} = abs($cmd_options{'max'}-1); if ($cmd_options{'max'}) { $key_mess = 'm => Displaying [m]ax Bandwidth'; } else { $key_mess = 'm => Not Displaying [m]ax Bandwidth'; } } elsif ($ikey eq 'a') { $cmd_options{'avg'} = abs($cmd_options{'avg'}-1); if ($cmd_options{'avg'}) { $key_mess = 'a => Displaying [a]verage Bandwidth'; } else { $key_mess = 'a => Not Displaying [a]verage Bandwidth'; } } elsif ($ikey eq 'i') { $cmd_options{'bits'} = abs($cmd_options{'bits'}-1); if ($cmd_options{'bits'}) { $key_mess = 'i => Displaying Values in Kb[i]ts/sec (Kbps)'; } else { $key_mess = 'i => Not Displaying Values in Kb[i]ts/sec (Kbps)'; } } elsif ($ikey eq 'y') { $cmd_options{'bytes'} = abs($cmd_options{'bytes'}-1); if ($cmd_options{'bytes'}) { $key_mess = 'y => Displaying Values in KB[y]tes/sec (KBps)'; } else { $key_mess = 'y => Not Displaying Values in KB[y]tes/sec (KBps)'; } } elsif ($ikey eq 'd') { $cmd_options{'data'} = abs($cmd_options{'data'}-1); if($cmd_options{'data'}) { $key_mess = 'd => Displaying [d]ata transferred'; } else { $key_mess = 'd => Not Displaying [d]ata transferred'; } } elsif ($ikey eq 'r') { # Reset all values reset_all(); $key_mess = 'r -> [r]esetting all values'; } elsif ($ikey =~ /^\d$/ && $ikey != 0) { # If ikey is a digit then it is an interval $cmd_options{'interval'} = $ikey; $key_mess = $ikey.' => Refresh interval is now ['.$ikey.'] seconds'; } elsif ($ikey eq 's') { # shift interface up/down $movers{'init'} = 1; $key_mess = $ikey.' => [s]hift interface up/down. Enter interface number '; } else { $key_mess = $ikey.' => Invalid keystroke'; } # something has to be shown! # resort to Kbits by default $cmd_options{'bits'} = 1 if ($cmd_options{'bits'} == 0 && $cmd_options{'bytes'} == 0); } sub order_interfaces() { if ($debug) { debug_it('order_interfaces():'); debug_it('Before:'); debug_it('%movers DUMP:'); debug_it(Dumper(%movers)); debug_it('@interface_names DUMP:'); debug_it(Dumper(@interface_names)); } # Check for boundary conditions if (($movers{'dir'} eq 'u') && ($movers{'num'} > 1) && ($movers{'num'} <= $#interface_names+1)) { ($interface_names[$movers{'num'}-2], $interface_names[$movers{'num'}-1]) = ($interface_names[$movers{'num'}-1], $interface_names[$movers{'num'}-2]); } elsif (($movers{'dir'} eq 'd') && ($movers{'num'} >= 1) && ($movers{'num'} <= $#interface_names)) { ($interface_names[$movers{'num'}], $interface_names[$movers{'num'}-1]) = ($interface_names[$movers{'num'}-1], $interface_names[$movers{'num'}]); } if ($debug) { debug_it('order_interfaces():'); debug_it('After:'); debug_it('%movers DUMP:'); debug_it(Dumper(%movers)); debug_it('@interface_names DUMP:'); debug_it(Dumper(@interface_names)); } }