# # $Header: emagent/scripts/unix/AgentLifeCycle.pm /st_emagent_10.2.0.4.3db11.2.0.2/1 2010/06/08 10:00:34 njagathe Exp $ # # AgentLifeCycle.pm # # Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. # # NAME # AgentLifeCycle.pm - start and stop of the agent. # # DESCRIPTION # Module that handles start and stop of the agent using emctl. # # NOTES # # MODIFIED (MM/DD/YY) # njagathe 05/28/10 - .lr to _lr # njagathe 02/15/08 - XbranchMerge dgiaimo_bug-4757344 from main # kduvvuri 09/10/05 - process abbend file on unix platforms. # kduvvuri 08/22/05 - align the headers. # kduvvuri 08/19/05 - remove temp files. # kduvvuri 08/05/05 - fix 4524126. # vnukal 07/21/05 - returning exit code of stop/istop # kduvvuri 06/21/04 - align the help columns. # kduvvuri 07/09/04 - Add define for EXITFILE. # kduvvuri 05/05/04 - created. # package AgentLifeCycle; use EmctlCommon; use EmCommonCmdDriver; use File::Temp qw/ tempfile /; use POSIX ":sys_wait_h"; sub new { my $classname = shift; my $self = { }; bless ( $self, $classname); #cmdList is a list containing all the command implementors. #construct this some how.. return $self; } sub doIT { my $classname = shift; my $rargs = shift; my $result = $EMCTL_DONE; # if 2nd arg is start agent, look for start and stop as the first args. if ( $rargs->[1] eq "agent" ) { traceDebug("AgentLifeCycle.pm: Processing $rargs->[0] agent"); if ( $rargs->[0] eq "start" ) { startCEMD(); return $EMCTL_DONE; } elsif ( $rargs->[0] eq "stop" ) { $result = stopCEMD(); @retArray = ($EMCTL_DONE,$result); return \@retArray; } elsif ( $rargs->[0] eq "istop" ) { $result = istopCEMD(); @retArray = ($EMCTL_DONE,$result); return \@retArray; } else { return $EMCTL_UNK_CMD; } } else { return $EMCTL_UNK_CMD; #UNKNOWN_COMMAND. } } sub usage { print " emctl start | stop agent\n"; } # # Sub routine to start the CEMD # sub startCEMD { my ($returnCode) = 1; $EMHOME = getEMHome($ENV{CONSOLE_CFG}); traceDebug("AgentLifeCycle.pm: EMHOME is $EMHOME "); testCEMDAvail(); if( $IS_WINDOWS eq "TRUE" ) { $returnCode = system("$ENV{WINDIR}\\system32\\net.exe start $ENV{AGENT_SERVICE_NAME}"); $returnCode >>= 8; traceDebug("AgentLifeCycle.pm:Exiting with $returnCode"); exit $returnCode; } #print "In StartCEMD \n"; my($returnCode) = 0; local $curdir=`pwd`; # get the current directory chomp($curdir); # remove trailing spaces chdir("$EMHOME/sysman/emd"); my($fh,$tmpfilename) = tempfile($UNLINK => 1, DIR => "$EM_TMP_DIR"); close $fh; # closing to prevent file sharing violations on Windows my($rc) = 0xffff & system("$EMDROOT/bin/emdctl status agent >$tmpfilename 2>&1"); $rc >>= 8; traceDebug("AgentLifeCycle.pm:status agent returned with retCode=$rc"); if( $rc == 255) { open ($fh,"<$tmpfilename") or die "Error opening file $tmpfilename: $!\n"; while (<$fh>) { print STDERR; } close $fh or warn "Error closing file $tmpfilename: $!\n"; unlink("$tmpfilename"); exit -1; } unlink("$tmpfilename"); if ( $rc < 2 ) { # Start the agent and wait for 30 secs print "Starting agent ..."; #put the marker in abbend file. $abendBeginTime = localtime(); writeToEMAbbendFile("$EMHOME/sysman/log/agabend.log","$abendBeginTime"); writeToEMAbbendFile("$EMHOME/sysman/log/agabend.log", "$EM_ABBEND_MARKER"); $CHILD_PROCESS = fork(); if( $CHILD_PROCESS == 0 ) { # Need to close the STD handles close(STDIN); close(STDOUT); close(STDERR); # Assume the process group leadership... setpgrp(0, 0); # Exec the emwd process ... exec("$PERL_BIN/perl $EMDROOT/bin/emwd.pl agent " . " $AGENT_NOHUPFILE "); exit 0; } else { local $tries=$EmctlCommon::EMAGENT_TIME_FOR_START_STOP; my $printFromAbend = 0; while( $tries > 0 ) { #print "In parent, doing waipid on $CHILD_PROCESS\n"; $reaped = waitpid($CHILD_PROCESS, &WNOHANG); $processStatus = $? ; #print "processStatus=$processStatus, reaped=$reaped\n"; if ( WIFEXITED($processStatus) ) { $exitCode = WEXITSTATUS($processStatus); traceDebug("AgentLifeCycle.pm:Watch dog processs id: $CHILD_PROCESS exited with an exit code of $exitCode"); if ( ($exitCode == $EM_EXIT_DONT_RESTART) or ($exitCode == $EM_EXIT_THRASH) ) { $printFromAbend = 1; last; } } sleep 1; $rc = 0xffff & system("$EMDROOT/bin/emdctl status agent >$devNull 2>&1"); $rc >>= 8; if ($rc == 3) { last; } $tries = $tries-1; print "."; } traceDebug("AgentLifeCycle.pm: Exited loop with retCode=$rc"); # print appropriate started or failed error message. if( $rc == 3 ) { print " started.\n"; $returnCode = 0; } elsif ( $rc == 4 ) { print " started but not ready. \n"; $returnCode = 0; } else { print " failed.\n"; if ( $printFromAbend == 1 ) { printLastAbbendDetails("$EMHOME/sysman/log/agabend.log"); } print "Consult the log files in: $EMHOME/sysman/log\n"; $returnCode = 1; } } } else { print "Agent is already running\n"; $returnCode = 0; } chdir("$curdir"); exit $returnCode; } # #Print the contents of abbend file since last marker on standard out. # sub printLastAbbendDetails() { my $ag_abbend_file = $_[0]; my $AG_ABBEND_LAST_RUN = "$ag_abbend_file" . "_lr"; my @linesToPrint = (); open(ABBENDLRFILE, ">$AG_ABBEND_LAST_RUN"); open(ABBENDRFILE, "<$ag_abbend_file"); #Get last 4k bytes from abend file and write to abbend_lr seek (ABBENDRFILE, -4096, 2); while(read ABBENDRFILE, $buf, 4096) { print ABBENDLRFILE $buf; } close(ABBENDLRFILE); close(ABBENDRFILE); #Read all of abbend_lr into an array. pop the lines until abbend marker #is hit. open(ABBENDLRFILE,"<$AG_ABBEND_LAST_RUN") ; @abbendlines = ; while ( $abbendline = pop @abbendlines ) { chomp($abbendline); if ( $abbendline eq "$EM_ABBEND_MARKER" ) { last; } push(@linesToPrint, "$abbendline"); } #print the lines in reverse order. while( $lineToPrint = pop @linesToPrint ) { print "$lineToPrint\n"; } } sub stopCEMD { my($returnCode) = 0; testCEMDAvail(); if($IS_WINDOWS eq "TRUE") { $returnCode = system("$ENV{WINDIR}\\system32\\net.exe stop $ENV{AGENT_SERVICE_NAME}"); $returnCode >>= 8; traceDebug("AgentLifeCycle.pm:Exiting with $returnCode"); exit $returnCode; } else { return istopCEMD(); } } # # Issues the stop for CEMD and active waits $EMAGENT_TIME_FOR_START_STOP secs # to check wether the agent was stopped or not. # sub istopCEMD() { $agentStatObj = AgentStatus->new(); my($rc) = $agentStatObj->istatusCEMD(); traceDebug("AgentLifeCycle.pm:istatusCEMD returned $rc"); if( $rc == 255) { return 7; } elsif( $rc == 1) { print "Agent is Not Running\n"; } elsif ( $rc == 3 or $rc == 4 ) { print "Stopping agent ..."; my($fh,$tmpfilename) = tempfile($UNLINK => 1, DIR => "$EM_TMP_DIR"); close $fh; # closing to prevent file sharing violations on Windows $rc = 0xffff & system("$EMDROOT/bin/emdctl stop agent >$tmpfilename 2>&1"); $rc >>= 8; traceDebug("AgentLifeCycle.pm:emdctl stop agent returned $rc"); if($rc != 4) { print "\nStop agent failed\n"; open ($fh,"<$tmpfilename") or die "Error opening file $tmpfilename: $!\n"; while (<$fh>) { print STDERR; } close $fh or warn "Error closing file $tmpfilename: $!\n"; unlink("$tmpfilename"); return 1; } unlink("$tmpfilename"); local $tries=$EmctlCommon::EMAGENT_TIME_FOR_START_STOP; my($rc); while( $tries > 0 ) { sleep 1; $rc = $agentStatObj->istatusCEMD(); if ($rc < 2) { last; } $tries = $tries-1; print "."; } traceDebug("AgentLifeCycle.pm:exited loop with $rc"); # print appropriate started or failed error message. if( $rc < 2 ) { print " stopped.\n"; return 0; } else { print " failed.\n"; return 1; } } return 0; } 1;