#!/opt/perl-5.6.1/bin/perl ################################################################################ ############ #Initial Phase: Make a working daemon. #Second Phase: Fork child processes. #Third phase: Build a basic framework wherein the individual pieces of functionalities can be just plugged in. #Fourth Phase: Build the individual pieces of checks / other functionalities like debug option, logging other checks etc. #Fifth Phase: Bind the different functionalities with the basic framework. #Sixth Phase: Test the compelete script. #Seventh Phase: Performance improvement. ################################################################################ ############ use POSIX; use FileHandle; use File::Basename; use IO::Handle; #$PGM=basename($0); $DEF_TIMEOUT=60; $CHILD_TIMEOUT=10; $NUM_OF_KIDS=4; $shutitdown=0; #Please do not change this value. my $pid; my $file='/home/hkitmond/test.txt'; my $file2='/home/hkitmond/pid.txt'; my $logfile='/home/hkitmond/log'; STDOUT->autoflush(1); STDERR->autoflush(1); @jobs = (); %job = (); ###############Install signal handler############ $SIG{'TERM'}=$SIG{'INT'}=$SIG{'HUP'}=$SIG{'QUIT'}='shutdown'; ################################################# if ($pid=fork()){ print "\nI am the parent and just forked a child that has this PID:$pid"; #####Log this PID somewhere so that it can be used while issuing /bin/kill -s TERM ############## open(PIDFILE, '>/home/hkitmond/pid.txt'); print PIDFILE "$pid"; close(PIDFILE); ###################################################################################################### print "\nExiting.."; exit 0; } elsif(!defined $pid){ print "\nCouldn't fork child. Probably process table is filled. Get in touch with sysadm!!"; } else{ #This is the thread that is actually the daemon and it will keep running forever. setpgrp(0, 0); chdir('/'); print STDOUT "\nI am the child $$ and have just been forked by my parent. Now I have become a daemon."; open(LOGFILE,'>/home/hkitmond/log'); LOGFILE->autoflush(1); while(1){ open(INPUT, $file)||die ("\nCannot open $file"); chomp (@args=); close(INPUT); $i=1; #if ($shutitdown==0){ #foreach $node (@args){ while ($node = shift(@args)){ if ($shutitdown==0){ $READER = "READER$i"; $WRITER = "WRITER$i"; pipe($READER, $WRITER); $WRITER->autoflush(1); if ($pid = fork()){ close($WRITER); $job{$pid}{'pipe'}= $READER; } elsif(!defined $pid){ print "\nCouldn't fork child"; } else{ ###This is the thread invoked per server - it will contain calls to wrapper scripts for every check. Agent scripts reside on agent. ###This thread will exit after it runs checks and other tasks. ###################################### #Include timeout functionality here to make sure a thread doesn't linger too long. #Install the appropriate signal handler for timeout $SIG{'ALRM'}='thread_hung'; alarm $CHILD_TIMEOUT; print STDOUT "\nI am the child $$ corresponding to $node"; setpgrp(0, 0); close($READER); chdir('/'); ################################## #Write code here to call scripts to invoke various checks# #Use timeout functionality #while(1){ #} @RES = system("/usr/sbin/ping $node 3 > /dev/null"); ################################## $m="$$:$node:x_START_x"; print $WRITER "$m\n"; foreach $m (@RES){ print $WRITER "$m\n"; } close($WRITER); ###Exit this thread### exit 0; } ################################################################################# #Need to implement logic to allow no more than defined number of threads to run parallely #while(scalar(keys %job) >= $NUM_OF_KIDS || (%job && (scalar @args < $NUM_OF_KIDS))){ while(scalar(keys %job) >= $NUM_OF_KIDS || ((scalar(keys %job) >= 1) && (scalar @args == 0))){ print STDOUT "\n".scalar(keys %job).",".scalar @args; print STDOUT "\nWaiting for some child..."; $kpid= wait; #waiting for any child process to finish. This is essential for proper termination of child. print STDOUT "\nJust waited for $kpid child"; #$a = @args; #not sure why this is added. next unless $job{$kpid}; #Not required actually. @kid_stdout = (); $PIPE=$job{$kpid}{'pipe'}; chomp(@kid_stdout=<$PIPE>); close($PIPE); foreach $l (@kid_stdout){ print STDOUT "\n$l"; print LOGFILE "\n$l"; } delete($job{$kpid}); #removing the element from job corresponding to this process } ##Logic to restrict number of parallel threads less than the predefined value ends #################################################################################### print STDOUT "\nGoing to next run of loop"; $i++; } #If block corresponding to $shutitdown=0 ends ######################################################################## #Need to include logic such that if a daemon needs to be killed, it catches this signal, does the required cleanup and then exits. #If its req. to stop the daemon, use /bin/kill -9 command which will be caught by signal handler and the required cleanup will be done. ######################################################################## else{ ############################################################## #This block contains logic such that on reception of SIGTERM, the already forked processes are waited upon by the parent. #We need to consider the situation where some child has already been killed as a result of timeout. ############################################################## print STDOUT "\nInside the cleanup section..."; print STDOUT "\nNumber of outstanding processes:".scalar(keys %job)." .."; while(scalar(keys %job) != 0){ $pid=wait; delete($job{$pid}); print STDOUT "\nJust received exit status of $pid. Waiting for ".scalar(keys %job)." others before stopping the daemon.."; } print "\nDaemon exiting..."; close(LOGFILE); exit 0; } #Else block corresponding to cleanup i.e. $shutitdown=1 ends } #for loop corresponding to every node from i/p file ends. =piyush ######################################################################## #Need to include logic such that if a daemon needs to be killed, it catches this signal, does the required cleanup and then exits. #If its req. to stop the daemon, use /bin/kill -9 command which will be caught by signal handler and the required cleanup will be done. ######################################################################## else{ ############################################################## #This block contains logic such that on reception of SIGTERM, the already forked processes are waited upon by the parent. #We need to consider the situation where some child has already been killed as a result of timeout. ############################################################## print STDOUT "\nInside the cleanup section..."; print STDOUT "\nNumber of outstanding processes:".scalar(keys %job)." .."; while(scalar(keys %job) != 0){ $pid=wait; delete($job{$pid}); print STDOUT "\nJust received exit status of $pid. Waiting for ".scalar(keys %job)." others before stopping the daemon.."; } print "\nDaemon exiting..."; exit 0; } #Else block corresponding to cleanup i.e. $shutitdown=1 ends =cut } #End of infinite while loop } #end of daemon code. ##############Subroutines Section############################################# sub shutdown{ print STDOUT "\nReceived stop signal. Stopping the daemon..."; $shutitdown=1; } sub thread_hung{ print STDOUT "\nThread $$ is hung. Aborting.."; $id=$$; $pipe=$job{$id}{'pipe'}; delete($job{$id}); kill -9, $id; close($pipe); }