# $Header: empexecuteSQL.pl 20-aug-2007.08:14:29 shnavane Exp $ # # Copyright (c) 2002, 2007, Oracle. All rights reserved. # # DESCRIPTION # ECM script to execute a SQL script # # For each database # - Execute the SQL specified # # USAGE # perl empexecuteSQL.pl # # options # -oh # -os # -sql Absolute path to the SQL script # # 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 # bguhatha 06/07/07 - bug-5971223 # bguhatha 06/22/07 - Backport bguhatha_bug-5971223 from main # rsah 03/09/06 - Fix for bug 5064490.\. # milshah 11/11/05 - change statusf to always right shift return code # shgangul 09/21/05 - Remove warnings # shgangul 07/14/05 - support extra unknown parameters, -asm # shgangul 06/08/05 - Execute the sql script directly # shgangul 04/29/05 - Spool sql errors and parse them # mningomb 04/13/05 - mningomb_dbpatch # shgangul 04/08/05 - Creation # # --- Set up necessary variables for proper running of this environment --- use strict; use FileHandle; use File::Basename(); use File::Path(); use File::Find(); use File::Spec(); use File::stat; use User::pwent; use XML::Parser; my $scriptName = File::Basename::basename($0); my $osmScriptDir = File::Basename::dirname($0); my $ecmCommon = File::Spec->catfile($osmScriptDir, 'ecmCommon.pl'); #my $db_instance = File::Spec->catfile($ENV{EMDROOT}, "sysman", "admin", "scripts", "db", "db_instance.pl"); my $db_state = File::Spec->catfile($ENV{EMDROOT}, "sysman", "admin", "scripts", "db", "dbstate.pl"); my %elements; my $seen = 0; my $root; require "$ecmCommon"; require "$db_state"; #require "$db_instance"; # ------ Initialize global variables ------------------------------------- use constant COPYRIGHT => "Copyright \251 2002, 2006, Oracle. All rights reserved."; use constant VERSION => '10.2.0.0.0'; 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_ASM => '-asm'; 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; # my @ORACLE_SIDs = (); # -os mjgdb817,msdfsjk,sdnms23 my @ORACLE_ASMs = (); # -os mjgdb817,msdfsjk,sdnms23 my $tns_admin = S_EMPTY; # Location of listener config file my $sqlscript = S_EMPTY; # Location of sql script to execute my $listener_list = S_EMPTY; # List of comma separated listeners my @db_listeners = (); # List of listeners my $shared = 0; # Whether shared or not my $rac = 0; # Whether RAC setup or not 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 $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 $INVPTRLOCFILE = 'oraInst.loc'; my $INVPTRLOCFILEPATH = S_EMPTY; my $file; my $item; my @lit; my $count; my @loc; my $script_loc; my $m_sql_script; my $m_cpu_name; my $output_string; my @tokens; my $str; my $len; # --------------------- 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 %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'; } } } # # logf() # # Display the message with timestamp # # sub logf($) { my ($msg) = @_; printf("\n%s - %s\n", scalar(localtime()), $msg); } # 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 } # parseArgs() # # Store all the arguments in hashed table # sub parseArgs { # Initialize the parameters; my $opt = S_EMPTY; my $argcount = scalar(@ARGV); logf("Arguments: @ARGV"); my $i = 0; while ($i < $argcount) { $opt = $ARGV[$i]; if ($opt eq "-oh") { $i ++; $ORACLE_HOME = $ARGV[$i]; } elsif ($opt eq "-os") { $i ++; # Parse the SID list and store it in SID array my $sidlist = $ARGV[$i]; chomp $sidlist; @ORACLE_SIDs = split(/&/, $sidlist); # Get a list of uniq SIDs my @tempsids = (); for(my $sidi = 0; $sidi < scalar(@ORACLE_SIDs); $sidi++) { my $uniq = 1; for(my $sidj = 0; $sidj < scalar(@tempsids); $sidj++) { if ($ORACLE_SIDs[$sidi] eq $tempsids[$sidj]) { $uniq = 0; last; } } if ($uniq == 1) { push(@tempsids, $ORACLE_SIDs[$sidi]); } } @ORACLE_SIDs = @tempsids; } elsif ($opt eq "-sql") { $i ++; $sqlscript = $ARGV[$i]; } elsif ($opt eq S_ASM) { $i ++; # Parse the ASM list and store it in ASM array my $asmlist = $ARGV[$i]; chomp $asmlist; @ORACLE_ASMs = split(/&/, $asmlist); # Get a list of uniq ASMs my @tempasms = (); for(my $asmi = 0; $asmi < scalar(@ORACLE_ASMs); $asmi++) { my $uniq = 1; for(my $asmj = 0; $asmj < scalar(@tempasms); $asmj++) { if ($ORACLE_ASMs[$asmi] eq $tempasms[$asmj]) { $uniq = 0; last; } } if ($uniq == 1) { push(@tempasms, $ORACLE_ASMs[$asmi]); } } @ORACLE_ASMs = @tempasms; } else { printHeader($0, $#ARGV) if (!$isHeader); #abort($action, statusf(E_INV_ARG), "Invalid argument: $opt"); printf("Following argument not supported: $opt"); } $i ++; # increment the count } if ($ORACLE_HOME eq S_EMPTY) { abort($action, statusf(E_INV_ARG), "Oracle Home not set"); } if ($sqlscript eq S_EMPTY) { abort($action, statusf(E_INV_ARG), "SQL script not specified"); } if (! -f $sqlscript && $sqlscript ne 'defaultSqlScript') { abort($action, statusf(E_INV_ARG), "SQL script does not exist"); } if (scalar(@ORACLE_SIDs) == 0) { abort($action, statusf(E_INV_ARG), "No SIDs are specified"); } } # 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; } # 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 $lsnr = S_EMPTY; my @lines = (); # Listener config file my $list_config_file = File::Spec->catfile($tns_admin, "listener.ora"); print "Geting teh listenres file=$list_config_file\n"; if (! -e $list_config_file ) { return; } # Parse the listener.ora file to get the list of listeners local *LISTDATA; open(LISTDATA, "<$list_config_file") or abort($action, statusf($?), "Could not open listerner config file \'$list_config_file\'"); my @ldata = ; close(LISTDATA); foreach my $line (@ldata) { chomp $line; print "Reading line=$line\n"; if ($line =~ m#^LISTENER(.*)=(\s*)$#) { print "Special Reading line=$line\n"; my @linewords = split(/ /, $line); if ($linewords[0] eq "") {next;} if ($linewords[0] =~ m#^\(#) {next;} if ($linewords[0] =~ m#^SID_LIST_#) {next;} push (@db_listeners, $linewords[0]); } } logf ("List of listeners detected: @db_listeners"); } # 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) = @_; $! = E_SUCCESS; logf("Stopping Oracle database listener ${name}..."); echodo("$LSNRCTL stop $name"); if ($! != E_SUCCESS) { logf("Could not shutdown database listener: $!"); } } # 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}\$")) { 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'); } } # executesqlSID(,