Showing posts with label Shell scripting. Show all posts
Showing posts with label Shell scripting. Show all posts

Monday, April 22, 2024

grep for all database names in /etc/oratab

The file /etc/oratab contains:
#
mydb01:/orainst/product/19c:Y
cdb:/orainst/product/19c:N
To extract the database names:
grep "^[^#]" /etc/oratab | awk -F':' '{print $1}'
Result:
mydb01
cdb

Thursday, April 18, 2024

Solution to script warning: here-document at line < num > delimited by end-of-file (wanted `!')

In a script, I had formatted my code as follows:
  for l in $(cat file.txt|grep 'Status'|  awk -F' ' '{print $2}'); do
    if [ $l != "SUCCESS" ]; then
       echo $l ": Errors found. Please check logfile status.log"
    else
      echo "Readjust memory for the remaining cdb instance"
        su - oracle <<!
        
        -- code here --
      !
      runAdjustMemory
    fi
  done
During execution, my script failed with
./myscript.sh: line 32: warning: here-document at line 20 delimited by end-of-file (wanted `!')
./myscript.sh: line 33: syntax error: unexpected end of file


Cause: The termination character, in this case the exclamation point ! was indented in the code.

Solution: Remove the formatting and pull the termination character all the way to the left margin of your editor:
  for l in $(cat file.txt|grep 'Status'|  awk -F' ' '{print $2}'); do
    if [ $l != "SUCCESS" ]; then
       echo $l ": Errors found. Please check logfile status.log"
    else
      echo "Readjust memory for the remaining cdb instance"
        su - oracle <<!
        
        -- code here --
!
      runAdjustMemory
    fi
  done

Wednesday, April 17, 2024

A scriptlet that will look for a file and when found, start displaying it using tail

A short script that will look for the existence of a file, and when found, start tailing it to std out:
while true; do 
 if [ -f /u01/createdb.log ]; then 
   tail -f /u01/createdb.log
 fi 
done

Friday, April 12, 2024

How to process a variable consisting of values separated by blank spaces using a for-loop construct in shell scripting

If you have a variable with to or more values, separated by space, it's very simple to loop through them and process them individually in a script.

Notice the space between the two strings in the variable $pmon:
pmon=`ps -fu oracle | grep pmon_$1 | grep -v grep | awk '{ print $8}'`

echo $pmon
ora_pmon_cdb ora_pmon_mydb01

for pname in $pmon; do
 echo $pname
done
Output:
ora_pmon_cdb
ora_pmon_mydb01
The for loop construct seem to take space as a delimter by default, so in this case it works out well.

Tuesday, April 9, 2024

How to extract the the first of two identical sentences in a log file using awk

I have a log file which repeats the same message twice.

I would like to save this message in a variable to use later in the script.

The following awk expression will pull the first of the two sentences out for you to save in a variable:
analyze_status=`cat /u01/oracle/cfgtoollogs/upgrade/auto/autoupgrade.log | grep 'ANALYZE and FIXUPS' | awk 'NR==1'`
Output of the command is:
echo $analyze_status
ANALYZE and FIXUPS modes are not run when converting a Non-CDB database to a PDB
Without the NR==1 I get the same sentence repeated twice:
ANALYZE and FIXUPS modes are not run when converting a Non-CDB database to a PDB ANALYZE and FIXUPS modes are not run when converting a Non-CDB database to a PDB

How to trim away all extra output from a result using sqlplus

The following code can be put in a shell script and executed by root.

Note the sqlplus directives which will remove all unwanted output from the resulting file /tmp/count_options.out

su - oracle <<!
echo "
set lines 10
set pages 0
set trimspool on
set verify off
set heading off
set feedback off
set echo off
spool /tmp/count_options.out
SELECT TRIM(COUNT(*)) FROM DBA_REGISTRY;
" > /tmp/count_options.sql
sqlplus -s / as sysdba @/tmp/count_options.sql
!
Output is:
 /tmp]# cat count_options.out
4
Note that without the TRIM function, the output will be
/tmp]# cat count_options.out
         4
The -s switch will execute sqlplus silently, without it, the output would be
cat count_options.out
         4
