# $Header: emdb/scripts/unix/DBConsole.pm.template /st_emdbsa_11.2/12 2010/08/21 17:56:48 rpattabh Exp $ # # Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. # # NAME # DBConsole.pm - Perl Module to provide start, stop, status functionality # # DESCRIPTION # This script provides the stop,status,debug functionality for # the emwd and the emctl. Additionally it may hold other # states like the start time, its PID, thrashCount etc. # # MODIFIED (MM/DD/YY) # rpattabh 08/20/10 - Bug 10041125: Use ps -aef on Solaris # sshastry 02/09/09 - apply mix case fix # ashomish 02/04/09 - fix bug 8217579 # gapadman 11/22/08 - change UNQNAME message # ashomish 11/04/08 - fix bug 7422635 # ashomish 09/30/08 - Remove version hard coding # rsamaved 05/21/08 - use ORACLE_UNQNAME instead of DB_UNIQUE_NAME # rsamaved 05/08/08 - update version to 11.2 # swexler 04/08/08 - move functions here # dchakumk 03/10/08 - XbranchMerge dchakumk_6752_xbmsrc from # st_emdbsa_11.1 # swexler 02/18/08 - remove ipv4 flags # swexler 02/08/08 - change version # swexler 01/31/08 - fix for bad oc4j shutdowns # dchakumk 01/07/08 - Merging a2 files from stpl_emdb_main_gen as per # janet # ezeng 12/18/07 - Backport ezeng_bug-6396653_gc from main # snandarg 09/18/07 - Fixing syntax issue # vgoli 09/11/07 - XbranchMerge vgoli_bug-6346876 from main # vgoli 08/22/07 - change ps command options for HP-UX # misun 08/22/07 - fix the bug 6346686: emctl status dbconsole # reports dbconsole to be not running but em is up. # sresrini 08/17/07 - bug 6339100 # sresrini 08/17/07 - bug 6339100 # kdas 06/27/07 - XbranchMerge kdas_bug-6042435 from st_emdbsa_11.1 # misun 06/08/07 - fix the bug 6037461: version number should be # 11.1.0.6.0 for db control production. # kdas 05/22/07 - hit the logon page for initializing image cache # misun 05/21/07 - fix bug 6062223, beta5 :emctl status dbconsole # shows 11.1.0.4.0. # vivsharm 04/04/07 - If EM OC4J ADMIN password is defined use that # rsamaved 04/03/07 - fix pid parsing # misun 02/06/07 - update DB version number to 11.1.0.4.0 # misun 10/18/06 - update DB version number # rsamaved 09/02/06 - fix warning during stop # misun 09/06/06 - update DB version number # vivsharm 08/21/06 - lrg 2505782 # misun 08/16/06 - update DB version number # vivsharm 07/25/06 - bug 5408027 # rdabbott 07/28/06 - fix header # vivsharm 04/12/06 - fix stop dbconsole # blivshit 05/05/05 - porting fix for RLAL # kduvvuri 07/28/04 - add getVersion. # aaitghez 06/08/04 - bug 3656322. Cleanup perl warnings # kduvvuri 06/01/04 - add destroy method and setImageCacheInitialized. # rzazueta 12/17/03 - Increase sleep time in debug # rzazueta 12/01/03 - Deprecate password to shutdown DBConsole # dmshah 09/17/03 - Code review changes # dmshah 09/15/03 - Integration testing changes # dmshah 09/11/03 - Check for stack dump during stop # dmshah 09/03/03 - Removing dependency on instantiated port settings # dmshah 07/09/03 - Testing changes # dkapoor 07/07/03 - use admin instead of ias_admin # szhu 06/20/03 - Workaround for status() # vnukal 06/17/03 - adding okToRestart method # dmshah 05/08/03 - Obsoleting getProcList # dmshah 04/06/03 - dmshah_bug-2849086_mainsa # dmshah 04/08/03 - Removing hardcoded pid from stopSAC # dmshah 03/14/03 - Adding restart code # dmshah 03/13/03 - Adding incThrashCount # dmshah 03/11/03 - dmshah_em_watchdog # dmshah 03/06/03 - Using signal 0 for process liveness # dmshah 03/03/03 - Fixing constructor syntax # dmshah 03/03/03 - Testing if..else block # dmshah 02/26/03 - Created. # package DBConsole; use strict; use EmctlCommon; use LWP::Simple; use LWP::UserAgent; use URI; use DBConsoleBanner; $DB_NOHUPFILE=getEMHome("dbconsole") . "/sysman/log/emdb.nohup"; # Nohup file when only the agent is running. $AGENT_NOHUPFILE=getEMHome("dbconsole") . "/sysman/log/emagent.nohup"; $PID_FILE=getEMHome("dbconsole") . "/emctl.pid"; sub new { my ($class) = @_; my $self = { PID => -1, name => undef, startTime => -1, thrashCount => 0, imageCacheInitialized => 0, debug => 0, emHome => getEMHome("dbconsole"), oc4jHome => getOC4JHome("dbconsole"), url => getWebUrl(getOC4JHome("dbconsole"), getEMHome("dbconsole"), "dbconsole"), rmiPort => getORMIPort( getOC4JHome("dbconsole") ), initialized => 0 }; bless $self, $class; return $self; } # # Initialize # Ensure that the values are correct. # sub Initialize { my ($self) = shift; my ($inPID) = shift; my ($inStartTime) = shift; my ($debugFlag) = shift; $self->{PID} = $inPID; $self->{startTime} = $inStartTime; $self->{thrashCount} = 0; $self->{name} = "DBConsole"; $self->{initialized} = 1; $self->{debug} = $debugFlag if defined($debugFlag); if($self->{debug}) { print "The following is set for the DBConsole : \n"; print "OC4JHome : $self->{oc4jHome} \n"; print "EMHome : $self->{emHome} \n"; print "DBConsole URL : $self->{url} \n"; print "ORMI Port : $self->{rmiPort} \n"; } $self->{initialized} = 1; return 1; } # # status # Checks the PID liveness test first and then uses the appropriate handler # to check the login Page of the console # sub status { my($self) = @_; if($self->{initialized}) { my $rc; $rc = 0xffff & system("$EMDROOT/bin/emdctl status url $self->{url} >$devNull 2>&1"); $rc >>= 8; if( $rc eq 3 ) #DBConsole is UP and running... { $rc = $STATUS_PROCESS_OK; unless($self->{imageCacheInitialized}) { print "## Connected to $self->{url}. Initializing image Cache. \n" if $self->{debug}; $self->initializeImageCache(); $self->{imageCacheInitialized} = 1; } } elsif( $rc eq 1 ) # DBConsole process is dead... No Connection by emdctl { $rc = $STATUS_NO_SUCH_PROCESS; } elsif( $rc eq 2 ) # DBConsole is hanging ... TIMEOUT from emdctl { $rc = $STATUS_PROCESS_HANG; } elsif( $rc eq 6 ) # emdctl internal error... print for debug purposes { print "## $EMDROOT/bin/emdctl status url $self->{url} returns internal error. \n"; $rc = $STATUS_PROCESS_UNKNOWN; } else { print "## Status URL returned unknown status. Return Code : $rc.\n" if $self->{debug}; $rc = $STATUS_PROCESS_UNKNOWN; #This should not happen... } return $rc; } } # # stop # Stops the Console # sub stop { my $self = shift; my $password = shift; if($self->{initialized}) { # changed logic for dbconsole not stopping with kill 0 my $tries = 5; while($tries gt 0) { unless( (kill 0, $self->{PID}) ) { #On windows platform [NT 4.0 and Win2k, Perl 5.6's kill is flaky... if($IS_WINDOWS ne "TRUE") { return 0; } } sleep 1; $tries = $tries - 1; } if($password eq undef) { print "--- DBConsole internal stop. No OC4J admin passwd hence hard stop. ---\n"; if ($^O eq "linux") { my $proc = ""; my @procs = `/bin/ps uxww | /bin/grep "$ORACLE_HOME/jdk/bin/java" | /bin/grep "DEMSTATE" | /bin/grep -v grep`; foreach $proc (@procs) { my @parts = split ( /\s+/ , $proc ); kill 9, $parts[1]; } } else { kill 9, $self->{PID}; } return 0; } else { my($timeInMillis) = time(); my($pwdfile); if(! -d "$FORMFACTOR_BASE/opmn/conf") { if(! -d "$FORMFACTOR_BASE/opmn") { mkdir "$FORMFACTOR_BASE/opmn"; chmod 0755, "$FORMFACTOR_BASE/opmn"; } mkdir "$FORMFACTOR_BASE/opmn/conf"; chmod 0755, "$FORMFACTOR_BASE/opmn/conf"; } open($pwdfile, "> $FORMFACTOR_FILE"); print {$pwdfile} $timeInMillis; close($pwdfile); # redirect stdout/stderr; save old handles open(OLDOUT, ">&STDOUT"); open(OLDERR, ">&STDERR"); open(STDOUT, ">> $self->{emHome}/sysman/log/stopDBConsole.out"); open(STDERR, ">> $self->{emHome}/sysman/log/stopDBConsole.out"); print "\n Stopping DBConsole on ormi port : $self->{rmiPort}. \n"; my $rc; $rc = 0xffff & system("$JAVA_HOME/bin/java -jar ". "-Doracle.home=$FORMFACTOR_BASE -DOPMN=true ". "$ORACLE_HOME/$OC4JLOC"."j2ee/home/admin.jar ". "ormi://localhost:$self->{rmiPort} admin ". "$timeInMillis -shutdown force"); print "\n\n Shutdown command to OC4J returned :$rc\n"; $rc >>= 8; print "\n\n After right shift by 8 bits return status =$rc\n"; # delete the formfactor file now ... unlink ($FORMFACTOR_FILE); # close file with redirected output, restore old handles close(STDOUT); close(STDERR); open(STDOUT, ">&OLDOUT"); open(STDERR, ">&OLDERR"); # scan output file for exceptions, then remove open(EMOUT, "stopDBConsole.out"); while() { if (index($_, "AuthenticationException") >= 0) { print("Incorrect password provided\n"); $rc = (1<<8); last; } if (index($_, "ConnectException") >= 0) { print("Incorrect EM_ADMIN_PORT specified\n"); $rc = (2<<8); last; } if (index($_, "xception") >= 0) { print("Exception during shutdown\n"); $rc = (3<<8); last; } } close(EMOUT); unlink ("$self->{emHome}/sysman/log/stopDBConsole.out") unless $self->{debug}; # do not try use kill on windows - it will only kill the parent process # and the child java process will remain if($rc gt 0 and $IS_WINDOWS ne "TRUE") { # If we have not returned yet, means all attemps to kill 0 failed print "\nall attemps to stop oc4j failed... now trying to kill 9\n"; unless( (kill 9, $self->{PID}) ) { #On windows platform [NT 4.0 and Win2k, Perl 5.6's kill is flaky... if($IS_WINDOWS ne "TRUE") { return 0; } } } print "--- Failed to shutdown DBConsole Gracefully --- \n" if( $rc gt 0 ); # Error during shutdown # 5408027 - Even after sure_stop_em reported STOPPED, java process kept running. my $psCmd_Linux = "ps auxww"; # this might need porting on other platforms my $osname = `uname -s`; chomp($osname); if($osname eq "HP-UX") { # bug: 6346876, 6391598 for HP-UX platform $psCmd_Linux = "ps -aex"; #This is for HP-UX platform } elsif($osname eq "SunOS" ) { #bug 6040898 - redundant ps usage messages while stopping dbconsole $psCmd_Linux = "/usr/bin/ps -aef"; #This is for Solaris platform } else { # 5408027 - Even after sure_stop_em reported STOPPED, java process kept running. $psCmd_Linux = "ps auxww"; # this might need porting on other platforms } if($IS_WINDOWS ne "TRUE") { my $DBCONSOLE_STOPPED = "1"; my $stopStatus = `$psCmd_Linux | grep "$ENV{'ORACLE_HOME'}/jdk/bin/java" | grep "$self->{emHome}" | wc -l`; my $trimmed_stopStatus = trim($stopStatus); my $status_tries = 5; while($status_tries gt 0) { if ($trimmed_stopStatus eq $DBCONSOLE_STOPPED) { last; #break out of while } else { # no specific reason, just trying 11 secs # on a heavily loaded system this might not be sufficient # but if I put in a => while($trimmed_stopStatus ne "1") # the risk was that this loop might hang indefinitely - if something was wrong with OC4J sleep 11; } $stopStatus = `$psCmd_Linux | grep "$ENV{'ORACLE_HOME'}/jdk/bin/java" | grep "$self->{emHome}" | wc -l`; $trimmed_stopStatus = trim($stopStatus); $status_tries = $status_tries - 1; } # if still not stopped - ports will not be freed. if ($trimmed_stopStatus ne $DBCONSOLE_STOPPED) { my $java_pid; if($osname eq "SunOS" ){ my $java_pid_lines = `$psCmd_Linux | grep "$ENV{'ORACLE_HOME'}/jdk/bin/java" | grep "$self->{emHome}" | cut -d " " -f2`; my @pid_lines = split(/\n/,$java_pid_lines); $java_pid = $pid_lines[0]; }else{ my $java_pid_lines = `$psCmd_Linux | grep "$ENV{'ORACLE_HOME'}/jdk/bin/java" | grep "$self->{emHome}"`; my @pid_lines = split(/\n/,$java_pid_lines); my @pid_line_fields = split(/\s+/,$pid_lines[0]); $java_pid = $pid_line_fields[1]; } # I dont like it much, but you've gotta go now, sorry ! if($java_pid gt 0) { kill 9, $java_pid; } } my $sts = $self->status(); if ($sts eq $STATUS_NO_SUCH_PROCESS) { $rc = 0; } } else #for NT either suggest an equivalent command or let this be { # This returns a signal of 1 - HANGUP # emwd.pl must be updated to assume this is normal # or it will start another java process system("taskkill /F /T /PID $self->{PID}"); my $stopStatus = $self->status(); if ($stopStatus eq $STATUS_NO_SUCH_PROCESS || $stopStatus eq $STATUS_PROCESS_OK ) { $rc = 0; sleep 11; } } return $rc; } } else { return 1; # We should never be here... } } sub trim() { my($string) = @_; $string =~ s/^\s+//; $string =~ s/\s+$//; return $string; } # # gatherProcessStatistics # Gathers process Statistics like Memory size etc # sub gatherProcessStatistics { my($self) = @_; if($self->{initialized}) { } } # # reInitialize # Update after a restart, the PID and the start time are changed now # and needs to be reflected. # sub reInitialize { my($self, $inPID, $inStartTime) = @_; if($self->{initialized}) { $self->{PID} = $inPID; $self->{startTime} = $inStartTime; $self->{imageCacheInitialized} = 0; return 0; } else { return 1; } } # # getThrashCount # Returns the number of restarts that has occurred # sub getThrashCount { my($self) = @_; if($self->{initialized}) { return $self->{thrashCount}; } else { return -1; } } # # setThrashCount # Reset routine for the setThrashCount # sub setThrashCount { my($self, $inThrashCount) = @_; if($self->{initialized}) { $self->{thrashCount} = $inThrashCount; return 0; } else { return 1; } } # # incThrashCount # Increments the thrashCount by 1 # sub incThrashCount { my($self) = @_; if($self->{initialized}) { $self->{thrashCount}++; return 0; } else { return 1; } } # # getPID # Returns the PID for the DBConsole # sub getPID { my($self) = @_; if($self->{initialized}) { return $self->{PID}; } else { return -1; } } # # getStartTime # Returns the start time of the DBConsole # sub getStartTime { my($self) = @_; if($self->{initialized}) { return $self->{startTime}; } else { return -1; } } # # getName # Returns the Name # sub getName { my($self) = @_; if($self->{initialized}) { return $self->{name}; } else { return undef; } } # # debug # Provides the Debug functionality # sub debug { my($self) = @_; if($self->{initialized}) { my($tPid) = $self->{PID}; print "----- Attempting to kill $self->{name} : $tPid -----\n"; if( kill 0, $tPid) { print "----- Attempting to dump threads for $tPid ----- \n"; kill 3, $tPid; sleep 10; print "----- Attempting to dump threads for $tPid ----- \n"; kill 3, $tPid; sleep 10; kill 9, $tPid; } return 0; } } # # debugCore # DebugCore is called when the monitor detects a core dump # Parameter : CoreFile # sub debugCore { my($self, $debugFile) = @_; if($self->{initialized}) { } } sub recycle { return "FALSE"; } sub okToRestart { return "TRUE"; } #initializeImageCache #This subroutine pings the DBConsole, saves the resultant #html page and then searches and gets the images. The resultant #effect is that the Server image cache is initialized. sub initializeImageCache { my $self = shift; my($htmlPage) = $self->{emHome}."/sysman/log/logonPage_dbconsole.temp"; my($rvalue); my $imageCacheUrl=$self->{url}; $imageCacheUrl =~ s/aboutApplication/logon/; $imageCacheUrl=$imageCacheUrl."/logon"; $rvalue = 0xffff & system("$EMDROOT/bin/emdctl status url $imageCacheUrl >$htmlPage 2>&1"); $rvalue >>= 8; if($rvalue eq 3) #HTML page is up... we parse it for image { open(HTMLFILE, "<$htmlPage"); while() { if(/img src/) { my(undef, $img) = split /img src="/, $_; ($img, undef) = split /" /, $img; ($img, undef) = split /">/, $img; if( ($img =~ /gif/) or ($img =~ /png/) ) { my($urlTemp, undef) = split /\/em/, $imageCacheUrl; $img = $urlTemp.$img; $rvalue = 0xffff & system("$EMDROOT/bin/emdctl status url $img >$devNull 2>&1"); $rvalue >>= 8; if($rvalue ne 3) { print "## Unable to load $img on $imageCacheUrl. Error code returned is $rvalue \n" if $self->{debug}; last; } } } } close (HTMLFILE); } unlink ($htmlPage); return $rvalue; } sub setImageCacheInitialized { ; } sub getVersion { # print " Enterprise Manager 11g DB Control Version 11.2.0.0.1\n"; DBConsoleBanner::printVersion(); } sub getOracleUniqueName { my($oh,$sid)=@_; my $oracleUnqname = &EmctlCommon::getOracleUniqueName($oh,$sid); #print "UNQNAME for $sid is $oracleUnqname\n"; if(!defined($oracleUnqname) &&($IS_WINDOWS eq "TRUE")) #for windows ignore case { #print "Unable to retrieve ORACLE_UNQNAME for $sid, trying with upper/lower case\n"; if(uc($sid) eq $sid) { $oracleUnqname = &EmctlCommon::getOracleUniqueName($oh,lc($sid)); }else { $oracleUnqname = &EmctlCommon::getOracleUniqueName($oh,uc($sid)); } } return $oracleUnqname ; } sub getOC4JHome { my ($self)=@_; my $oc4jHome = "$ORACLE_HOME/oc4j/j2ee/OC4J_DBConsole"; # For DBConsole, OC4J HOME is an offset of hostname_ my $oracleUnqname = &getOracleUniqueName($ENV{ORACLE_HOME},$ENV{ORACLE_SID}); if($EmctlCommon::HOST_SID_OFFSET_ENABLED eq "host_sid") { if(!defined($oracleUnqname)) { if(!defined($self)) { print "Environment variable ORACLE_UNQNAME not defined. Please set ORACLE_UNQNAME to database unique name. \n" ; exit(1); } } # Grok the current hostname and create the hostname_sid offset to # location. We may use a java api here to get the host and domainname. my $topDir = &EmctlCommon::getLocalHostName(); # for 10.2 dbcontrol, use node name for RAC if(substr($ENV{EMPRODVER},0,4) ne "10.1") { if (defined($ENV{CRS_HOME}) and ($ENV{CRS_HOME} ne "#CRS_HOME#")) { # if we are in RAC, use the local node name $topDir = &EmctlCommon::getLocalRACNode(); if ($topDir eq "") { print "RAC node name not found, defaulting to local host name\n" if $DEBUG_ENABLED; $topDir = &EmctlCommon::getLocalHostName(); } } } $oc4jHome=$oc4jHome."_".$topDir."_".$oracleUnqname; } # die "OC4J Configuration issue. $oc4jHome not found. \n" unless( -e "$oc4jHome" ); print "OC4J HOME ================== $oc4jHome\n" if $DEBUG_ENABLED; return $oc4jHome; } sub getEMHome { my($self)=@_; my $emHome = $EMDROOT; # EMSTATE env. var. is set from the script in the em state only bin # directory emctl [during NFS installs of state only agents]. if ( $ENV{EMSTATE} ne "" ) { $emHome = $ENV{EMSTATE}; } elsif ( $EmctlCommon::HOST_SID_OFFSET_ENABLED eq "host_sid" ) { # For DBConsole, EM HOME is an offset of hostname_ my $oracleUnqname = &getOracleUniqueName($ENV{ORACLE_HOME},$ENV{ORACLE_SID}); if(!defined($self)) { die "Environment variable ORACLE_UNQNAME not defined. Please define it. \n" unless defined ($oracleUnqname); } my $topDir = &EmctlCommon::getLocalHostName(); if (defined($ENV{CRS_HOME}) and ($ENV{CRS_HOME} ne "#CRS_HOME#")) { # if we are in RAC, use the local node name $topDir = &EmctlCommon::getLocalRACNode(); if ($topDir eq "") { print "RAC node name not found, defaulting to local host name\n" if $DEBUG_ENABLED; $topDir = &EmctlCommon::getLocalHostName(); } } $emHome = $ORACLE_HOME."/".$topDir."_".$oracleUnqname; $ENV{EMSTATE}=$emHome; # Promote EMSTATE to the env. } else { $emHome = $EMDROOT; } #EM_TMP_DIR is valid only after a call to getEMHome. $EM_TMP_DIR = "$emHome"; print "EMHOME ================== $emHome\n" if $DEBUG_ENABLED; return $emHome; } sub DESTROY { my $self = shift; } 1;