Révision 138de37d
perl version not committed?!?
| plugins/other/bandwidth_ | ||
|---|---|---|
| 1 |
#!/bin/bash |
|
| 1 |
#!/usr/bin/perl |
|
| 2 |
# -*- perl -*- |
|
| 2 | 3 |
|
| 3 |
# Now updated to support 32-bit operating systems |
|
| 4 |
# Requires bash |
|
| 5 |
|
|
| 6 |
: << =cut |
|
| 4 |
=head1 NAME |
|
| 7 | 5 |
|
| 8 | 6 |
bandwidth_ - Wildcard-plugin to monitor total network traffic and |
| 9 |
predict 30 day bandwidth usage |
|
| 7 |
predict 30 day bandwidth usage
|
|
| 10 | 8 |
|
| 11 | 9 |
=head1 CONFIGURATION |
| 12 | 10 |
|
| ... | ... | |
| 20 | 18 |
|
| 21 | 19 |
Most likely usage is to monitor an interface connected to your ISP. |
| 22 | 20 |
|
| 21 |
The suggest option will try and determine if you have any interfaces with a |
|
| 22 |
public IP and if so it will suggest monitoring those interfaces. If all |
|
| 23 |
IP addresses are private the setup will have to be done manually. Suggest |
|
| 24 |
does not handle IPv6 addresses. |
|
| 25 |
|
|
| 23 | 26 |
=head1 USAGE |
| 24 | 27 |
|
| 25 | 28 |
Any device found in /proc/net/dev can be monitored. Examples include ipsec*, |
| 26 | 29 |
eth*, irda* and lo. |
| 27 | 30 |
|
| 28 |
Please not that aliases cannot be monitored with this plugin. |
|
| 31 |
Please note that aliases cannot be monitored with this plugin.
|
|
| 29 | 32 |
|
| 30 | 33 |
=head1 VERSION |
| 31 | 34 |
|
| 32 |
$Id: bandwidth_,v 1.2 2011/09/16 17:54:50 root Exp $
|
|
| 35 |
$Id: bandwidth_,v 1.35 2012/01/23 20:04:33 root Exp $
|
|
| 33 | 36 |
|
| 34 | 37 |
=head1 AUTHOR |
| 35 | 38 |
|
| ... | ... | |
| 53 | 56 |
|
| 54 | 57 |
=cut |
| 55 | 58 |
|
| 56 |
# Change to show your outside interface |
|
| 57 |
INTERFACE=${0##*bandwidth_}
|
|
| 58 |
HISTORY="/var/lib/munin/plugin-state/bandwidth_$INTERFACE.state" |
|
| 59 |
|
|
| 60 |
TOTALUPTIME=0 |
|
| 61 |
TOTALINPUT=0 |
|
| 62 |
TOTALOUTPUT=0 |
|
| 63 |
OLDUPTIME=0 |
|
| 64 |
OLDINPUT=0 |
|
| 65 |
OLDOUTPUT=0 |
|
| 66 |
|
|
| 67 |
test -f $HISTORY || touch $HISTORY |
|
| 68 |
BC=$(which bc) |
|
| 69 |
test ${#BC} || (echo "bc not found, please install bc" && exit 1)
|
|
| 70 |
|
|
| 71 |
case $1 in |
|
| 72 |
|
|
| 73 |
# I know that "bandwidth is bits and base10 as opposed to bytes and base2. |
|
| 74 |
# However the purpose of this plugin it to monitor your monthly bandwidth |
|
| 75 |
# consumption to make sure you don't go over your ISP's peak. ISP's seem |
|
| 76 |
# to be interested in expressing peaks in bytes.... |
|
| 77 |
|
|
| 78 |
config) |
|
| 79 |
cat <<'EOM' |
|
| 59 |
use strict; |
|
| 60 |
use Storable qw(store retrieve); |
|
| 61 |
use Switch; |
|
| 62 |
|
|
| 63 |
my $interface; |
|
| 64 |
my $history; |
|
| 65 |
my $counter_input; |
|
| 66 |
my $counter_output; |
|
| 67 |
my $input; |
|
| 68 |
my $output; |
|
| 69 |
my $uptime; |
|
| 70 |
my $oldest_ts; |
|
| 71 |
my $input_30days; |
|
| 72 |
my $output_30days; |
|
| 73 |
my $perf_ref = {};
|
|
| 74 |
my $count30 = 2592000; # The number of seconds in 30 days |
|
| 75 |
my $unix_ts = time; |
|
| 76 |
my $rollover = 4294967295; |
|
| 77 |
|
|
| 78 |
eval { init(); };
|
|
| 79 |
|
|
| 80 |
sub autoconf {
|
|
| 81 |
$0 =~ /bandwidth_(.+)*$/; |
|
| 82 |
$interface = $1; |
|
| 83 |
exit 2 unless defined $interface; |
|
| 84 |
$history = "/var/lib/munin/plugin-state/bandwidth_$interface.state"; |
|
| 85 |
} |
|
| 86 |
|
|
| 87 |
sub bit32or64 {
|
|
| 88 |
if ( $input > $rollover || $output > $rollover ) {
|
|
| 89 |
$rollover = 18446744073709551615; |
|
| 90 |
} |
|
| 91 |
} |
|
| 92 |
|
|
| 93 |
sub retrieve_history {
|
|
| 94 |
return (undef) unless ( -r $history ); |
|
| 95 |
my $store = retrieve($history); |
|
| 96 |
while ( my ( $key, $value ) = each(%$store) ) {
|
|
| 97 |
if ( $unix_ts - $key < $count30 ) {
|
|
| 98 |
$perf_ref->{$key} = $value;
|
|
| 99 |
} |
|
| 100 |
if ( $key =~ /last/ ) {
|
|
| 101 |
$perf_ref->{$key} = $value;
|
|
| 102 |
} |
|
| 103 |
|
|
| 104 |
} |
|
| 105 |
} |
|
| 106 |
|
|
| 107 |
sub suggest {
|
|
| 108 |
|
|
| 109 |
# This only works if one of your interfaces has a public IP, |
|
| 110 |
# Otherwise it will fail and you will have to set it manually |
|
| 111 |
# Multiple public IP addresses can be detected. It won't |
|
| 112 |
# Detect IPv6 addresses. |
|
| 113 |
my $locate = readpipe("locate -b '\\ifconfig'");
|
|
| 114 |
my @ifconfig = readpipe($locate); |
|
| 115 |
my @old; |
|
| 116 |
my $net = "/proc/net/dev"; |
|
| 117 |
my @interfaces; |
|
| 118 |
-f $net || die "Unable to read $net: $!"; |
|
| 119 |
open( DEV, "<", $net ) || die "Unable to read $net: $!"; |
|
| 120 |
|
|
| 121 |
while (<DEV>) {
|
|
| 122 |
chomp; |
|
| 123 |
split; |
|
| 124 |
/Inter|face/ and next; |
|
| 125 |
split /:/; |
|
| 126 |
push( @interfaces, $_[0] ); |
|
| 127 |
} |
|
| 128 |
close(DEV); |
|
| 129 |
|
|
| 130 |
foreach (@ifconfig) {
|
|
| 131 |
if (/inet addr:([\d.]+)/) {
|
|
| 132 |
$1 |
|
| 133 |
=~ /^(127\.\d+|10\.\d+|172\.(1[6-9]|2\d|3[0-1])|192\.168)(\.\d+){2}$/
|
|
| 134 |
and next; |
|
| 135 |
exists $interfaces[ $old[0] ] and print "$old[0]\n"; |
|
| 136 |
} |
|
| 137 |
@old = split; |
|
| 138 |
chomp @old; |
|
| 139 |
} |
|
| 140 |
exit 0; |
|
| 141 |
} |
|
| 142 |
|
|
| 143 |
sub store_history {
|
|
| 144 |
|
|
| 145 |
# Store the current values to the new old times |
|
| 146 |
$perf_ref->{$unix_ts} = {
|
|
| 147 |
input => $input, |
|
| 148 |
output => $output, |
|
| 149 |
}; |
|
| 150 |
$perf_ref->{last} = {
|
|
| 151 |
counter_input => $counter_input, |
|
| 152 |
counter_output => $counter_output, |
|
| 153 |
uptime => $uptime, |
|
| 154 |
}; |
|
| 155 |
store( $perf_ref, $history ) || die "Unable to store $history: $!"; |
|
| 156 |
} |
|
| 157 |
|
|
| 158 |
sub arg {
|
|
| 159 |
defined( $ARGV[0] ) or return; |
|
| 160 |
switch ( $ARGV[0] ) {
|
|
| 161 |
case 'autoconf' { print "yes\n"; exit 0; }
|
|
| 162 |
case 'config' { print_config(); }
|
|
| 163 |
case 'suggest' { suggest(); }
|
|
| 164 |
} |
|
| 165 |
} |
|
| 166 |
|
|
| 167 |
sub print_config {
|
|
| 168 |
print <<EOM; |
|
| 80 | 169 |
graph_title Monthly Bandwidth average |
| 81 |
graph_vlabel Bytes |
|
| 82 |
average.label current average |
|
| 83 |
monthly.label monthly projection |
|
| 84 |
average.info Your average bandwidth usage based on uptime |
|
| 85 |
monthly.info Your projected monthly bandwidth usage based on uptime |
|
| 170 |
graph_vlabel Bytes (per sec) |
|
| 171 |
average.label current 30 day average bytes/sec |
|
| 172 |
monthly.label monthly project based on 30 day average |
|
| 173 |
30dayusage.label monthly usage |
|
| 174 |
average.info Your average network rate based (up to) the last 30 days of data |
|
| 175 |
monthly.info Your projected monthly network rate based on your average network rate |
|
| 176 |
30dayusage.info Your usage for the last 30 days. |
|
| 86 | 177 |
graph_category network |
| 87 | 178 |
graph_args --base 1024 -l 0 |
| 88 |
graph_info This graph show your current average bandwidth usage and projected 30 day average based on your current consumption
|
|
| 89 |
average.warning 8944269393.92
|
|
| 179 |
graph_info This graph show your current average bandwidth usage and projected 30 day average based on your last 30 day usage.
|
|
| 180 |
average.warning 103563
|
|
| 90 | 181 |
monthly.warning 268435456000 |
| 182 |
30dayusage.warning 268435456000 |
|
| 91 | 183 |
EOM |
| 92 |
exit 0;; |
|
| 93 |
esac |
|
| 94 |
|
|
| 95 |
source $HISTORY |
|
| 96 |
|
|
| 97 |
INPUT=$(ifconfig $INTERFACE|grep bytes|awk '{print $2}'|sed s/bytes://g)
|
|
| 98 |
OUTPUT=$(ifconfig $INTERFACE|grep bytes|awk '{print $6}'|sed s/bytes://g)
|
|
| 99 |
|
|
| 100 |
|
|
| 101 |
UPTIME=$(cat /proc/uptime | cut -d'.' -f1-1) |
|
| 102 |
|
|
| 103 |
# Dealing with a reboot. I'm not worrying about a uptime rollover. |
|
| 104 |
# Evidently uptime is 64-bit even on 32-bit machines using "jiffies". |
|
| 105 |
if [[ $OLDUPTIME -gt $UPTIME ]]; then |
|
| 106 |
TOTALUPTIME=$(($TOTALUPTIME+$UPTIME)) |
|
| 107 |
TOTALINPUT=$(($TOTALINPUT+$INPUT)) |
|
| 108 |
TOTALOUTPUT=$(($TOTALOUTPUT+$OUTPUT)) |
|
| 109 |
|
|
| 110 |
# Dealing with a 32-bit counter rollover. This is detected by comparing |
|
| 111 |
# The last value with the new value and the uptime. Else update normally |
|
| 112 |
|
|
| 113 |
else |
|
| 114 |
|
|
| 115 |
TOTALUPTIME=$(($TOTALUPTIME+$UPTIME-$OLDUPTIME)) |
|
| 116 |
|
|
| 117 |
if [[ $OLDINPUT -gt $INPUT ]]; then |
|
| 118 |
TOTALINPUT=$(($TOTALINPUT+$INPUT)) |
|
| 119 |
else |
|
| 120 |
TOTALINPUT=$((TOTALINPUT+$INPUT-$OLDINPUT)) |
|
| 121 |
fi |
|
| 122 |
if [[ $OLDOUTPUT -gt $OUTPUT ]]; then |
|
| 123 |
TOTALOUTPUT=$((TOTALOUTPUT+$OUTPUT)) |
|
| 124 |
else |
|
| 125 |
TOTALOUTPUT=$((TOTALOUTPUT+$OUTPUT-$OLDOUTPUT)) |
|
| 126 |
fi |
|
| 127 |
fi |
|
| 128 |
|
|
| 129 |
|
|
| 130 |
|
|
| 131 |
TOTAL=$(($TOTALINPUT+$TOTALOUTPUT)) |
|
| 132 |
UPV=$(echo "scale=3;$TOTALUPTIME/60/60/24"|bc) |
|
| 133 |
DAILY=$(echo "scale=3;$TOTAL/$UPV"|bc) |
|
| 134 |
MONTHLY=$(echo "scale=3;$DAILY*30"|bc) |
|
| 135 |
|
|
| 136 |
echo "TOTALUPTIME=$TOTALUPTIME" > $HISTORY |
|
| 137 |
echo "OLDUPTIME=$UPTIME" >> $HISTORY |
|
| 138 |
echo "TOTALINPUT=$TOTALINPUT" >> $HISTORY |
|
| 139 |
echo "OLDINPUT=$INPUT" >> $HISTORY |
|
| 140 |
echo "TOTALOUTPUT=$TOTALOUTPUT" >> $HISTORY |
|
| 141 |
echo "OLDOUTPUT=$OUTPUT" >> $HISTORY |
|
| 142 |
|
|
| 143 |
echo "average.value $DAILY" |
|
| 144 |
echo "monthly.value $MONTHLY" |
|
| 184 |
exit 0; |
|
| 185 |
} |
|
| 186 |
|
|
| 187 |
sub read_traffic {
|
|
| 188 |
open( my $rx, "<", "/sys/class/net/$interface/statistics/rx_bytes" ) |
|
| 189 |
|| die "Unable to read: $!"; |
|
| 190 |
$counter_input = <$rx>; |
|
| 191 |
chomp $counter_input; |
|
| 192 |
close($rx); |
|
| 193 |
open(my $tx , "<", "/sys/class/net/$interface/statistics/tx_bytes" ) |
|
| 194 |
|| die "Unable to read: $!"; |
|
| 195 |
$counter_output = <$tx>; |
|
| 196 |
chomp $counter_output; |
|
| 197 |
close(DEV); |
|
| 198 |
} |
|
| 199 |
|
|
| 200 |
sub uptime {
|
|
| 201 |
my $puptime = "/proc/uptime"; |
|
| 202 |
open( TIME, "<", $puptime ) || die "Unable to read $puptime: $!"; |
|
| 203 |
while (<TIME>) {
|
|
| 204 |
split; |
|
| 205 |
$uptime = @_[0]; |
|
| 206 |
} |
|
| 207 |
close(TIME); |
|
| 208 |
chomp $uptime; |
|
| 209 |
} |
|
| 210 |
|
|
| 211 |
sub update_stats {
|
|
| 212 |
|
|
| 213 |
# First determine if this has ever run before. If not set initial values |
|
| 214 |
# to 0. |
|
| 215 |
if ( defined $perf_ref->{last}->{uptime} ) {
|
|
| 216 |
|
|
| 217 |
# Compute the new totals, caused by reboot. As uptime is measures in |
|
| 218 |
# 64-bit jiffies, the chance of a counter rollover is remote |
|
| 219 |
if ( $perf_ref->{last}->{uptime} > $uptime ) {
|
|
| 220 |
$input = $counter_input; |
|
| 221 |
$output = $counter_output; |
|
| 222 |
|
|
| 223 |
} |
|
| 224 |
else {
|
|
| 225 |
if ( $perf_ref->{last}->{counter_input} > $counter_input ) {
|
|
| 226 |
$input = |
|
| 227 |
$counter_input |
|
| 228 |
+ $rollover |
|
| 229 |
- $perf_ref->{last}->{counter_input};
|
|
| 230 |
} |
|
| 231 |
else {
|
|
| 232 |
$input = $counter_input - $perf_ref->{last}->{counter_input};
|
|
| 233 |
} |
|
| 234 |
if ( $perf_ref->{last}->{counter_output} > $counter_output ) {
|
|
| 235 |
$output = |
|
| 236 |
$counter_output |
|
| 237 |
+ $rollover |
|
| 238 |
- $perf_ref->{last}->{counter_output};
|
|
| 239 |
} |
|
| 240 |
else {
|
|
| 241 |
$output = |
|
| 242 |
$counter_output - $perf_ref->{last}->{counter_output};
|
|
| 243 |
} |
|
| 244 |
} |
|
| 245 |
} |
|
| 246 |
else {
|
|
| 247 |
$input = 0; |
|
| 248 |
$output = 0; |
|
| 249 |
} |
|
| 250 |
} |
|
| 251 |
|
|
| 252 |
sub sum_old {
|
|
| 253 |
$oldest_ts = $unix_ts; |
|
| 254 |
while ( my ( $key, $value ) = each(%$perf_ref) ) {
|
|
| 255 |
$key =~ /last/ and next; |
|
| 256 |
$input_30days += $perf_ref->{$key}->{'input'};
|
|
| 257 |
$output_30days += $perf_ref->{$key}->{'output'};
|
|
| 258 |
$key < $oldest_ts and $oldest_ts = $key |
|
| 259 |
} |
|
| 260 |
$input_30days += $input; |
|
| 261 |
$output_30days += $output; |
|
| 262 |
} |
|
| 263 |
|
|
| 264 |
sub munin_output {
|
|
| 265 |
my $period = $unix_ts - $oldest_ts; |
|
| 266 |
my $total30 = $input_30days + $output_30days; |
|
| 267 |
my $average30 = $total30 / $period; |
|
| 268 |
print "average.value $average30\n"; |
|
| 269 |
print "monthly.value " . $average30 * $count30 . "\n"; |
|
| 270 |
print "30dayusage.value $total30\n"; |
|
| 271 |
} |
|
| 272 |
|
|
| 273 |
sub init {
|
|
| 274 |
arg(); |
|
| 275 |
autoconf(); |
|
| 276 |
retrieve_history(); |
|
| 277 |
read_traffic(); |
|
| 278 |
bit32or64(); |
|
| 279 |
uptime(); |
|
| 280 |
update_stats(); |
|
| 281 |
sum_old(); |
|
| 282 |
munin_output(); |
|
| 283 |
store_history(); |
|
| 284 |
} |
|
Formats disponibles : Unified diff