SYS@mydb01>SQL>

Friday, February 9, 2024

Script snipplet to test for subdirectories

echo "Test: are there subdirectories in /orainst/oracle/cfgtoollogs/dbca/cdb ?"
ls $(pwd)/*/ > /dev/null 2>&1
if [ $? == 0 ]; 
then 
  echo "Yes"
  export PDBDIR=`ls -d */ | awk -F '/' '{ print $1 }'`
  grep ERROR --exclude-dir=${PDBDIR} * | egrep -v $ignorelist
else 
  echo "No"
  grep ERROR * | egrep -v $ignorelist
fi
The code above is based on a finding in this post on Stack Overflow.

Thursday, February 8, 2024

Script snipplet to scan the dbca logs for errors

Here is a way to scan the logs in the directory where dbca creates its logfiles, by default under your $ORACLE_BASE/cfgtoollogs/dbca/$ORACLE_SID.

If it happens to be a multitenant database, dbca will create subdirectories for the PDB(s).

If you want to skip scanning these, exclude them from your grep command, like below:
cd /orasw/oracle/cfgtoollogs/dbca/cdb
export PDBDIR=`ls -d */ | awk -F '/' '{ print $1 }'`
export ignorelist='ORA_IGNORE_CVU_ERRORS|exectask.sh|utlrp0.log|RMANUtil\$RMANUtilErrorListener.handleError:1386|RMANUtil\$RMANUtilErrorListener.handleError:1383|RMANEngine.readSqlOutput:1046'
grep ERROR --exclude-dir=${PDBDIR} * | egrep -v $ignorelist
The errors I have excluded are based on my own observations on what's important or not during dbca usage.

Script to check for the number of control files in a database and create minimum two if only one is found

A script that checks for the number of controlfiles and creates two new ones if only one is found.
# 080224: Created 
# Check if there is only one controlfile present. If yes, create two new ones in the desired locations
#!/bin/bash
#cleanup old files
chkcntrfiles() {
rm -f /tmp/chk_cntrfile_location.sql
rm -f /tmp/chk_cntrfile_location.log
sqlfile=/tmp/chk_cntrfile_location.sql
logfile=/tmp/chk_cntrfile_location.log
echo "Check controlfile locations in database " $ORACLE_SID
cat << EoF > ${sqlfile}
   set lines 200 heading off feedback off verify off echo off termout off
   set pages 0
   set trimspool on
   col name format a70
   spool ${logfile}
select name
from v\$controlfile;
exit
EoF

cd /home/oracle/&&sqlplus -s -L / as sysdba @${sqlfile}
}
chkcntrfiles

if [ `cat ${logfile} | wc -l` -ge 2 ]; then
  echo "There are at least 2 controlfiles present"
else
  echo "There is only one controfile present."
  echo "Will now shutdown db and make another copy"
  echo "shutdown immediate" | sqlplus / as sysdba
  export org_contr_file=`cat ${logfile}`
  cp -v $org_contr_file /disk1/oradata/$ORACLE_SID/control01.ctl
  cp -v $org_contr_file /disk2/fra/$ORACLE_SID/control02.ctl
  echo "startup nomount" | sqlplus / as sysdba
  echo "alter system set control_files='/disk1/oradata/$ORACLE_SID/control01.ctl','/disk2/fra/$ORACLE_SID/control02.ctl' scope=spfile;" | sqlplus / as sysdba
  echo "startup mount force;" | sqlplus / as sysdba
  echo "Check new controlfile locations in database " $ORACLE_SID
  chkcntrfiles
  if [ ! `cat ${logfile} | wc -l` -ge 2 ]; then
   echo "We tried creating two new controlfiles but failed for some reason. Manual checkup required."
   exit 1
  fi
  echo "Alles OK!"
  echo "alter database open;" | sqlplus / as sysdba
fi

exit

Friday, December 8, 2023

Script sniplet to differentiate between cdb and pdb environment settings in a shell script

This little sniplet could be used if you find yourself in a situation where you need to differentiate between the cdb environment and the pdb environment on a server using multitenant setup.

I am setting a commonly used alias for the usage of sqlplus called "sql" depending on the ORACLE_SID being set to the cdb or the pdb.

It differs slightly since I you can only do a bequath session when connecting to the former, and not the latter:

  • When connecting to the pdb as sysdba, you need to go through the listener, and therefore supply the password.
  • When connecting to the cdb you can do a so called bequeath session and connect directly to the oracle instance through IPC.
    read -p 'Will you be administrating the cdb or the PDB? ' container
    case $container in
            CDB|cdb)
            . $ORACLE_HOME/cdb_settings.env;
            alias sql='sqlplus / as sysdba';;
            PDB1|pdb1)
            . $ORACLE_HOME/pdb1.env;
            alias sql='sqlplus sys@pdb1 as sysdba';;
            *) echo "You must select cdb or pdb1";
             exit 1;;
    esac
    
  • Friday, August 25, 2023

    How to exchange a line in a text file with a different one, when using double quotation marks in the text itself?

    The following sed command will exchange the string
    initParams=
    
    with
    initParams=undo_tablespace=UNDOTBS1,sga_target=9GB,db_block_size=32768BYTES,control_files=\"\/u02\/oradata\/{DB_UNIQUE_NAME}\/control01.ctl\"\,\"\/recovery\/fra\/{DB_UNIQUE_NAME}\/control01.ctl\"),db_recovery_file_dest=\/recovery\/fra\/{DB_UNIQUE_NAME}
    
    in the file "myresponsefile.rsp":
    sed -i "s/initParams=/initParams=undo_tablespace=UNDOTBS1,sga_target=9GB,db_block_size=32768BYTES,control_files=\"\/u02\/oradata\/{DB_UNIQUE_NAME}\/control01.ctl\"\,\"\/recovery\/fra\/{DB_UNIQUE_NAME}\/control01.ctl\"),db_recovery_file_dest=\/u04\/recovery\/{DB_UNIQUE_NAME} /" myreponse_file.rsp
    
    Note that all double quotes (") and forward (/) slashes must be masked by the backslash charcater \ to be interpreted correctly.

    Saturday, February 18, 2023

    How to prevent sed to destroy your symlinks

    Because of EBS, we have a subdirectory in our $TNS_ADMIN which has the following name
    PDB1_test1.oric.no
    
    In other words, the files listener.ora, sqlnet.ora and tnsnames.ora are symlinks pointing to this subdirectory:
    # ls -altr
    lrwxrwxrwx  1 oracle dba   34 Feb 10 13:29 sqlnet.ora -> PDB1_test1.oric.no/sqlnet.ora
    lrwxrwxrwx  1 oracle dba   36 Feb 10 13:29 tnsnames.ora -> PDB1_test1.oric.no/tnsnames.ora
    lrwxrwxrwx  1 oracle dba   36 Feb 18 12:17 listener.ora -> PDB1_test1.oric.no/listener.ora
    drwxr-xr-x  2 oracle dba 4096 Feb 18 12:18 PDB1_test1.oric.no
    drwxr-xr-x  5 oracle dba 4096 Feb 18 12:19 .
    
    If you are to exchange a string in these files, for example when switching to a new version of the Oracle software, make sure you use the directive --follow-symlinks to preserve your symlinks:
    export PRE_ORACLE_VERSION=19.17
    export NEW_ORACLE_VERSION=19.18
    cd $TNS_ADMIN
    sed --follow-symlinks -i "s/$PRE_ORACLE_VERSION/$NEW_ORACLE_VERSION/g" listener.ora
    
    If you don't, the listener.ora will be placed directly in $TNS_ADMIN, and the symlinks will be dropped.

    Tuesday, February 14, 2023

    Error fetching the value from a shell script executed by root, when doing "su - oracle"

    Problem:
    Inside a new bash shell session, executed as user "oracle", like this:
    su - oracle <<!
    
    instructions here
    
    !
    
    I was not able to save the value of a string extracted from an xml file in a session variable.
    I tried all possible variants (I thought), but was still unable to get my shell script to hold the value in a variable and use it locally within the oracle user session.

    Solution:
    Use backslash around the entire command, marked in yellow below:
    su - oracle <<!
    export CNTXT_FILE_PERL_VERSION=\`grep PERL5LIB \$CONTEXT_FILE | awk -F "site_perl/" '{print \$2}' | cut -f 1 -d":"\`
    !
    

    Credit goes to an experienced and clever colleague of mine, who shall remain nameless unless he actively wants his name listed on my blog ;-)

    Friday, January 6, 2023

    How to solve script error $'\r': command not found syntax error: unexpected end of file

    when trying to execute a script from root, like the following:
     su - oracle -c "/tmp/set_params.sh"
    
    You may see errors like the following:
    set_params.sh: line 6: $'\r': command not found
    set_params.sh: line 42: syntax error: unexpected end of file
    
    Root cause:

    You have windows-style formatting in your file

    Solution:
    dos2unix set_params.sh
    dos2unix: converting file flexpod_params.sh to Unix format...
    
    When executed again, the above errors should be gone!

    Wednesday, November 16, 2022

    How to log entire output from a shell script

    I have recently used exec to send all output from a bash script to a designated logfile.

    For example, if you have a complex script which performs multiple tasks and even execute tasks under a different user along the way, all the output will go into the global logfile indicated by the $GLOGFILE variable:
    #!/bin/bash
    export SCRIPT_NAME=`basename $0`
    export TS=`date +\%m.\%d.\%y\_%H_%M_%S`
    export GLOGFILE=/u01/mylogfile_${TS}.log
    touch ${GLOGFILE}
    chmod 666 ${GLOGFILE}
    exec 1> ${GLOGFILE} 2>&1
    echo "Starting job at " `date`
    
    your shell instructions here
    
    echo "Ending job at " `date`
    exit
    


    Good sources:

  • Linuxfordevices.com
  • Geeksforgeeks.org
  • Tuesday, August 23, 2022

    How to extract hostname withouth FQDN in a shell variable

    Taken from https://stackoverflow.com/questions/36151206/hostname-variable-in-shell-script-not-fqdn and really useful:
    export HOST=${HOSTNAME%%.*}
    

    Thursday, July 7, 2022

    How to check for existence of multiple files in a shell script

    # check for installation files existence
    if  [ ! -f /tmp/file1 -a -f /tmp/file2 -a -f /tmp/file3 ]
    then
    echo "Some of the files file1, file2 or file3 are missing from /tmp "
    exit 1
    fi
    

    Thursday, October 15, 2020

    How to select a specific line number using awk

    The file clonetext.txt contains:
      Clone Volume: true
                          Clone Parent server Name: myserver1-cluster49
                            SnapClone Parent Volume: myvolume_mirror1
                            

    You would like to get the name of the volume, which is the 4th word on the 3rd line of the file. When grepping for the keyword "Clone" all lines are returned:
     cat clonetext.txt | grep Clone
      Clone Volume: true
                          Clone Parent server Name: myserver1-cluster49
                            SnapClone Parent Volume: myvolume_mirror1
    
    Grepping for the 4th column helps, but you still get two rows, not just the single one you're interested in:
    oracle@oric-db01:[mydb01]# cat clonetext.txt | grep Clone | awk -F' ' '{print $4}'
    
    Name:
    myvolume_mirror1
    
    Adding the NR flag to your command solves the problem:
    cat clonetext.txt | grep Clone | awk -F' ' 'NR==3 {print $4}'
    myvolume_mirror1
    

    Monday, June 4, 2018

    one-liner for debugging script parameter output

    To view the output of your script parameters, put this line in the beginning of your script:

    printf "Parameters passed are : $*\n"
    

    Tuesday, May 29, 2018

    Shell script snipplet for resetting a password

    This little code snipplet to use a Linux/Unix escape character to send a line shift into a string of mulitple commands:

     #!/bin/bash
    . /home/oracle/.bash_profile
    userid=$1
    password=$2
    userexist="WHENEVER SQLERROR EXIT;"
    echo -e "alter session set container=PDB01;\n$userexist\nalter user $userid identified by $password account unlock;" | sqlplus -L -s / as sysdba