# $Header: ecmPatchDatabase_PA.pl 02-sep-2007.22:45:26 shnavane Exp $ # # Copyright (c) 2002, 2007, Oracle. All rights reserved. # # DESCRIPTION # ECM script to patch Oracle RDBMS server with Interim|Patchset patches # # USAGE # perl ecmPatchDatabase.pl [] # # command # checkTarget | expandPatch | applyPatch | showResults # options # -c count # -cf # -d path # -f patchfile # -h # -i patchid # -oh ORACLE_HOME # -os ORACLE_SID # -p patchtype # -s size # -t targettype # -x index # -v # -sharedMove # -stage_location # # NOTES # # # MODIFIED (MM/DD/YY) # shnavane 09/02/07 - Backport shnavane_bug-6024894 from main # vsriram 07/25/07 - Bug 5501067 - Handle the return values. # shnavane 05/18/07 - Fix bug #6024894 # shgangul 12/05/05 - Creation # # --- Set up necessary variables for proper running of this environment --- use strict; use English; use Cwd(); use Cwd; use File::Basename; use File::Find; use File::Path; use File::Spec(); use File::Spec::Functions qw (:ALL); use File::Copy(); use File::Copy; use FileHandle; use File::stat; use User::pwent; my $scriptName = File::Basename::basename($0); my $osmScriptDir = File::Basename::dirname($0); my $ecmCommon = File::Spec->catfile($osmScriptDir, 'ecmCommon.pl'); require "$ecmCommon"; # ------ Initialize global variables ------------------------------------- use constant COPYRIGHT => "Copyright \251 2002, 2004, Oracle. All rights reserved."; use constant VERSION => '10.1.0.2'; use constant PTYPE_PATCH => 'patch'; use constant PTYPE_PATCHSET => 'patchset'; use constant TTYPE_HOST => 'host'; use constant TTYPE_DB => 'oracle_database'; use constant TTYPE_EMD => 'oracle_emd'; use constant TTYPE_IAS => 'oracle_ias'; use constant DEPOTROOT => 'EMStagedPatches'; use constant S_DELAY => '-delay'; use constant S_FORCE => '-force'; use constant S_HELP => '-help'; use constant S_JRE => '-jre'; use constant S_JDK => '-jdk'; use constant S_LOCAL => '-local'; use constant S_MINIMIZEDOWNTIME => '-minimize_downtime'; use constant S_NOBUGSUPERSET => '-no_bug_superset'; use constant S_NOINVENTORY => '-no_inventory'; use constant S_OH => '-oh'; use constant S_PATCHID => '-patchid'; use constant S_RETRY => '-retry'; use constant S_SILENT => '-silent'; use constant S_VERSION => '-version'; use constant S_VERBOSE => '-verbose'; use constant S_INVPTRLOC => '-invPtrLoc'; use constant S_EMPTY => ''; use constant S_SPACE => ' '; use constant S_QUOTE => '"'; use constant S_APOSTROPHE => "'"; use constant KB => 1024; use constant B_TRUE => 1; use constant B_FALSE => 0; use constant E_SUCCESS => 0; use constant E_FAIL => 1 * (1 << 8); use constant E_NO_ENV => 2 * (1 << 8); use constant E_NO_OPATCHPL => 3 * (1 << 8); use constant E_NO_INVENTORY => 4 * (1 << 8); use constant E_NO_COMMAND => 5 * (1 << 8); use constant E_INV_COMMAND => 6 * (1 << 8); use constant E_INV_ARG => 7 * (1 << 8); use constant E_TOO_MANY => 8 * (1 << 8); use constant E_MISSING_ARG => 9 * (1 << 8); use constant E_NOT_ENOUGH_SPACE => 10 * (1 << 8); my $action = S_EMPTY; # ARGV[0] my $ORACLE_HOME = S_EMPTY; # -oh /private/OraHome1 my $ORACLE_SID = S_EMPTY; # -os mjgdb817 my $depot_path = S_EMPTY; # -d EMStagedPatches my $patch_type = S_EMPTY; # -p (patch|patchset) my $target_type = S_EMPTY; # -t (oracle_database|oracle_emd|oracle_ias) my $shutdown_type = '15'; # -st 1=instance,2=listener,4=agent,8=startup my $shutdown_sids = S_EMPTY; # -ss mjgdb817 my $shutdown_lsnrs = S_EMPTY; # -sl LISTENER my $patch_id = S_EMPTY; # -i 1390304 my $patch_size = '0'; # -s 5237 my $patch_file = S_EMPTY; # -f p1390304.zip my $patch_index = '1'; # -x 1..n my $patch_count = '1'; # -c n my $patch_lock = 'PATCH.lck'; my $dbsnmp_lock = 'DBSNMP.lck'; my $lsnr_lock = 'LSNR.lck'; my $db_lock = 'DB.lck'; my $db_name = S_EMPTY; my @db_instances = (); my @db_listeners = (); my $OS = $^O; # OS type (solaris|linux) my $PERL = $^X; # Perl executable my $PERL5LIB = S_EMPTY; my $EMDROOT = S_EMPTY; my $JAVA_HOME = S_EMPTY; my $OUILOC = S_EMPTY; my $isRAC = B_FALSE; # true if RAC patch my $db_shutdown = B_FALSE; # true if database shutdown required my $lsnr_shutdown = B_FALSE; # true if listener shutdown required my $dbsnmp_shutdown = B_FALSE; # true if Oracle agent shutdown required my $isProduct = B_FALSE; # true if RTM release my $isDebug = B_FALSE; # true if debugging my $isHelp = B_FALSE; # true if help request my $isLogging = B_FALSE; # true if logging output my $isHeader = B_FALSE; # true if header printed my $local_opt = S_EMPTY; # if -local specified my $inv_loc = S_EMPTY; # invPtrLoc option for apply my $isShared = 0; # if it is a shared home my $Shared = S_EMPTY; # sharedMove string my $isStaged = 0; # Whether the patch is staged my $stage_location = S_EMPTY; # Location of the patch stage my $StagedLoc = S_EMPTY; # Staged patch location if specified my $INVPTRLOCFILE = 'oraInst.loc'; my $INVPTRLOCFILEPATH = S_EMPTY; # --------------------- Command-line arguments -------------------------- use constant CTYPE_HELP => 'help'; use constant CTYPE_APPLY => 'applyPatch'; use constant CTYPE_CHECK => 'checkTarget'; use constant CTYPE_EXPAND => 'expandPatch'; use constant CTYPE_SHOW => 'showResults'; use constant CTYPE_SHUTDOWN => 'shutdown'; use constant CTYPE_STARTUP => 'startup'; my $CT = '-c'; # -c count my $CF = '-cf'; # -cf my $DP = '-d'; # -d directory my $PF = '-f'; # -f patchfile my $DB = '-g'; # -g debug my $HP = '-h'; # -h my $ID = '-i'; # -i patchid my $OH = '-oh'; # -oh ORACLE_HOME my $SID = '-os'; # -os ORACLE_SID my $PT = '-p'; # -p patchtype my $QT = '-q'; # -q my $SI = '-s'; # -s size my $SL = '-sl'; # -sl shutownlisteners my $SS = '-ss'; # -ss shutdownsids my $ST = '-st'; # -st shutdownttype my $TT = '-t'; # -t targettype my $PI = '-x'; # -x index my $VE = '-v'; # -v my $SHOME = '-sharedMove'; # -sharedMove, an unary operator my $STAGELOC = '-stage_location'; # Location of the patch stage my %OPTV = (); my %UNARYS = (); my %DEFS = (); my %ARGS = (); my %CMDS = (); # --------------------- OSD platform-specific --------------------------- my $DF = '/usr/bin/df'; my $dfOpt = '-k'; my $ECHO = '/usr/bin/echo'; # obsolete my $EGREP = '/usr/bin/egrep'; # obsolete my $EMUNZIP = 'emunzip'; my $EMZIP = 'emzip'; my $LS = '/usr/bin/ls'; my $AWK = '/usr/bin/awk'; # obsolete my $NULL_DEVICE = '/dev/null'; my $PS = '/usr/bin/ps'; # obsolete my $LSNRCTL = 'lsnrctl'; # obsolete my $SHELL = '/bin/sh'; my $SQLPLUS = 'sqlplus'; # obsolete my $SRVCTL = 'srvctl'; # obsolete my $TAR = '/usr/bin/tar'; my $tarOpt = 'xvf'; my $UNZIP = '/usr/bin/unzip'; my $unzipOpt = '-o'; my $ZIP = '/usr/bin/zip'; my $zipOpt = S_EMPTY; my $oratab = '/var/opt/oracle/oratab'; # obsolete my $BAT_SUFFIX = S_EMPTY; my $EXE_SUFFIX = S_EMPTY; my $CLASSPATHSEP = ':'; my $PATHSEP = ':'; my $FILESEP = '/'; my $DEF_PATH = '/bin:/sbin:/usr/bin:/usr/sbin:/etc:/usr/etc:/usr/ccs/bin:/usr/ucb'; my $DEF_LD_LIBRARY_PATH = '/usr/lib'; my $DEF_JAVA_HOME = '/usr/local/packages/jdk1.3.1'; # --------------------- Subroutines ------------------------------------- # setupOSD() # # Setup OSD commands # sub setupOSD { if (onWindows()) { $ECHO = 'echo'; $LS = 'dir'; $NULL_DEVICE = 'NUL'; $SHELL = 'cmd.exe /c'; $TAR = 'tar.exe'; $UNZIP = 'unzip.exe'; $ZIP = 'zip.exe'; $BAT_SUFFIX = '.bat'; $EXE_SUFFIX = '.exe'; $CLASSPATHSEP = ';'; $PATHSEP = ';'; $FILESEP = '\\'; $DEF_PATH = $ENV{'PATH'}; $DEF_LD_LIBRARY_PATH = $ENV{'PATH'}; $DEF_JAVA_HOME = $ENV{'JAVA_HOME'}; $ENV{'DIRCMD'} = ''; $ENV{'COPYCMD'} = ''; } else { if (!equalsIgnoreCase('solaris', $OS) && !equalsIgnoreCase('linux', $OS)) { $dfOpt = '-Pk'; } if (!equalsIgnoreCase('solaris', $OS)) { $oratab = '/etc/oratab'; } if (equalsIgnoreCase('hpux', $OS)) { $DF = '/usr/bin/bdf'; $dfOpt = ''; } if (equalsIgnoreCase('linux', $OS)) { $DF = '/bin/df'; $ECHO = '/bin/echo'; $EGREP = '/bin/egrep'; $LS = '/bin/ls'; $AWK = '/bin/awk'; $PS = '/bin/ps'; $TAR = '/bin/tar'; } elsif (equalsIgnoreCase('darwin', $OS)) { $DF = '/bin/df'; $ECHO = '/bin/echo'; $LS = '/bin/ls'; $PS = '/bin/ps'; } } } # isRunning() # # Return true if process is running # sub isRunning($) { my ($proc_match) = @_; return (system("$PS -e -o args | $EGREP -s \'$proc_match\'") == E_SUCCESS); } # initOptions() # # Setup known options for parsing # sub initOptions { $CMDS{lc(CTYPE_HELP)} = '1'; $CMDS{lc(CTYPE_APPLY)} = '1'; $CMDS{lc(CTYPE_CHECK)} = '1'; $CMDS{lc(CTYPE_EXPAND)} = '1'; $CMDS{lc(CTYPE_SHOW)} = '1'; #$CMDS{lc(CTYPE_SHUTDOWN)} = '1'; #$CMDS{lc(CTYPE_STARTUP)} = '1'; $OPTV{$CT} = 'count'; $DEFS{$CT} = '1'; # -c $OPTV{$DP} = 'directory'; $DEFS{$DP} = DEPOTROOT; # -d $OPTV{$PF} = 'patchfile'; # -f $OPTV{$DB} = 'debug'; $DEFS{$DB} = '0'; # -g $OPTV{$HP} = 'help'; $UNARYS{$HP} = '1'; # -h $OPTV{$ID} = 'patchid'; # -i $OPTV{$OH} = 'ORACLE_HOME'; # -oh $OPTV{$SID} = 'ORACLE_SID'; $DEFS{$SID} = 'none'; # -os $OPTV{$PT} = 'patchtype'; $DEFS{$PT} = PTYPE_PATCH; # -p $OPTV{$SI} = 'size'; $DEFS{$SI} = '0'; # -s $OPTV{$SL} = 'listeners'; $DEFS{$SL} = ' '; # -sl $OPTV{$SS} = 'ids'; $DEFS{$SS} = ' '; # -ss $OPTV{$ST} = 'shutdowntype'; $DEFS{$ST} = '15'; # -st $OPTV{$TT} = 'targettype'; $DEFS{$TT} = TTYPE_DB; # -t $OPTV{$PI} = 'index'; $DEFS{$PI} = '1'; # -x $OPTV{$VE} = 'version'; $UNARYS{$VE} = '1'; # -v $OPTV{$CF} = 'checkfree'; $UNARYS{$CF} = '1'; # -cf $OPTV{$QT} = 'quiet'; $UNARYS{$QT} = '1'; # -q $OPTV{$SHOME} = 'sharedMove'; # -sharedMove $UNARYS{$SHOME} = '1'; # -sharedMove $DEFS{$SHOME} = '0'; # default is not-shared $OPTV{$STAGELOC} = 'stageLoc'; # -stage_location $DEFS{$STAGELOC} = ' '; # default nothing } # parseArgs() # # Store all the arguments in hashed table # sub parseArgs { initOptions(); my $opt = S_EMPTY; my $argcount = scalar(@ARGV); $action = $ARGV[0]; # checkTarget|expandPatch|applyPatch|showResults if (isEmpty($action) || isEqual($VE, $action) || isEqual($HP, $action)) { $ARGS{$HP} = '1'; $ARGS{$VE} = '1' if ((defined $action) && isEqual($VE, $action)); $action = CTYPE_HELP; } if (!defined $CMDS{lc($action)}) { printHeader($0, $#ARGV) if (!$isHeader); abort($action, statusf(E_INV_COMMAND), "Invalid command: $action"); } for (my $i = 1 ; $i < $argcount ; $i++) { $opt = $ARGV[$i]; if (defined $OPTV{$opt}) { if (defined $UNARYS{$opt}) { $ARGS{$opt} = '1'; } elsif ($i < ($argcount - 1)) { $i += 1; if (!isEqual('-', substr($ARGV[$i], 0, 1))) { $ARGS{$opt} = $ARGV[$i]; } } if (!defined $ARGS{$opt}) { printHeader($0, $#ARGV) if (!$isHeader); abort($action, statusf(E_MISSING_ARG), "Missing value: $opt <$OPTV{$opt}>"); } } else { printHeader($0, $#ARGV) if (!$isHeader); #abort($action, statusf(E_INV_ARG), "Invalid argument: $opt"); print("Following argument is not supported: $opt"); } } # set up our global flags $isDebug = getArg($DB); $isProduct = B_FALSE if ($isDebug); $isHelp = (equalsIgnoreCase(CTYPE_HELP, $action) || getArg($HP, 0)); # Set the shared flag $isShared = getArg($SHOME); # Set the shared option to be passed to emdpatch.pl if ($isShared) { $Shared = $SHOME; } # Check if the patch is staged if (getArg($STAGELOC) ne ' ') { $isStaged = 1; $stage_location = getArg($STAGELOC); } if (!$isHelp) { # set invPtrLoc is not already set $ORACLE_HOME = getArg($OH); # /private/OraHome1 if (isEmpty($inv_loc)) { $INVPTRLOCFILEPATH = File::Spec->catfile($ORACLE_HOME, $INVPTRLOCFILE); if (-f $INVPTRLOCFILEPATH) { $inv_loc = S_INVPTRLOC . S_SPACE . fnQuote($INVPTRLOCFILEPATH); } } } } # getArg(,) # # Get a command argument # # Return argument # sub getArg($;$) { my ($opt, $default) = @_; my $arg = S_EMPTY; if (defined $ARGS{$opt}) { $arg = $ARGS{$opt}; } elsif (defined $default) { $arg = $default; } else { $arg = $DEFS{$opt}; } if (isEmpty($arg)) { printHeader($0, $#ARGV) if (!$isHeader); abort($action, statusf(E_MISSING_ARG), "Missing argument: $opt $OPTV{$opt}"); } return $arg; } # getFileSize() # # Return the allocated size of file # sub getFileSize($) { my ($filename) = @_; my $filesize = 0; if (-f $filename) { # my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($filename); my $st = stat($filename); $filesize = $st->size; } return $filesize; } # getFreeKB() # # Return the available KB of file system # sub getFreeKB($) { my ($loc) = @_; my @lines = (); my @bytes = (); my $freeKB = 0; if (onWindows()) { chomp(@lines = `%SYSTEMROOT%\\SYSTEM32\\CMD.EXE /C DIR /A:D /-C "$loc"`); @bytes = split (' ', $lines[@lines - 1]); if ($#bytes > 2) { $freeKB = $bytes[2]; # Win2K/XP } else { $freeKB = $bytes[0]; # WinNT } $freeKB = $freeKB / KB; } else { chomp(@lines = `$DF $dfOpt "$loc"`); @bytes = split (' ', $lines[@lines - 1]); $freeKB = $bytes[@bytes - 3]; } return $freeKB; } # isDBRunning() # # Return true if db is running # sub isDBRunning($) { my ($sid) = @_; my $old_sid = $ENV{'ORACLE_SID'}; my @lines = (); my $isRunning = B_FALSE; $ENV{'ORACLE_SID'} = $sid; chomp(@lines = `$ECHO "SET pagesize 0\\nSET tab off\\nSELECT 1 FROM sys.dual;\\n" | $SQLPLUS -S '/ as sysdba'` ); $ENV{'ORACLE_SID'} = $old_sid; if ($#lines >= 0) { $lines[0] =~ s/ //g; $isRunning = B_TRUE if (isEqual('1', $lines[0])); } return $isRunning; } # createLock(,) # # Place a marker in the depot to indicate patching state # sub createLock($$) { my ($lock_file, $lock_id) = @_; my $lock_path = File::Basename::dirname($lock_file); File::Path::mkpath($lock_path, 0, 0775) if (!-d "$lock_path"); open(OUTPUT, "> $lock_file") or abort($action, statusf($?), "Could not open lockfile $lock_file to write: $!"); printf(OUTPUT "$lock_id\n"); close(OUTPUT); } # isLocked() # # Test a marker in the depot to indicate patching state # sub isLocked($) { my ($lock_file) = @_; return (-f $lock_file); } # findLocks(,) # # Return list of lock files # sub findLocks($$) { my ($path, $mask) = @_; my @locks = (); my $pattern = File::Spec->catfile($path, $mask); if (onWindows()) { $pattern =~ s~/~\\~g; chomp(@locks = `DIR /B $pattern 2> $NULL_DEVICE`); for (my $i = 0 ; $i <= $#locks ; $i++) { $locks[$i] = File::Spec->catfile($path, $locks[$i]); } } else { chomp(@locks = `$LS -1 $pattern 2> $NULL_DEVICE`); } return @locks; } # clearLocks() # # Reset all patching state markers # sub clearLocks { my @db_locks = (); my @lsnr_locks = (); my @initoras = (); unlink($patch_lock); unlink($dbsnmp_lock); @db_locks = findLocks($depot_path, '*-DB.lck'); for (my $i = 0 ; $i <= $#db_locks ; $i++) { unlink($db_locks[$i]) if ($db_locks[$i] =~ m/\-DB\.lck$/); } @lsnr_locks = findLocks($depot_path, '*-LSNR.lck'); for (my $i = 0 ; $i <= $#lsnr_locks ; $i++) { unlink($lsnr_locks[$i]) if ($lsnr_locks[$i] =~ m/\-LSNR\.lck$/); } @initoras = findLocks($depot_path, 'init*.ora'); for (my $i = 0 ; $i <= $#initoras ; $i++) { unlink($initoras[$i]) if ($initoras[$i] =~ m/init.*\.ora$/); } } # getDB_NAME() # # Find db_name for use in shutting down RAC instances # sub getDB_NAME($) { my ($lock_file) = @_; my @lines = (); if (!isEmpty($lock_file)) { open(INPUT, "< $lock_file"); while () { chomp; $db_name = $_ if (!isEmpty($_)); } close(INPUT); return; } chomp(@lines = `$ECHO "SET pagesize 0\\nSET tab off\\nSELECT SYS_CONTEXT(\'USERENV\',\'DB_NAME\') FROM sys.dual;\\n" | $SQLPLUS -S '/ as sysdba'` ); if ($#lines >= 0) { $lines[0] =~ s/ //g; $db_name = $lines[0]; } } # getDB_LISTENERS() # # Populate db_listeners for use in shutting down all Oracle listeners # sub getDB_LISTENERS($) { my ($lock_file) = @_; my $lsnr = S_EMPTY; my @lines = (); my $count = $#db_listeners; if (!isEmpty($lock_file)) { chomp(@lines = `$LS -1 $lock_file 2> $NULL_DEVICE`); for (my $i = 0 ; $i <= $#lines ; $i++) { ($lines[$i] = File::Basename::basename($lines[$i])) =~ s/[-]LSNR.lck$//; } } else { chomp(@lines = `$PS -e -o args | $EGREP "^$ORACLE_HOME/bin/tnslsnr[ ]+" | $AWK '{print \$2}'` ); } LOOP: for (my $j = 0 ; $j <= $#lines ; $j++) { $lsnr = $lines[$j]; for (my $i = 0 ; $i <= $count ; $i++) { next LOOP if (isEqual($lsnr, $db_listeners[$i])); } $count += 1; $db_listeners[$count] = $lsnr; } } # getDB_INSTANCES() # # Populate db_instances for use in shutting down all Oracle instances # sub getDB_INSTANCES { my $sid = $ORACLE_SID; my $home = $ORACLE_HOME; my $start = 'N'; my $count = $#db_instances; $! = E_SUCCESS; open(INPUT, "< $oratab") or return; INPUT: while () { chomp; s/ //g; next INPUT if (m/^[#*]/ || isEmpty($_)); ($sid, $home, $start) = split (/:/, $_, 3); next INPUT if (isEmpty($sid)); if (isEqual($ORACLE_HOME, $home)) { for (my $i = 0 ; $i <= $count ; $i++) { next INPUT if (isEqual($sid, $db_instances[$i])); } $count += 1; $db_instances[$count] = $sid; } } close(INPUT); } # createInitOra(,) # # Create an init$ORACLE_SID.ora file for use in startup # sub createInitOra($$) { my ($sid, $initora) = @_; my $name = S_EMPTY; my $value = S_EMPTY; my @lines = (); open(OUTPUT, "> $initora") or abort($action, statusf($?), "Could not open initfile $initora to write: $!"); printf(OUTPUT "# $initora generated on %s\n", scalar(localtime())); chomp(@lines = `$ECHO "SET pagesize 0\\nSET tab off\\nSET linesize 512\\nSELECT CONCAT(CONCAT(name,'='),value) FROM V\\\$PARAMETER WHERE isdefault='FALSE' ORDER BY name;\\n" | $SQLPLUS -S '/ as sysdba'` ); for (my $i = 0 ; $i <= $#lines ; $i++) { $lines[$i] =~ s/ //g; next if (!$lines[$i] =~ m/=/); ($name, $value) = split (/=/, $lines[$i], 2); next if (!defined $value); if ($value =~ m/,/) { $value =~ s/,/","/g; $value = '"' . $value . '"'; } elsif ($value =~ m/=/) { $value = '"' . $value . '"'; } if ($name =~ m/control_files/i) { $value = '(' . $value . ')'; } else { $value = '""' if (isEmpty($value)); } printf(OUTPUT "%s=%s\n", $name, $value); } printf(OUTPUT "# end of generated file\n"); close(OUTPUT); } # shutdownLSNR() # # Shutdown database listener if running # Create shutdown marker to indicate what we did # sub shutdownLSNR($) { my ($name) = @_; my $lsnr_lock = File::Spec->catfile($depot_path, "${name}-LSNR.lck"); my $status = E_SUCCESS; if (isRunning("^$ORACLE_HOME/bin/tnslsnr[ ]+ $name")) { $! = E_SUCCESS; printf(STDOUT "Stopping Oracle database listener ${name}...\n"); $status = echodo("$LSNRCTL stop $name"); $status == E_SUCCESS or abort($action, statusf($?), "Could not shutdown database listener: $!"); createLock($lsnr_lock, $name); } } # shutdownDBSNMP() # # Shutdown Oracle Agent if running # Create shutdown marker to indicate what we did # sub shutdownDBSNMP { my $DBSNMP = 'dbsnmp'; my $AGENTCTL = "$LSNRCTL dbsnmp_stop"; my $status = E_SUCCESS; if (-f File::Spec->catfile($ORACLE_HOME, 'bin', 'agentctl')) { $DBSNMP = File::Spec->catfile($ORACLE_HOME, 'bin', $DBSNMP); $AGENTCTL = File::Spec->catfile($ORACLE_HOME, 'bin', 'agentctl') . ' stop'; } if (isRunning("^${DBSNMP}\$")) { $! = E_SUCCESS; printf(STDOUT "Stopping Oracle agent...\n"); $status = echodo("$AGENTCTL"); $status == E_SUCCESS or abort($action, statusf($?), "Could not shutdown Oracle agent: $!"); createLock($dbsnmp_lock, 'AGENT'); } } # shutdownSID() # # Shutdown database instance if running # Create shutdown marker to indicate what we did # sub shutdownSID($) { my ($sid) = @_; my $db_lock = File::Spec->catfile($depot_path, "${sid}-DB.lck"); my $initora = File::Spec->catfile($depot_path, "init${sid}.ora"); my $oldSID = $ENV{'ORACLE_SID'}; my $status = E_SUCCESS; if (isDBRunning($sid)) { if ($isRAC) { getDB_NAME(S_EMPTY); printf(STDOUT "Stopping Oracle database instances and listeners...\n"); $status = echodo("$SRVCTL stop -p $db_name"); } else { $ENV{'ORACLE_SID'} = $sid; createInitOra($sid, $initora); printf(STDOUT "Stopping Oracle database instance ${sid}...\n"); $status = echodo("$ECHO shutdown immediate | $SQLPLUS \'/ as sysdba\'"); $ENV{'ORACLE_SID'} = $oldSID; $db_name = $sid; } $status == E_SUCCESS or abort($action, statusf($status), "Could not shutdown database"); if (isDBRunning($sid)) { abort($action, statusf(E_FAIL), "Could not shutdown database"); } createLock($db_lock, $db_name); } } # setShutdownTypes() # # Set up requested shutdown/startup types # sub setShutdownTypes { my $sid = S_EMPTY; my $lsnr = S_EMPTY; my $count = 0; if (equalsIgnoreCase(CTYPE_SHUTDOWN, $action)) { $db_shutdown = B_TRUE if ($shutdown_type & 1); $lsnr_shutdown = B_TRUE if (($shutdown_type & 2) && !$isRAC); $dbsnmp_shutdown = B_TRUE if ($shutdown_type & 4); } elsif (equalsIgnoreCase(CTYPE_STARTUP, $action) && ($shutdown_type & 8)) { $db_shutdown = B_TRUE if ($shutdown_type & 1); $lsnr_shutdown = B_TRUE if (($shutdown_type & 2) && !$isRAC); $dbsnmp_shutdown = B_TRUE if ($shutdown_type & 4); } if ($db_shutdown && !isEmpty($shutdown_sids)) { $count = $#db_instances; $shutdown_sids =~ s/ //g; LOOP: foreach $sid (split (/,/, $shutdown_sids)) { next LOOP if (isEmpty($sid)); for (my $i = 0 ; $i <= $count ; $i++) { next LOOP if (isEqual($sid, $db_instances[$i])); } $count += 1; $db_instances[$count] = $sid; } } if ($lsnr_shutdown && !isEmpty($shutdown_lsnrs)) { $count = $#db_listeners; $shutdown_lsnrs =~ s/ //g; LOOP: foreach $lsnr (split (/,/, $shutdown_lsnrs)) { next LOOP if (isEmpty($lsnr)); for (my $i = 0 ; $i <= $count ; $i++) { next LOOP if (isEqual($lsnr, $db_listeners[$i])); } $count += 1; $db_listeners[$count] = $lsnr; } } } # shutdownDB() # # Shutdown database listener(s) and database instance(s) if running # Create shutdown marker(s) to indicate what we did # sub shutdownDB($) { my ($force) = @_; my $status = E_SUCCESS; clearLocks() if ($force); if ($lsnr_shutdown) { getDB_LISTENERS(S_EMPTY); for (my $i = 0 ; $i <= $#db_listeners ; $i++) { shutdownLSNR($db_listeners[$i]); } } if ($dbsnmp_shutdown) { shutdownDBSNMP(); } if ($db_shutdown) { getDB_INSTANCES(); for (my $i = 0 ; $i <= $#db_instances ; $i++) { shutdownSID($db_instances[$i]); } } } # startupLSNR() # # Start database listener if it was running # Remove shutdown marker to indicate the current state # sub startupLSNR($) { my ($name) = @_; my $lsnr_lock = File::Spec->catfile($depot_path, "${name}-LSNR.lck"); my $status = E_SUCCESS; if (isLocked($lsnr_lock)) { if (!isRunning("^$ORACLE_HOME/bin/tnslsnr[ ]+ $name")) { $! = E_SUCCESS; printf(STDOUT "Starting Oracle database listener ${name}...\n"); $status = echodo("$LSNRCTL start $name"); $status == E_SUCCESS or abort($action, statusf($?), "Could not startup database listener: $!"); } unlink($lsnr_lock); } } # startupDBSNMP() # # Start Oracle agent if it was running # Remove shutdown marker to indicate the current state # sub startupDBSNMP { my $DBSNMP = 'dbsnmp'; my $AGENTCTL = "$LSNRCTL dbsnmp_start"; my $status = E_SUCCESS; if (-f File::Spec->catfile($ORACLE_HOME, 'bin', 'agentctl')) { $DBSNMP = File::Spec->catfile($ORACLE_HOME, 'bin', $DBSNMP); $AGENTCTL = File::Spec->catfile($ORACLE_HOME, 'bin', 'agentctl') . ' start'; } if (isLocked($dbsnmp_lock)) { if (!isRunning("^${DBSNMP}\$")) { $! = E_SUCCESS; printf(STDOUT "Starting Oracle agent...\n"); $status = echodo("$AGENTCTL"); $status == E_SUCCESS or abort($action, statusf($?), "Could not startup Oracle agent: $!"); } unlink($dbsnmp_lock); } } # startupSID() # # Start database instance if it was running # Remove shutdown marker to indicate the current state # sub startupSID($) { my ($sid) = @_; my $db_lock = File::Spec->catfile($depot_path, "${sid}-DB.lck"); my $initora = File::Spec->catfile($depot_path, "init${sid}.ora"); my $oldSID = $ENV{'ORACLE_SID'}; my $status = E_SUCCESS; if (isLocked($db_lock)) { if (!isDBRunning($sid)) { if ($isRAC) { getDB_NAME($db_lock); printf(STDOUT "Starting Oracle database instances and listeners...\n"); $status = echodo("$SRVCTL start -p $db_name"); } else { $ENV{'ORACLE_SID'} = $sid; printf(STDOUT "Starting Oracle database instance ${sid}...\n"); $status = echodo( "$ECHO startup pfile=$initora | $SQLPLUS \'/ as sysdba\'"); $ENV{'ORACLE_SID'} = $oldSID; $db_name = $sid; } $status == E_SUCCESS or abort($action, statusf($status), "Could not startup database"); if (!isDBRunning($sid)) { abort($action, statusf(E_FAIL), "Could not startup database"); } } unlink($db_lock); unlink($initora); } } # startupDB() # # Start database listener and database instance(s) if they were running # Remove shutdown marker(s) to indicate the current state # sub startupDB($) { my ($force) = @_; my $status = E_SUCCESS; if ($db_shutdown) { getDB_INSTANCES(); for (my $i = 0 ; $i <= $#db_instances ; $i++) { startupSID($db_instances[$i]); } } if ($lsnr_shutdown) { getDB_LISTENERS("$depot_path/*-LSNR.lck"); for (my $i = 0 ; $i <= $#db_listeners ; $i++) { startupLSNR($db_listeners[$i]); } } if ($dbsnmp_shutdown) { startupDBSNMP(); } clearLocks() if ($force); } # cleanupPatch(,,) # # Remove anything not needed for undo of patch # sub cleanupPatch($$$) { my ($patch_path, $patch_file, $force) = @_; my $undo_patch = S_EMPTY; my $patchset_file = S_EMPTY; if ($isProduct) { unlink($patch_file); if (isEqual(PTYPE_PATCHSET, $patch_type)) { if (onWindows()) { $patchset_file = findFile($patch_path, '.*\.zip'); } else { $patchset_file = findFile($patch_path, '.*\.tar'); } unlink($patchset_file) if (!isEmpty($patchset_file)); } if (!$force) { $undo_patch = findFile($patch_path, 'undo_pre[0-9]*\.sh'); } if (isEmpty($undo_patch)) { # File::Path::rmtree($patch_path,0,1); } } } # checkTarget() # # Verify ORACLE_HOME # Create depot directory to store patch # Check to see if patch already applied (one-off patch) # Check disk space for available free space # sub checkTarget { my $patch_path = File::Spec->catfile($depot_path, $patch_id); my $oracle_file = File::Spec->catfile($ORACLE_HOME, 'bin', "oracle$EXE_SUFFIX"); my $undo_patch = S_EMPTY; my $tempfile = "_test_$$"; my $freeKB = 0; my $needKB = 0; my $isDB = isEqual(TTYPE_DB, $target_type); my $isEMD = isEqual(TTYPE_EMD, $target_type); my $isIAS = isEqual(TTYPE_IAS, $target_type); my $status = E_FAIL; $! = E_SUCCESS; chdir($ORACLE_HOME) or abort($action, statusf($?), "Could not cd to >$ORACLE_HOME<: $!"); if (!-e $patch_path) { File::Path::mkpath($patch_path, 0, 0775) > 0 or abort($action, statusf($?), "Could not mkpath >$patch_path<: $!"); } chdir($patch_path) or abort($action, statusf($?), "Could not cd to >$patch_path<: $!"); if (isEqual(PTYPE_PATCH, $patch_type) && $isDB) { # $undo_patch = findFile($patch_path, 'undo_pre[0-9]*\.sh'); # $undo_patch eq S_EMPTY # or abort($action,statusf(E_FAIL),"$patch_id already applied"); } open(OUTPUT, "> $tempfile") or abort($action, statusf($?), "Could not open file $tempfile to write: $!"); close(OUTPUT); unlink($tempfile); $freeKB = getFreeKB('.'); if (isEqual(PTYPE_PATCH, $patch_type) && $isDB) { $needKB = getFileSize($oracle_file); } $needKB = int((($needKB * 2) + (3 * $patch_size)) / KB); if (defined $ARGS{$CF}) { printf(STDOUT "%d,%d\n", $freeKB, $needKB); } else { $freeKB > $needKB or abort($action, statusf(E_NOT_ENOUGH_SPACE), "Not enough free disk space: ${freeKB}KB less than ${needKB}KB"); } } # expandPatch() # # Unpack the patch # Unpack the patchset file (if Patchset) # sub expandPatch { # my $patch_path = File::Spec->catfile($depot_path, $patch_id); my $patch_path = $depot_path; my $patch_home = $patch_path; my $patchset_file = S_EMPTY; my $unpack = S_EMPTY; my $unpackOpt = S_EMPTY; my $status = E_FAIL; $! = E_SUCCESS; chdir($patch_path) or abort($action, statusf($?), "Could not cd to >$patch_path<: $!"); printf(STDOUT "Unpacking patch file ${patch_file}...\n"); $status = echodo(fnQuote($UNZIP) . ' ' . $unzipOpt . ' ' . fnQuote($patch_file)); $status == E_SUCCESS or abort($action, statusf($?), "Could not unpack $patch_file"); if (isEqual(PTYPE_PATCHSET, $patch_type)) { if (onWindows()) { $unpack = $UNZIP; $unpackOpt = $unzipOpt; rename($patch_file, "${patch_file}.save"); $patchset_file = findFile($patch_path, '.*\.zip'); rename("${patch_file}.save", $patch_file); } else { $unpack = $TAR; $unpackOpt = $tarOpt; $patchset_file = findFile($patch_path, '.*\.tar'); } if (!isEmpty($patchset_file)) { printf(STDOUT "\nUnpacking patchset file ${patchset_file}...\n"); $status = echodo(fnQuote($unpack) . ' ' . $unpackOpt . ' ' . fnQuote($patchset_file)); $status == E_SUCCESS or abort($action, statusf($?), "Could not unpack $patchset_file"); } } } # applyPatch() # # run the patch script # sub applyPatch { # Copy the patch to official stage location if it is a staged patch if ($isStaged == 1) { my $patch_src = $stage_location; my $patch_dst = File::Spec->catfile($depot_path, $patch_id); mkpath( $patch_dst ) if not -e $patch_dst; print(STDOUT "Patch already staged. Copying the staged patch from $patch_src to $patch_dst...\n"); if (copy_dir($patch_src, $patch_dst) != E_SUCCESS) { abort($action, statusf(E_FAIL)); } } my $patch_path = File::Spec->catfile($depot_path, $patch_id); my $patch_log = File::Spec->catfile($patch_path, CTYPE_APPLY . "_${patch_id}.log"); my $patch_marker = CTYPE_APPLY . "$patch_id successful"; my $opatch = S_EMPTY; my $patch_args = S_EMPTY; my $patch_home = $patch_path; my $patchset_rsp = S_EMPTY; my $products_jar = S_EMPTY; my $failed = 'skipped'; my $isDB = isEqual(TTYPE_DB, $target_type); my $isEMD = isEqual(TTYPE_EMD, $target_type); my $isIAS = isEqual(TTYPE_IAS, $target_type); my $status = E_FAIL; # This script is always called for agent patches $isEMD = B_TRUE; $! = E_SUCCESS; chdir($patch_path) or abort($action, statusf($?), "Could not cd to >$patch_path<: $!", $patch_log); unlink($patch_lock) if ($patch_index == 1); if (!isLocked($patch_lock)) { unlink($patch_log); createLock($patch_lock, $patch_id) if ($patch_count > 1); if ($isEMD) { $opatch = findFile($patch_path, mask('emdpatch.pl')); if (isEmpty($opatch)) { $opatch = findFile($patch_path, mask('patch.sh')); } $opatch ne S_EMPTY or abort($action, statusf(E_NO_OPATCHPL), "Could not find emdpatch.pl", $patch_log); $patch_home = File::Basename::dirname($opatch); chdir($patch_home) or abort($action, statusf($?), "Could not cd to >$patch_home<: $!", $patch_log); } # elsif (isEqual(PTYPE_PATCH, $patch_type)) # { # $opatch = findFile($patch_path, mask('opatch')); # if (isEmpty($opatch)) # { # $opatch = findFile($patch_path, mask('patch.sh')); # } # # $opatch ne S_EMPTY # or abort($action, statusf(E_NO_OPATCHPL), # "Could not find opatch", $patch_log); # # $patch_home = File::Basename::dirname($opatch); # # $local_opt = S_LOCAL; # $patch_args = "apply -silent -oh \"$ORACLE_HOME\" $local_opt $inv_loc" # if (isEqual('opatch', File::Basename::basename($opatch))); # # chdir($patch_home) # or abort($action, statusf($?), # "Could not cd to >$patch_home<: $!", $patch_log); # } # elsif (isEqual(PTYPE_PATCHSET, $patch_type)) # { # $ENV{'DISPLAY'} = ':0.0' if (!defined $ENV{'DISPLAY'}); # # $patchset_rsp = findFile(File::Spec->catfile($patch_path, 'response'), # '.*\.rsp'); # $patchset_rsp ne S_EMPTY # or abort($action, statusf(E_NO_INVENTORY), # "Could not find response file", $patch_log); # # $products_jar = findFile(File::Spec->catfile($patch_path, 'stage'), # mask('products.jar')); # $products_jar ne S_EMPTY # or abort($action, statusf(E_NO_INVENTORY), # "Could not find products.jar", $patch_log); # # $local_opt = S_LOCAL; # $patch_args = # "-silent -responseFile $patchset_rsp session_FROM_LOCATION=\"$products_jar\" session_ORACLE_HOME=\"$ORACLE_HOME\" $local_opt $inv_loc"; # chdir("$ORACLE_HOME/bin") # or abort($action, statusf($?), # "Could not cd to >$ORACLE_HOME/bin<: $!", $patch_log); # # $opatch = File::Spec->catfile($ORACLE_HOME, 'bin', 'runInstaller'); # } if ((-f $opatch) && (!-x $opatch)) { chmod(0777, $opatch) or abort($action, statusf($?), "Could not chmod >$opatch<: $!", $patch_log); } $failed = 'failed'; $ENV{'PWD'} = currentDir(); if ($isEMD) { tee("Applying Patch ${patch_id}...\n", $patch_log); if (isEqual('emdpatch.pl', File::Basename::basename($opatch))) { $status = echodo(fnQuote($PERL) . ' -w ' . fnQuote($opatch) . " ${patch_id} ${Shared} >> " . fnQuote($patch_log) . " 2>&1 &"); } else { $status = echodo("$ECHO Y | $SHELL " . fnQuote($opatch) . " >> " . fnQuote($patch_log) . " 2>&1 &"); } } # elsif (isEqual(PTYPE_PATCH, $patch_type)) # { # tee("Applying Patch ${patch_id}...\n", $patch_log); # $status = # echodo( # "$ECHO Y | $SHELL " . fnQuote($opatch) . " $patch_args >> " . fnQuote($patch_log) . " 2>&1"); # } # elsif (isEqual(PTYPE_PATCHSET, $patch_type)) # { # tee("Applying Patchset ${patch_id}...\n", $patch_log); # $status = # echodo("$ECHO Y | " . fnQuote($opatch) . " $patch_args >> " . fnQuote($patch_log) . " 2>&1"); # } unlink($patch_lock) if (($patch_count > 1) && ($status == E_SUCCESS)); } if ($patch_index == $patch_count) { unlink($patch_lock); } $status == E_SUCCESS or abort($action, statusf($status), CTYPE_APPLY . " $patch_id $failed", $patch_log); if (!$isEMD) { open(LOG, ">> $patch_log") or abort($action, statusf($?), "Could not open logfile $patch_log to write: $!"); printf(LOG "\n\n$patch_marker\n\n"); close(LOG); } chdir($ORACLE_HOME) or abort($action, statusf($?), "Could not cd to >$ORACLE_HOME<: $!", $patch_log); cleanupPatch($patch_path, $patch_file, !isEmpty($patch_args)); } # showResults() # # Show the log of the actual Agent patch # sub showResults { my $patch_path = File::Spec->catfile($depot_path, $patch_id); my $patch_log = File::Spec->catfile($patch_path, CTYPE_APPLY . "_${patch_id}.log"); my $patch_marker = CTYPE_APPLY . " $patch_id successful"; my $status = E_FAIL; $! = E_SUCCESS; chdir($ORACLE_HOME) or abort($action, statusf($?), "Could not cd to >$ORACLE_HOME<: $!"); printf(STDOUT "Patch results for ${patch_id}...\n\n"); if (-f $patch_log) { open(LOG, "< $patch_log"); while () { $status = E_SUCCESS if (m/^$patch_marker$/); print(STDOUT $_); } close(LOG); printf(STDOUT "\n"); } if ($isProduct) { if ($status == E_SUCCESS) { unlink($patch_log); # File::Path::rmtree($patch_path,0,1); } } cleanAndExit($status); } # addPATH() # # Add the directory at the beginning of PATH # sub addPATH($) { my ($new_path) = @_; my $PATH = $ENV{'PATH'}; if (onWindows()) { $new_path =~ s~/~\\~g; } if (isEmpty($PATH)) { $PATH = $DEF_PATH; } else { if (onWindows()) { $new_path =~ s~\\~\\\\~g; } $PATH =~ s~(^|${PATHSEP})${new_path}(${PATHSEP}|$)~${PATHSEP}~g; $PATH =~ s~(^${PATHSEP}|${PATHSEP}$)~~g; if (onWindows()) { $new_path =~ s~\\\\~\\~g; } } $ENV{'PATH'} = "${new_path}${PATHSEP}${PATH}"; } # addLDPATH() # # Add the directory at the beginning of LD_LIBRARY_PATH # sub addLDPATH($) { my ($new_ldpath) = @_; my $LD_LIBRARY_PATH = $ENV{'LD_LIBRARY_PATH'}; if (onWindows()) { addPATH($new_ldpath); return; } if (isEmpty($LD_LIBRARY_PATH)) { $LD_LIBRARY_PATH = $DEF_LD_LIBRARY_PATH; } else { $LD_LIBRARY_PATH =~ s~(^|${PATHSEP})${new_ldpath}(${PATHSEP}|$)~${PATHSEP}~g; $LD_LIBRARY_PATH =~ s~(^${PATHSEP}|${PATHSEP}$)~~g; } $ENV{'LD_LIBRARY_PATH'} = "${new_ldpath}${PATHSEP}${LD_LIBRARY_PATH}"; } # oraenv(,) # # Set ORACLE_HOME environment # sub oraenv($$) { ($ORACLE_HOME, $ORACLE_SID) = @_; $ORACLE_HOME = trim($ORACLE_HOME); $ORACLE_SID = trim($ORACLE_SID); @db_instances = split (/,/, $ORACLE_SID); $ORACLE_SID = trim($db_instances[0]); $db_name = $ORACLE_SID; $LSNRCTL = File::Spec->catfile($ORACLE_HOME, 'bin', $LSNRCTL); $SQLPLUS = File::Spec->catfile($ORACLE_HOME, 'bin', "$SQLPLUS$EXE_SUFFIX"); $SRVCTL = File::Spec->catfile($ORACLE_HOME, 'bin', $SRVCTL); if (-f $SRVCTL) { $isRAC = B_TRUE; } my %oldenv = %ENV; if (!onWindows()) { %ENV = (); # my ($login,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwuid($>); my $pw = getpw($>); $ENV{'HOME'} = $pw->dir; $ENV{'LOGNAME'} = $pw->name; $ENV{'USER'} = $pw->name; $ENV{'LC_ALL'} = 'C'; } $ENV{'EMDROOT'} = $EMDROOT; $ENV{'PERL5LIB'} = $PERL5LIB; $ENV{'JAVA_HOME'} = $JAVA_HOME; $ENV{'PWD'} = $oldenv{'PWD'} if (defined $oldenv{'PWD'}); $ENV{'SHELL'} = $SHELL; $ENV{'TZ'} = $oldenv{'TZ'} if (defined $oldenv{'TZ'}); $ENV{'ORACLE_HOME'} = $ORACLE_HOME; $ENV{'ORACLE_SID'} = $ORACLE_SID; $ENV{'TNS_ADMIN'} = File::Spec->catfile($ORACLE_HOME, 'network', 'admin'); $ENV{'PATH'} = S_EMPTY; addPATH(File::Spec->catfile($JAVA_HOME, 'bin')); addPATH(File::Spec->catfile($ORACLE_HOME, 'bin')); $ENV{'LD_LIBRARY_PATH'} = S_EMPTY; addLDPATH(File::Spec->catfile($ORACLE_HOME, 'network', 'lib')); addLDPATH(File::Spec->catfile($ORACLE_HOME, 'lib')); #printf(STDOUT "PATH = %s\nLD_LIBRARY_PATH = %s\n",$ENV{'PATH'},$ENV{'LD_LIBRARY_PATH'}); } # emdenv() # # Set EMD environment # sub emdenv { $EMDROOT = $ENV{'EMDROOT'}; if (isEmpty($EMDROOT)) { ($EMDROOT = $osmScriptDir) =~ s/.sysman.admin.scripts.osm$//; } $JAVA_HOME = $ENV{'JAVA_HOME'}; if (isEmpty($JAVA_HOME)) { $JAVA_HOME = $DEF_JAVA_HOME; } $UNZIP = File::Spec->catfile($EMDROOT, 'bin', "unzip$EXE_SUFFIX"); if (!-x $UNZIP) { $UNZIP = File::Spec->catfile($EMDROOT, 'bin', "$EMUNZIP$BAT_SUFFIX"); } if (!-x $UNZIP) { $UNZIP = 'unzip'; } $ZIP = File::Spec->catfile($EMDROOT, 'bin', "zip$EXE_SUFFIX"); if (!-x $ZIP) { $ZIP = File::Spec->catfile($EMDROOT, 'bin', "$EMZIP$BAT_SUFFIX"); } if (!-x $ZIP) { $ZIP = 'zip'; } $OUILOC = $ENV{'OUILOC'}; $PERL5LIB = getPERL5LIB(); } # usage() # # Display a usage help page # sub usage { if (defined $ARGS{$VE}) { printf(STDOUT "\n%s Version %s\n%s\n\n", $scriptName, VERSION, COPYRIGHT); cleanAndExit(0); } my ($checkTarget, $expandPatch, $applyPatch, $showResults) = (CTYPE_CHECK, CTYPE_EXPAND, CTYPE_APPLY, CTYPE_SHOW); # Start of "here doc". print STDOUT <<_EOM_ Usage: perl $scriptName [] command $checkTarget | $expandPatch | $applyPatch | $showResults options $CT <$OPTV{$CT}>\t: Number of patches (defaults to $DEFS{$CT}) $CF \t\t: Check freespace ($checkTarget only) $DP <$OPTV{$DP}>\t: Location of patches (defaults to "$DEFS{$DP}") $PF <$OPTV{$PF}>\t: Name of patch file (defaults to "p.zip") $HP \t\t: Display this help $ID <$OPTV{$ID}>\t: Patch number (required) $OH <$OPTV{$OH}>\t: Location of Oracle Home (required) $SID <$OPTV{$SID}>\t: Name of database instance (defaults to "$DEFS{$SID}") $QT \t\t: Omit header/trailer output $PT <$OPTV{$PT}>\t: Type of patch (defaults to "$DEFS{$PT}") $SI <$OPTV{$SI}>\t\t: Size of patch file (defaults to $DEFS{$SI}) $TT <$OPTV{$TT}>\t: Type of target (defaults to "$DEFS{$TT}") $PI <$OPTV{$PI}>\t: Index of current patch (defaults to $DEFS{$PI}) $SHOME \t: The Agent home is a shared home Examples: $checkTarget -i 1390304 -oh /private/OraHome1 -s 5192 $expandPatch -i 1390304 -oh /private/OraHome1 -f p1390304.zip $applyPatch -i 1390304 -oh /private/OraHome1 -t oracle_emd $applyPatch -i 1390304 -oh /private/OraHome1 -t oracle_emd -sharedMove $showResults -i 1390304 -oh /private/OraHome1 _EOM_ ; } # statusf() # # Returns the termination status of command # sub statusf($) { my ($status) = @_; $status = E_FAIL if (!defined $status); $status = ($status >> 8) if ($status >= E_FAIL); return $status; } # cleanAndExit() # # Clean up and terminate with status # sub cleanAndExit($) { my ($status) = @_; exit statusf($status); } # Copy directory recursively to destination # result = copy_dir ( , ) # Copies the contents of Source directory to Destination directory sub copy_dir { my $src = $_[0]; # Source Directory my $dst = $_[1]; # Destination Directory my $result = E_FAIL; # Default to failure # Try to copy if both source and destination are directories if ( ( -d $src ) && ( -r $src ) && ( -d $dst ) && ( -w $dst) ) { $src =~ s/\\/\//g; $dst =~ s/\\/\//g; # Do not copy if the source and destination are the same # Return failure if ( $src eq $dst ) { return $result; } find ( sub { my $targetdir = $File::Find::dir; my $target = $targetdir; $targetdir = $dst . substr($targetdir, length($src)); mkpath( $targetdir ) if not -e $targetdir; my $file = $_; my $source = "./" . $file; my $dest = "$targetdir/$file"; if ( ($file ne $scriptName) && (-f $source) ) { # Preserve the permissions and timestamp my $stats = stat ( $source ); my @filetime = ($stats->atime(), $stats->mtime());#(stat $source)[8,9]; copy ($source, $dest); chmod $stats->mode(), $dest; # Copy permission utime $stats->atime(), $stats->mtime(), $dest; # Copy timestamp my $chown_result = 0; chown $stats->uid(), $stats->gid(), $dest or $chown_result = 1; # Copy Owner if ($chown_result) { my $s4 = $stats->uid(); my $s5 = $stats->gid(); printf(STDOUT "Could not chown file $dest to $s4, $s5...\n"); abort($action, statusf(E_FAIL)); } } }, $src ); $result = 0; # Copy success } return $result; } # --------------------- Main program ------------------------------------- setOutputAutoflush(); parseArgs(); # # Check for help requested # if ($isHelp) { usage(); cleanAndExit(0); } # # Check for call from PatchVerify.java (-q) # if (!defined $ARGS{$QT}) { printHeader($0, $#ARGV); $isHeader = B_TRUE; } # # Set the EMDROOT environment # setupOSD(); emdenv(); # # Set ORACLE_HOME environment # $ORACLE_HOME = getArg($OH); # /private/OraHome1 $ORACLE_SID = getArg($SID); # mjgdb817 oraenv($ORACLE_HOME, $ORACLE_SID); $depot_path = getArg($DP); # EMStagedPatches $depot_path = File::Spec->catfile($ORACLE_HOME, $depot_path); $patch_lock = File::Spec->catfile($depot_path, "${db_name}-$patch_lock"); $dbsnmp_lock = File::Spec->catfile($depot_path, "${db_name}-$dbsnmp_lock"); $lsnr_lock = File::Spec->catfile($depot_path, "${db_name}-$lsnr_lock"); $db_lock = File::Spec->catfile($depot_path, "${db_name}-$db_lock"); $patch_type = lc(getArg($PT)); # patch $target_type = lc(getArg($TT)); # oracle_database # # Execute the action requested # if (equalsIgnoreCase(CTYPE_CHECK, $action)) { $patch_id = getArg($ID); # 1390304 $patch_size = getArg($SI); # 5237 checkTarget(); } elsif (equalsIgnoreCase(CTYPE_EXPAND, $action)) { $patch_id = getArg($ID); # 1390304 $patch_file = getArg($PF, "p${patch_id}.zip"); # p1390304.zip expandPatch(); } elsif (equalsIgnoreCase(CTYPE_APPLY, $action)) { $patch_id = getArg($ID); # 1390304 $patch_file = getArg($PF, "p${patch_id}.zip"); # p1390304.zip $patch_index = getArg($PI); $patch_count = getArg($CT); applyPatch(); } elsif (equalsIgnoreCase(CTYPE_SHOW, $action)) { $patch_id = getArg($ID); # 1390304 showResults(); } #elsif (equalsIgnoreCase(CTYPE_SHUTDOWN, $action)) #{ # $shutdown_type = getArg($ST); # 1=instance,2=listener,4=agent # $shutdown_sids = getArg($SS); # ora817,mjg817 # $shutdown_lsnrs = getArg($SL); # LISTENER # setShutdownTypes(); # shutdownDB(1); #} #elsif (equalsIgnoreCase(CTYPE_STARTUP, $action)) #{ # $shutdown_type = getArg($ST); # 1=instance,2=listener,4=agent # $shutdown_sids = getArg($SS); # ora817,mjg817 # $shutdown_lsnrs = getArg($SL); # LISTENER # setShutdownTypes(); # startupDB(1); #} elsif (isEmpty($action)) { abort($action, statusf(E_NO_COMMAND), "Missing command:"); } else { abort($action, statusf(E_INV_COMMAND), "Invalid command: $action"); } # # Indicate a successful action; terminate with success status # if (!defined $ARGS{$QT}) { printf(STDOUT "\n\n$action $patch_id successful\n\n"); } cleanAndExit(0);