![]() ![]() |
hotsanic |
Subversion Repositories: |
Compare with Previous - Blame - Download
#!/usr/bin/env perluse strict;use warnings;use diagnostics;## $Id: rrdtimer.pl,v 1.3 2003/10/16 10:25:36 bernisys Exp $## use Getopt::Long;use FindBin;use lib "./lib";use lib $FindBin::RealBin;use HotSaNICparser;use subs qw(main_loop call_modules call_module_read daemonize);# let all outputs be flushed directly$|=1;# set commandline correctly$0="rrdtimer";(my $CALLDIR=$FindBin::RealBin) =~ s/\/rrdtimer//g;(my $VERSION = '$Revision: 1.3 $') =~ s/.*(\d+\.\d+).*/$1/;(my $IDENTIFIER = '$Id: rrdtimer.pl,v 1.3 2003/10/16 10:25:36 bernisys Exp $') =~ s/.*,v (.*) \$/$1/;print "reading & checking config ($CALLDIR/settings) ...\n";my %CONFIG=HotSaNICparser::get_config($CALLDIR);$CONFIG{MODULEDIR}=$CONFIG{DAEMONDIR}."/modules";$CONFIG{SCHEDULED}=1;print "evaluating cmdline arguments...\n";my ($debuglevel,$runmode)=check_for_args(@ARGV);if ($debuglevel>$CONFIG{"DEBUGLEVEL"}) { $CONFIG{"DEBUGLEVEL"}=$debuglevel; }if ($CONFIG{DEBUGLEVEL} >0) { foreach my $k (keys %CONFIG) { print "$k=$CONFIG{$k}\n"; }}if ($runmode < 128) { exit 0; }my $PID=HotSaNICparser::get_pid($CONFIG{DEBUGLEVEL},$CONFIG{PIDFILE},"rrdtimer");if ( $PID>0 ) {print "\nAnother process is running on PID $PID - daemon stopped.\n\n";exit 1;}my $debug="";if (($runmode&1)>0) { print "Debug mode enabled!\nIdentifier: $IDENTIFIER,\nLogdir: ",$CONFIG{LOGDIR},"\nPIDfile: ",$CONFIG{PIDFILE},"\n\n"; $debug="d"; }my @PIDs;my %PIDs;daemonize();$SIG{TERM} = \&signalhandler;$SIG{HUP} = \&signalhandler;$SIG{USR1} = \&signalhandler;$SIG{USR2} = \&signalhandler;main_loop();####################################################################### ## SUBROUTINES BEGIN HERE ## ############################################################################################################################################### signal-handler# TERM -> terminate daemon and modules# HUP -> re-configure# USR1 -> kill daemon only# USR2 -> kill modules only#sub signalhandler {my ($sig)=@_;if (defined $sig) {if (($sig eq "TERM") ||($sig eq "USR2")) {print time,"Stopping all running modules.\n";if (@PIDs) { kill "TERM", @PIDs; @PIDs=(); }}if (($sig eq "TERM") || ($sig eq "USR1")) {print time,"Daemon exiting normally.\n";if (-e $CONFIG{PIDFILE}) {unlink $CONFIG{PIDFILE};print "PID-file removed.\n";}close STDIN;close STDOUT;close STDERR;exit 0;}if ($sig eq "HUP") {print time," HUP signal received - signal not implemented yet...\n";foreach (keys %CONFIG) { print $_," -> ",$CONFIG{$_},"\n"; }# TODO:## - kill unused modules# - start configured modules (if necessary)# - re-configure all modules#}}}######################################################################## the main loop executes all timed scripts:## modules/*/read-data every >=10 sec. (hardcoded)# modules/*/diagrams every $DTIME# convert() every $CTIME if $CONVERTMETHOD is other than "HTML"# scan_for_modules() every $STIME#sub main_loop {my ($now,$last,$sleeptime,$lastscan,$lastdiagram,$lastconvert,@modules);$now=time;$last=$now-100;$lastscan=$now;$lastdiagram=int($now/$CONFIG{DTIME})*$CONFIG{DTIME};$lastconvert=int($now/$CONFIG{CTIME})*$CONFIG{CTIME};@modules=HotSaNICparser::scan_for_modules($CONFIG{MODULEDIR},$CONFIG{DEBUGLEVEL},$CONFIG{RUN});if ($CONFIG{DEBUGLEVEL} > 0) { print time,": initializing modules...\n"; }initialize_modules(@modules);%PIDs=call_modules(@modules);@PIDs=keys(%PIDs);while () {$now=time;# if ($last+10 <= $now) {if ($CONFIG{DEBUGLEVEL} > 0) { print "$now: main loop running\n"; }# scan for modules and (re-)start them if necessary#if ($lastscan+$CONFIG{STIME} <= $now) {@modules=HotSaNICparser::scan_for_modules($CONFIG{MODULEDIR},$CONFIG{DEBUGLEVEL},$CONFIG{RUN});%PIDs=call_modules(@modules);@PIDs=keys(%PIDs);$lastscan=$now;if ($CONFIG{DEBUGLEVEL} < 0) { logrotate(); }}# for each module call the read-data script.#if ($CONFIG{DEBUGLEVEL} > 0) { print "$now: signaling ",join " ",@PIDs,"\n"; }if (@PIDs) {if ($CONFIG{SCHEDULED} == 0) { kill "SIGUSR1", @PIDs; }else {foreach (@PIDs) {kill "SIGUSR1", $_;my $wait=int($CONFIG{SCHEDULE_MIN}+rand($CONFIG{SCHEDULE_MAX}-$CONFIG{SCHEDULE_MIN}))/1000;if ($CONFIG{DEBUGLEVEL} >3) { print "$wait($PIDs{$_}) "; }select(undef,undef,undef,$wait);}if ($CONFIG{DEBUGLEVEL} >3) { print "\n"; }}}$last=$now;# }# check if diagrams have to be built.#if ($lastdiagram+$CONFIG{DTIME} <= $now) {my $append;if ($CONFIG{DIAGRAMLOG} eq "all") { $append=1; }call_script($CONFIG{DAEMONDIR},"diagrams.pl",5,$CONFIG{LOGDIR}."/diagram.log",$append);$lastdiagram+=$CONFIG{DTIME};# check if mainpage-diagrams have to be generated.#if (($lastconvert+$CONFIG{CTIME} <= $now) && ($CONFIG{CONVERTMETHOD} ne "HTML")) {call_script($CONFIG{DAEMONDIR},"convert.pl",0);$lastconvert+=$CONFIG{CTIME};}}$sleeptime=10-(time % 10);sleep $sleeptime;}}######################################################################## call init script in each module (if available)#sub initialize_modules {my (@modules)=@_;my ($name,$ouser,$osystem,$user,$system,$utime,$stime);print time," Initializing modules...\n";for $name (@modules) {unlink $CONFIG{MODULEDIR}."/$name/*.dat";# unlink $CONFIG{MODULEDIR}."/$name/*.pid";unlink $CONFIG{MODULEDIR}."/$name/*.old";if ( -e $CONFIG{MODULEDIR}."/$name/init" ) {print time," initializing ",$name,"\n";system "cd ".$CONFIG{MODULEDIR}."/$name; ./init";print time," initializing of ",$name," DONE!\n\n";}}print time," END Initializing modules...\n","-" x 50,"\n\n";}######################################################################## start read-data.pl script in each module#sub call_modules {my (@modules)=@_;my %PIDs;my $nicelevel="0";# iterate through all configured modules...#for my $module (@modules) {chdir $CONFIG{MODULEDIR}."/$module";my $PID=HotSaNICparser::get_pid($CONFIG{DEBUGLEVEL});# if not running, start the module and wait for PIDfile to be generated#if ($PID == 0) {my $count=-1;print "\nstarting module: \"$module\"\n";if (-e "./running.pid") {if ($CONFIG{DEBUGLEVEL}>1) { print "removing old PIDfile...\n"; }unlink "./running.pid";}if (-e "./read-data-wrapper.pl") { system("nice -$nicelevel ./read-data-wrapper.pl start $module"); }else { system("nice -$nicelevel ./read-data.pl start $module"); }$count=0;while ( ($count<20) && (! -s "./running.pid") ) {$count++;print ".";sleep 1;}$PID=HotSaNICparser::get_pid($CONFIG{DEBUGLEVEL});}if ($PID >0) {print "$module running on PID $PID\n\n";$PIDs{$PID}=$module;}}return %PIDs;}######################################################################## call external script (incl. sanity checking etc)#sub call_script {my ($path,$script,$nicelevel,$output,$append)=@_;if (! defined $append) { $append=0; }if ( index("1 yes",lc $append) < 0) { rename $output,"$output.old"; }if (! defined $output) { $output=""; }if (! defined $nicelevel) { $nicelevel=0; }if ( (defined $path) && (defined $script) ) {print time,": executing $path/$script with nice $nicelevel\n";if ( -e "$path/$script") {if ($output ne "") {if ($nicelevel ne 0) {system ("cd \"$path\"; nice -$nicelevel ./$script >$output &"); }else {system ("cd \"$path\"; ./$script >$output &"); }}else {if ($nicelevel ne 0) {system ("cd \"$path\"; nice -$nicelevel ./$script &"); }else {system ("cd \"$path\"; ./$script &"); }}}else { print time.": script not found! Check your installation.\n"; }}}######################################################################## fork into background#sub daemonize {print "entering daemon mode...\n";if ($debug eq "") {close STDIN;close STDOUT;close STDERR;if (open(DEVTTY, "/dev/tty")) { ioctl(DEVTTY,0x20007471,0); close DEVTTY; }open STDIN,"/dev/null";open STDOUT,">>".$CONFIG{LOGDIR}."/HotSaNIC.log";open STDERR,">&STDOUT";chdir "/";fork && exit 0;print "\n\n----------------------------------------\n";print time,": archiver successfully forked into background and running on PID $$\n";}else { print time,": archiver running in debug-mode on PID $$\n"; }open FILE,">".$CONFIG{PIDFILE};print FILE $$;close FILE;}######################################################################## rotate logfiles#sub logrotate {my ($size,$file);if ((defined $CONFIG{DEBUGLEVEL}) && ($CONFIG{DEBUGLEVEL} < 0)) {$file=$CONFIG{LOGDIR}."/HotSaNIC.log";(undef,undef,undef,undef,undef,undef,undef,$size,undef,undef,undef,undef,undef) = stat($file);if (defined $size) {if ($size > $CONFIG{LOGSIZE}) {print time," $file exceeding ",$CONFIG{LOGSIZE}," bytes - rotating - keeping ",$CONFIG{LOGBACKUPS}," backups.\n";for (my $nn=$CONFIG{LOGBACKUPS};$nn>1;$nn--) {if ( -e "$file.$nn" ) { unlink "$file.$nn"; }if ( -e "$file.".($nn-1) ) { rename "$file.".($nn-1),"$file.".$nn; }}close STDOUT;rename $file,"$file.1";open STDOUT,">>$file";close STDERR;rename $file,"$file.1";open STDERR,">>$file";}}}}######################################################################## evaluate commandline arguments#sub check_for_args {my @args=@_;# set initial values#my $debuglevel=-1;my $runmode=0;# Check if we were called with any options#foreach my $arg (@args) {if (index($arg,"d") >= 0) { $runmode|=1; }if (index($arg,"D") >= 0) { $runmode|=128; }if (index($arg,"?") >= 0) { $runmode|=256; }$arg=~ s/[a-zA-Z]//g;if ($arg =~ /[0-9]/) { if ($arg > 0) { $debuglevel=$arg; } }}if (($runmode == 0) || ($runmode > 255)) {print "rrdtimer - CVS version $VERSION ($IDENTIFIER) - OS: $^O\n";print "usage:\nrrdtimer [options[debuglevel]]\n options:\n";print " D - enter daemon-mode (i.e. start the main loop)\n";print " d - enter debugging mode (don't fork into background)\n";print "\n";exit 0;}return ($debuglevel,$runmode);}