#!/usr/bin/perl -w # 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 # use POSIX; use RRDs; use strict; # # Basic setup # my $iface = 'wlan0'; # wireless interface my $step = 10; # sec my $next1_factor = 60; # $step * $next1_factor = 10*60 = 600 sec = 10 min my $next2_factor = 360; # $step * $next2_factor = 10*360 = 3600 sec = 1 hour my $update_graph_period = 10; # How often will be graph updated (1..1000) # # Setup files locations # my $wifi_proc_file='/proc/net/wireless'; my $dev_proc_file='/proc/net/dev'; my $rrd='./istatd.rrd'; my $signal_image='signal.png'; my $transfer_image='transfer.png'; my $pid_file='./istatd.pid'; # # End setup # ############################################################ my $start=time; my $syncrorun; my $switcher=$ARGV[0]; if (!($switcher)) { $switcher='undef'; } if ($switcher eq 'start') { &start(); } elsif ($switcher eq 'stop') { &stop(); } elsif ($switcher eq 'graph') { &update_graph(); } elsif ($switcher eq 'install') { &install(); } else { print qq(Usage: ./istatd.pl option option: start - Starting daemon stop - Stopping daemon graph - Get the latest graph install - Init database ); } ############################################################### sub install { my $sec_in_the_day=86400; my $sec_in_the_week=$sec_in_the_day*7; my $sec_in_the_month=$sec_in_the_day*31; my $minvalue=0; my $maxvalue=255; my $xfiles_factor=0.5; my $max_interval=$step/$xfiles_factor; my $number_steps_day=floor($sec_in_the_day/$step); my $number_steps_week=floor($sec_in_the_week/($step*$next1_factor)); my $number_steps_month=floor($sec_in_the_month/($step*$next2_factor)); RRDs::create ($rrd, "--start",$start-1, "--step",$step, "DS:link:GAUGE:$max_interval:$minvalue:$maxvalue", "DS:level:GAUGE:$max_interval:$minvalue:$maxvalue", "DS:noise:GAUGE:$max_interval:$minvalue:$maxvalue", "DS:in:COUNTER:$max_interval:0:U", "DS:out:COUNTER:$max_interval:0:U", "RRA:AVERAGE:$xfiles_factor:1:$number_steps_day", "RRA:AVERAGE:$xfiles_factor:$next1_factor:$number_steps_week", "RRA:AVERAGE:$xfiles_factor:$next2_factor:$number_steps_month"); my $ERROR = RRDs::error; die "$0: unable to create `$rrd': $ERROR\n" if $ERROR; print "Done.\n"; } ############################################################### sub start { my $pid=fork; exit if $pid; die "Could't fork: $!" unless defined($pid); POSIX::setsid() or die "Can't start a new session: $!"; $SIG{INT}=$SIG{TERM}=$SIG{HUP}=\&syncro_handler; $syncrorun=1; my $pid_id=$$; open(FILE, ">>$pid_file") || die "Cant write to $pid_file file: $!"; print FILE $pid_id; close(FILE); my $counter=0; while ($syncrorun) { $counter++; if (!( -e $pid_file)) { $syncrorun=0; } &get_data(); if ($counter == $update_graph_period) { &update_graph(); $counter=0; } sleep($step); } } ############################################################## sub stop { my $pid=`cat $pid_file`; `kill $pid`; } ############################################################## sub update_graph { RRDs::graph "$signal_image", "--title", " $iface signal statistics", "--start", "now-12h", "--end", "now", "--lower-limit=0", "--interlace", "--imgformat","PNG", "--width=450", "DEF:link=$rrd:link:AVERAGE", # "DEF:level=$rrd:level:AVERAGE", # "DEF:noise=$rrd:noise:AVERAGE", "AREA:link#00b6e4:link", # "LINE1:level#0022e9:level", # "LINE1:noise#cc0000:noise" ; print "ERROR ".RRDs::error."\n" if (RRDs::error); RRDs::graph "$transfer_image", "--title", " $iface transfer statistics", "--start", "now-12h", "--end", "now", "--lower-limit=0", "--interlace", "--imgformat","PNG", "--width=450", "DEF:in=$rrd:in:AVERAGE", "DEF:out=$rrd:out:AVERAGE", "AREA:in#00b6e4:in", "LINE1:out#0022e9:out", ; print "ERROR ".RRDs::error."\n" if (RRDs::error); } ############################################################### sub get_data { my ($link,$level,$noise,$in,$out) = ("U","U","U","U","U"); open(FILE, "$wifi_proc_file") || die "Cant open $wifi_proc_file file: $!"; while (my $line=) { ($link,$level,$noise) = ($1,$2,$3) if ($line=~/\s*?$iface\:\s+?\d+?\s+?(\d+)\.*?\d*?\s+?(\d+)\.*?\d*?\s+?(\d+)\.*?\d*?.*/); } close(FILE); open(FILE, "$dev_proc_file") || die "Cant open $dev_proc_file file: $!"; while (my $line=) { if ($line=~/\s*?$iface\:\s*?(\d+.*)$/) { my @v = split(/\s+/,$1,16); ($in,$out) = ($v[0],$v[8]); } } close(FILE); RRDs::update ("$rrd", "--template", "link:level:noise:in:out", "N:$link:$level:$noise:$in:$out"); print "ERROR ".RRDs::error."\n" if (RRDs::error); } ############################################################### sub syncro_handler { unlink($pid_file) || die "Cant unlink $pid_file file: $!"; $syncrorun=0; }