jablonka.czprosek.czf

hotsanic

Subversion Repositories:
[/] [branches/] [HotSaNIC-0.5.0-pre6/] [rrdtimer.pl] - Blame information for rev 20

 

Line No. Rev Author Line
11simandl#!/usr/bin/env perl
2 
3# $Id: rrdtimer.pl,v 1.17 2004/07/11 22:39:38 bernisys Exp $
4 
5# include PERL libraries
6use strict;
7use warnings;
8use diagnostics;
9 
10use FindBin;
11use lib $FindBin::RealBin;
12# use Getopt::Long;
13 
14# include HotSaNIC libraries
15use lib "./lib";
16use HotSaNICparser;
17use HotSaNIClog;
18 
19# let all outputs be flushed directly
20$|=1;
21 
22# set commandline correctly
23$0="rrdtimer";
24HotSaNIClog::set_modulename("rrdtimer");
25 
26(my $CALLDIR=$FindBin::RealBin) =~ s/\/rrdtimer//g;
27(my $VERSION = '$Revision: 1.17 $') =~ s/.*(\d+\.\d+).*/$1/;
28(my $IDENTIFIER = '$Id: rrdtimer.pl,v 1.17 2004/07/11 22:39:38 bernisys Exp $') =~ s/.*,v (.*) \$/$1/;
29 
30HotSaNIClog::info("reading & checking config ($CALLDIR/settings) ...");
31my %CONFIG=HotSaNICparser::get_config($CALLDIR);
32$CONFIG{MODULEDIR}=$CONFIG{DAEMONDIR}."/modules";
33$CONFIG{SCHEDULED}=1;
34HotSaNIClog::set_timestamping($CONFIG{TIMESTAMPING});
35 
36my ($debuglevel,$runmode)=check_for_args(@ARGV);
37$CONFIG{DEBUGLEVEL}=HotSaNIClog::get_debuglevel($CONFIG{DEBUGLEVEL});
38$CONFIG{DEBUGLEVEL} |= $debuglevel;
39HotSaNIClog::set_debuglevel($CONFIG{DEBUGLEVEL});
40 
41if (HotSaNIClog::check_debuglevel("MAIN_CONFIG")) { foreach my $k (keys %CONFIG) { HotSaNIClog::info("configuration -> $k=$CONFIG{$k}"); }}
42if ($runmode < 128) { exit 0; }
43 
44my $PID=HotSaNICparser::get_pid($CONFIG{PIDFILE},"rrdtimer");
45if ( $PID>0 ) {
46 HotSaNIClog::error("Another process is running on PID $PID - daemon stopped.");
47 exit 1;
48 }
49 
50my $debug="";
51if (($runmode&1)>0) {
52 HotSaNIClog::info("Debug mode enabled!");
53 HotSaNIClog::info("Identifier: $IDENTIFIER");
54 HotSaNIClog::info("Logdir: $CONFIG{LOGDIR}");
55 HotSaNIClog::info("PID-file: $CONFIG{PIDFILE}");
56 $debug="d";
57 }
58 
59my @PIDs=();
60 
61daemonize();
62 
63$SIG{TERM} = \&signalhandler;
64$SIG{HUP} = \&signalhandler;
65$SIG{USR1} = \&signalhandler;
66$SIG{USR2} = \&signalhandler;
67 
68main_loop();
69 
70 
71######################################################################
72# #
73# SUBROUTINES BEGIN HERE #
74# #
75######################################################################
76 
77 
78######################################################################
79#
80# signal-handler
81# TERM -> terminate daemon and modules
82# HUP -> re-configure
83# USR1 -> kill daemon only
84# USR2 -> kill modules only
85#
86sub signalhandler {
87 my ($sig)=@_;
88 
89 HotSaNIClog::info("$sig received.");
90 if (defined $sig) {
91 if (($sig eq "TERM") || ($sig eq "USR2")) {
92 HotSaNIClog::info("Stopping all running modules.");
93 if (@PIDs) { kill "TERM", @PIDs; @PIDs=(); }
94 }
95 
96 if (($sig eq "TERM") || ($sig eq "USR1")) {
97 HotSaNIClog::info("Daemon exiting normally.");
98 if (-e $CONFIG{PIDFILE}) {
99 unlink $CONFIG{PIDFILE};
100 HotSaNIClog::info("PID-file removed.");
101 }
102 close STDIN;
103 close STDOUT;
104 close STDERR;
105 exit 0;
106 }
107 
108 if ($sig eq "HUP") {
109 HotSaNIClog::info("reconfiguring myself...");
110 %CONFIG=HotSaNICparser::get_config($CALLDIR);
111 $CONFIG{MODULEDIR}=$CONFIG{DAEMONDIR}."/modules";
112 $CONFIG{SCHEDULED}=1;
113 # TODO:
114 #
115 # - kill unused modules
116 # - start configured modules (if necessary)
117 # - re-configure all modules
118 #
119 }
120 }
121 }
122 
123 
124######################################################################
125#
126# the main loop executes all timed scripts:
127#
128# signal modules/*/read-data every 10 sec. (hardcoded)
129# modules/*/diagrams every $DTIME
130# convert() every $CTIME if $CONVERTMETHOD is other than "HTML"
131# scan_for_modules() every $STIME
132#
133sub main_loop {
134 my @modules=();
135 my %MODULES=();
136 
137 my $now=time;
138 my $lastscan=0; # scan for modules directly after being started
139 my $lastdiagram=$now-$CONFIG{DTIME}+30; # generate all diagrams 30 sec. after start
140 my $lastconvert=$now-$CONFIG{CTIME}+300; # build thumbnails 5 minutes after start
141 
142 call_script($CONFIG{DAEMONDIR},"makeindex.pl",0,$CONFIG{LOGDIR}."/makeindex.log",0);
143 
144 while () {
145 $now=time;
146 
147# BUG: sometimes after HUP'ing the @PIDs array contains undefined values
148 
149 if (HotSaNIClog::check_debuglevel("MAIN_HEARTBEAT")) { HotSaNIClog::info("main loop running"); }
150 
151 # Tell modules to sample data. We do this BEFORE starting any module to avoid
152 # too small sample intervals. At start time @PIDs is empty so this code won't
153 # be executed until some modules are started.
154 #
155 if (@PIDs) {
156 if (HotSaNIClog::check_debuglevel("MAIN_SIGNAL")) { HotSaNIClog::info("signaling PIDs: ".join(" ",@PIDs)); }
157 
158 # When no schedule time was configured, signal ALL modules in PARALLEL (may produce high load!)
159 # Otherwhise serialize the signalling a bit.
160 #
161 if ($CONFIG{SCHEDULED} == 0) { kill "SIGUSR1", @PIDs; }
162 else {
163 foreach (@PIDs) {
164 if (defined $_) {
165 kill "SIGUSR1", $_;
166 my $wait=int($CONFIG{SCHEDULE_MIN}+rand($CONFIG{SCHEDULE_MAX}-$CONFIG{SCHEDULE_MIN}))/1000;
167 if (HotSaNIClog::check_debuglevel("MAIN_SIGNAL_VERBOSE")) { HotSaNIClog::info("\"$MODULES{$_}\" called, sleeping $wait sec."); }
168 select(undef,undef,undef,$wait);
169 }
170 }
171 }
172 }
173 
174 # scan for modules and (re-)start them if necessary
175 #
176 if ($lastscan+$CONFIG{STIME} <= $now) {
177 @modules=HotSaNICparser::scan_for_modules($CONFIG{MODULEDIR},$CONFIG{RUN});
178 %MODULES=call_modules(@modules);
179 @PIDs=keys(%MODULES);
180 $lastscan=int($now/$CONFIG{STIME})*$CONFIG{STIME};
181 if ($debug ne "d") { logrotate(); }
182 }
183 
184 # check if diagrams have to be built.
185 #
186 if ($lastdiagram+$CONFIG{DTIME} <= $now) {
187 my $append;
188 if ($CONFIG{DIAGRAMLOG} eq "all") { $append=1; }
189 call_script($CONFIG{DAEMONDIR},"diagrams.pl",5,$CONFIG{LOGDIR}."/diagram.log",$append);
190 $lastdiagram=int($now/$CONFIG{DTIME})*$CONFIG{DTIME};
191 }
192 
193 # check if thumbnails have to be generated.
194 #
195 if (($lastconvert+$CONFIG{CTIME} <= $now) && ($CONFIG{CONVERTMETHOD} ne "HTML")) {
196 call_script($CONFIG{DAEMONDIR},"convert.pl",0,$CONFIG{LOGDIR}."/convert.log",0);
197 $lastconvert=int($now/$CONFIG{CTIME})*$CONFIG{CTIME};
198 }
199 
200 # sleep until system time's next full 10 seconds
201 #
202 my $sleeptime=10-(time % 10);
203 sleep $sleeptime;
204 }
205 }
206 
207 
208######################################################################
209#
210# start read-data.pl script in each module
211#
212sub call_modules {
213 my (@modules)=@_;
214 my %MODULES;
215 my $nicelevel="0";
216 my $have_started=0;
217 
218 if (HotSaNIClog::check_debuglevel("MAIN_SCAN_MODULES")) { HotSaNIClog::info("Checking modules..."); }
219 
220 # iterate through all configured modules...
221 #
222 for my $module (@modules) {
223 my $verbose=0;
224 if (HotSaNIClog::check_debuglevel("MAIN_SCAN_MODULES_VERBOSE")) { $verbose=1; }
225 chdir $CONFIG{MODULEDIR}."/$module";
226 
227 my $PID=HotSaNICparser::get_pid();
228 
229 # if not running, start the module and wait for PID-file to be generated
230 #
231 if ($PID == 0) {
232 if (HotSaNIClog::check_debuglevel("MAIN_SCAN_MODULES")) { HotSaNIClog::info("starting module \"$module\""); }
233 if (HotSaNIClog::check_debuglevel("MAIN_SCAN_MODULES_VERBOSE")) { HotSaNIClog::info("----- begin start module \"$module\" -----"); }
234 $verbose=1;
235 if (-e "./running.pid") {
236 if (HotSaNIClog::check_debuglevel("MAIN_SCAN_MODULES_VERBOSE")) { HotSaNIClog::info("removing old PID-file"); }
237 unlink "./running.pid";
238 }
239 my $EXEC="";
240 if (-e "./read-data-wrapper.pl") { $EXEC="nice -$nicelevel ./read-data-wrapper.pl start $module"; }
241 elsif (-e "./read-data.pl") { $EXEC="nice -$nicelevel ./read-data.pl start $module"; }
242 else {
243 HotSaNIClog::error("cannot find read-data script for module \"$module\"");
244 next;
245 }
246 system "$EXEC";
247 
248 # wait for module writing its PID-file
249 #
250 my $count=0;
251 while ( ($count<80) && (! -s "./running.pid") ) {
252 if ($count == 0) { HotSaNIClog::info("waiting for module's PID-file"); }
253 $count++;
254 print "." if ($count%5 == 0);
255 select(undef,undef,undef,0.25);
256 }
257 print "\r" if ($count > 0);
258 $PID=HotSaNICparser::get_pid();
259 #if PID is valid -> sample for the first time after startup
260 if ($PID > 0) { kill "SIGUSR1",$PID; }
261 HotSaNIClog::info("----- end start module \"$module\" -----");
262 $have_started++;
263 }
264 
265 if ($PID >0) {
266 if ($verbose>0) { HotSaNIClog::info("\"$module\" running on PID $PID"); }
267 $MODULES{$PID}=$module;
268 }
269 else { HotSaNIClog::error("PID for \"$module\" could not be determined"); }
270 }
271 if ($have_started>0) { HotSaNIClog::info("-" x 75); }
272 return %MODULES;
273 }
274 
275 
276######################################################################
277#
278# call external script (incl. sanity checking etc)
279#
280sub call_script {
281 my ($path,$script,$nicelevel,$output,$append)=@_;
282 
283 if (! defined $append) { $append=0; }
284 if (! defined $output) { $output=""; }
285 if (! defined $nicelevel) { $nicelevel=0; }
286 
287 if ( (defined $path) && (defined $script) ) {
288 if (HotSaNIClog::check_debuglevel("MAIN_CALL_SCRIPT")) { HotSaNIClog::info("executing \"$path/$script\" with nice $nicelevel"); }
289 if ( -e "$path/$script") {
290 if ($output ne "") {
291 my $logaction="appending";
292 if (index("1 yes true",lc $append) < 0) {
293 rename $output,"$output.old";
294 $logaction="logging";
295 }
296 if (HotSaNIClog::check_debuglevel("MAIN_CALL_SCRIPT")) { HotSaNIClog::info("$logaction output to $output"); }
297 if ($nicelevel ne 0) {system ("cd \"$path\"; nice -$nicelevel ./$script >$output 2>&1 &"); }
298 else {system ("cd \"$path\"; ./$script >$output 2>&1 &"); }
299 }
300 else {
301 if ($nicelevel ne 0) {system ("cd \"$path\"; nice -$nicelevel ./$script &"); }
302 else {system ("cd \"$path\"; ./$script &"); }
303 }
304 }
305 else { HotSaNIClog::error("script \"$path/$script\" not found! Check your installation."); }
306 }
307 }
308 
309 
310######################################################################
311#
312# fork into background
313#
314sub daemonize {
315 use POSIX qw(setsid);
316 HotSaNIClog::info("entering daemon mode...");
317 if ($debug eq "") {
318 close STDIN;
319 close STDOUT;
320 close STDERR;
321 if (open(DEVTTY, "/dev/tty")) { ioctl(DEVTTY,0x20007471,0); close DEVTTY; }
322 open STDIN,"/dev/null";
323 open STDOUT,">>".$CONFIG{LOGDIR}."/HotSaNIC.log";
324 open STDERR,">&STDOUT";
325 setpgrp(0,$$);
326 chdir "/";
327 fork && exit 0;
328 setsid;
329 HotSaNIClog::info("archiver successfully forked into background and running on PID $$");
330 }
331 else { HotSaNIClog::info("archiver running in debug-mode on PID $$"); }
332 HotSaNIClog::info("-" x 75);
333 open FILE,">".$CONFIG{PIDFILE};
334 print FILE $$;
335 close FILE;
336 }
337 
338 
339######################################################################
340#
341# rotate logfiles
342#
343sub logrotate {
344 my ($size,$file);
345 
346 if ($debug ne "d") {
347 
348 $file=$CONFIG{LOGDIR}."/HotSaNIC.log";
349 (undef,undef,undef,undef,undef,undef,undef,$size,undef,undef,undef,undef,undef) = stat($file);
350 if (defined $size) {
351 if ($size > $CONFIG{LOGSIZE}) {
352 HotSaNIClog::info("$file exceeding $CONFIG{LOGSIZE} bytes - rotating - keeping $CONFIG{LOGBACKUPS} backups.");
353 for (my $nn=$CONFIG{LOGBACKUPS};$nn>1;$nn--) {
354 if ( -e "$file.$nn" ) { unlink "$file.$nn"; }
355 if ( -e "$file.".($nn-1) ) { rename "$file.".($nn-1),"$file.".$nn; }
356 }
357 close STDOUT;
358 rename $file,"$file.1";
359 open STDOUT,">>$file";
360 close STDERR;
361 rename $file,"$file.1";
362 open STDERR,">>$file";
363 }
364 }
365 }
366 }
367 
368 
369######################################################################
370#
371# evaluate commandline arguments
372#
373sub check_for_args {
374 HotSaNIClog::info("evaluating cmdline arguments...");
375 my @args=@_;
376 
377 # set initial values
378 #
379 my $debuglevel=0;
380 my $runmode=0;
381 
382 # Check if we were called with any options
383 #
384 foreach my $arg (@args) {
385 if (index($arg,"d") >= 0) { $runmode|=1; }
386 if (index($arg,"D") >= 0) { $runmode|=128; }
387 if (index($arg,"h") >= 0) { $runmode|=256; }
388 if (index($arg,"?") >= 0) { $runmode|=256; }
389 $arg=~ s/[a-zA-Z]//g;
390 if ($arg =~ /[0-9]/) { if ($arg > 0) { $debuglevel=$arg; } }
391 }
392 
393 if (($runmode == 0) || ($runmode > 255)) {
394 print "rrdtimer - CVS version $VERSION ($IDENTIFIER) - OS: $^O\n";
395 print "usage:\nrrdtimer [options[debuglevel]]\n options:\n";
396 print " D - enter daemon-mode (i.e. start the main loop)\n";
397 print " d - enter debugging mode (don't fork into background)\n";
398 print "\n";
399 exit 0;
400 }
401 return ($debuglevel,$runmode);
402 }
403 
404 

Powered by WebSVN 2.2.1