Skip to content

Instantly share code, notes, and snippets.

@haballan
Last active March 29, 2022 09:18
Show Gist options
  • Save haballan/86a59a3b6d8d470926024710e5b330a4 to your computer and use it in GitHub Desktop.
Save haballan/86a59a3b6d8d470926024710e5b330a4 to your computer and use it in GitHub Desktop.
Script to be used on the crontab to schedule an RMAN Full Backup (Variables in the first section must be modified before using the script)
# ##############################################################################################
# Script to be used on the crontab to schedule an RMAN Full Backup
VER="[1.3]"
# ##############################################################################################
# # # #
# Author: Mahmmoud ADEL # # # # ###
# Created: 04-10-17 # # # # #
#
# Modified:
# 10-03-19 Add the option of deleting old CONTROLFILE AUTOBACKUP files.
# 16-06-20 Add Backup tag option.
# 16-06-20 Add the option of deleting the last backup taken by the same script.
# 16-06-20 Add the check of ORACLE HOME validity.
# ##############################################################################################
# ##############################################################
# VARIABLES To be Modified by the user to match the Environment:
# ##############################################################
# INSTANCE Name: [Replace ${ORACLE_SID} with your instance SID]
ORACLE_SID=${ORACLE_SID}
# ORACLE_HOME Location: [Replace ${ORACLE_HOME} with the right ORACLE_HOME path]
ORACLE_HOME=${ORACLE_HOME}
# Backup Name: [TAG] [Replace DAILYBKP with the backup name you want to tag]
BACKUPTAG=DAILYBKP
# Backup Location: [Replace /backup/rmanfull with the backup location path]
BACKUPLOC=/backup/rmanfull
# Backup LOG location:
RMANLOG=${BACKUPLOC}/rmanfull.log
# COMPRESSED BACKUP option:[Y|N] [Default Y]
COMPRESSION=Y
# Perform Maintenance based on below Backup & Archivelog Retention: [Y|N] [Default DISABLED]
MAINTENANCEFLAG=N
# Delete the last backup taken by the same script: [Y|N] [Default Y]
DELETE_LAST_BKP=Y
# Backup Retention "In Days": [Backups older than this retention will be deleted]
BKP_RETENTION=7
# Archives Deletion "In Days": [Archivelogs older than this retention will be deleted]
ARCH_RETENTION=7
# CONTROLFILE AUTOBACKUP Retention "In Days": [AUTOBACKUP of CONTROLFILE older than this retention will be deleted]
CTRL_AUTOBKP_RETENTION=7
# ##################
# GENERIC VARIABLES: [Can be left without modification]
# ##################
# MAX BACKUP Piece Size: [To be considered, it should be BIGGER than the size of the biggest datafile in the database]
MAX_BKP_PIECE_SIZE=33g
# Show the full DATE and TIME details in the backup log:
NLS_DATE_FORMAT='DD-MON-YYYY HH24:MI:SS'
export ORACLE_SID
export ORACLE_HOME
export BACKUPTAG
export BACKUPLOC
export COMPRESSION
export BKP_RETENTION
export ARCH_RETENTION
export MAX_BKP_PIECE_SIZE
export RMANLOG
export NLS_DATE_FORMAT
export MAINTENANCEFLAG
# Check if the backup location is writable:
if [ ! -w ${BACKUPLOC} ]; then
echo
echo -e "\033[32;5mERROR: THE PROVIDED BACKUP LOCATION [${BACKUPLOC}] IS NOT WRITABLE !\033[0m"
echo
echo "Please provide a valid backup location by editing the value of variable 'BACKUPLOC' inside the script."
echo
exit
fi
# Check the selected COMPRESSION option:
case ${COMPRESSION} in
Y|y|YES|Yes|yes|ON|on)
COMPRESSED_BKP="AS COMPRESSED BACKUPSET"
export COMPRESSED_BKP
;;
*)
COMPRESSED_BKP=""
export COMPRESSED_BKP
;;
esac
# Check DELETE LAST BACKUP option:
case ${DELETE_LAST_BKP} in
Y|y|YES|Yes|yes|ON|on)
HASH_DELETE_LAST_BKP=""
export HASH_DELETE_LAST_BKP
;;
*)
HASH_DELETE_LAST_BKP="#"
export HASH_DELETE_LAST_BKP
;;
esac
# Check the selected MAINTENANCE option:
case ${MAINTENANCEFLAG} in
Y|y|YES|Yes|yes|ON|on)
HASH_MAINT=""
export HASH_MAINT
;;
*)
HASH_MAINT="#"
export HASH_MAINT
;;
esac
# Check if ORACLE_SID was missed by the user:
# ##########################################
if [ -z ${ORACLE_SID} ]; then
echo "ORACLE_SID was missed, the script will set it to the only running instance if found ..."
# Count Instance Numbers:
INS_COUNT=$( ps -ef|grep pmon|grep -v grep|egrep -v ${EXL_DB}|wc -l )
# Exit if No DBs are running:
if [ $INS_COUNT -eq 0 ]
then
echo No Database is Running !
exit
fi
# If there is ONLY one DB set it as default without prompt for selection:
if [ $INS_COUNT -eq 1 ]
then
export ORACLE_SID=$( ps -ef|grep pmon|grep -v grep|egrep -v ${EXL_DB}|awk '{print $NF}'|sed -e 's/ora_pmon_//g'|grep -v sed|grep -v "s///g" )
echo "Script found only 1 running instance."
echo "Script will run against [${ORACLE_SID}] DB ..."
else
echo "Script is unable to identify which instance to run against!"
echo "Please provide a value for ORACLE_SID inside the script."
echo "Script Terminated!"
exit
fi
fi
# Check if the given ORACLE_HOME is valid:
# #######################################
if [ ! -d ${ORACLE_HOME} ]; then
echo "ORACLE HOME is not valid, the script will search for the right ORACLE HOME ..."
ORA_USER=`ps -ef|grep ${ORACLE_SID}|grep pmon|grep -v grep|egrep -v ${EXL_DB}|awk '{print $1}'|tail -1`
USR_ORA_HOME=`grep ${ORA_USER} /etc/passwd| cut -f6 -d ':'|tail -1`
# SETTING ORATAB:
if [ -f /etc/oratab ]
then
ORATAB=/etc/oratab
export ORATAB
## If OS is Solaris:
elif [ -f /var/opt/oracle/oratab ]
then
ORATAB=/var/opt/oracle/oratab
export ORATAB
fi
# ATTEMPT1: Get ORACLE_HOME using pwdx command:
PMON_PID=`pgrep -lf _pmon_${ORACLE_SID}|awk '{print $1}'`
export PMON_PID
ORACLE_HOME=`pwdx ${PMON_PID}|awk '{print $NF}'|sed -e 's/\/dbs//g'`
export ORACLE_HOME
# ATTEMPT2: If ORACLE_HOME not found get it from oratab file:
if [ ! -f ${ORACLE_HOME}/bin/sqlplus ]
then
## If OS is Linux:
if [ -f /etc/oratab ]
then
ORATAB=/etc/oratab
ORACLE_HOME=`grep -v '^\#' ${ORATAB} | grep -v '^$'| grep -i "^${ORACLE_SID}:" | perl -lpe'$_ = reverse' | cut -f3 | perl -lpe'$_ = reverse' |cut -f2 -d':'`
export ORACLE_HOME
## If OS is Solaris:
elif [ -f /var/opt/oracle/oratab ]
then
ORATAB=/var/opt/oracle/oratab
ORACLE_HOME=`grep -v '^\#' ${ORATAB} | grep -v '^$'| grep -i "^${ORACLE_SID}:" | perl -lpe'$_ = reverse' | cut -f3 | perl -lpe'$_ = reverse' |cut -f2 -d':'`
export ORACLE_HOME
fi
fi
# ATTEMPT3: If ORACLE_HOME is in /etc/oratab, use dbhome command:
if [ ! -f ${ORACLE_HOME}/bin/sqlplus ]
then
ORACLE_HOME=`dbhome "${ORACLE_SID}"`
export ORACLE_HOME
fi
# ATTEMPT4: If ORACLE_HOME is still not found, search for the environment variable: [Less accurate]
if [ ! -f ${ORACLE_HOME}/bin/sqlplus ]
then
ORACLE_HOME=`env|grep -i ORACLE_HOME|sed -e 's/ORACLE_HOME=//g'`
export ORACLE_HOME
fi
# ATTEMPT5: If ORACLE_HOME is not found in the environment search user's profile: [Less accurate]
if [ ! -f ${ORACLE_HOME}/bin/sqlplus ]
then
ORACLE_HOME=`grep -h 'ORACLE_HOME=\/' ${USR_ORA_HOME}/.bash_profile ${USR_ORA_HOME}/.*profile | perl -lpe'$_ = reverse' |cut -f1 -d'=' | perl -lpe'$_ = reverse'|tail -1`
export ORACLE_HOME
fi
# ATTEMPT6: If ORACLE_HOME is still not found, search for orapipe: [Least accurate]
if [ ! -f ${ORACLE_HOME}/bin/sqlplus ]
then
if [ -x /usr/bin/locate ]
then
ORACLE_HOME=`locate -i orapipe|head -1|sed -e 's/\/bin\/orapipe//g'`
export ORACLE_HOME
fi
fi
fi
# Append the date to the backup log for each script execution:
echo "----------------------------" >> ${RMANLOG}
date >> ${RMANLOG}
echo "----------------------------" >> ${RMANLOG}
# ###################
# RMAN SCRIPT Section:
# ###################
${ORACLE_HOME}/bin/rman target / msglog=${RMANLOG} <<EOF
# Configuration Section:
# ---------------------
${HASH_MAINT}CONFIGURE BACKUP OPTIMIZATION ON;
${HASH_MAINT}CONFIGURE CONTROLFILE AUTOBACKUP ON;
${HASH_MAINT}CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '${BACKUPLOC}/%F';
${HASH_MAINT}CONFIGURE SNAPSHOT CONTROLFILE NAME TO '${ORACLE_HOME}/dbs/snapcf_${ORACLE_SID}.f';
## Avoid Deleting archivelogs NOT yet applied on the standby: [When FORCE is not used]
#CONFIGURE ARCHIVELOG DELETION POLICY TO APPLIED ON ALL STANDBY;
# Maintenance Section:
# -------------------
## Crosscheck backups/copied to check for expired backups which are physically not available on the media:
${HASH_MAINT}crosscheck backup completed before 'sysdate-${BKP_RETENTION}' device type disk;
${HASH_MAINT}crosscheck copy completed before 'sysdate-${BKP_RETENTION}' device type disk;
## Report & Delete Obsolete backups which don't meet the RETENTION POLICY:
${HASH_MAINT}REPORT OBSOLETE RECOVERY WINDOW OF ${BKP_RETENTION} DAYS device type disk;
${HASH_MAINT}DELETE NOPROMPT OBSOLETE RECOVERY WINDOW OF ${BKP_RETENTION} DAYS device type disk;
## Delete All EXPIRED backups/copies which are not physically available:
${HASH_MAINT}DELETE NOPROMPT EXPIRED BACKUP COMPLETED BEFORE 'sysdate-${BKP_RETENTION}' device type disk;
${HASH_MAINT}DELETE NOPROMPT EXPIRED COPY COMPLETED BEFORE 'sysdate-${BKP_RETENTION}' device type disk;
## Crosscheck Archivelogs to avoid the backup failure:
${HASH_MAINT}CHANGE ARCHIVELOG ALL CROSSCHECK;
${HASH_MAINT}DELETE NOPROMPT EXPIRED ARCHIVELOG ALL;
## Delete Archivelogs older than ARCH_RETENTION days:
${HASH_MAINT}DELETE NOPROMPT archivelog all completed before 'sysdate -${ARCH_RETENTION}';
## Delete AUTOBACKUP Controlfile older than CTRL_AUTOBKP_RETENTION days:
DELETE NOPROMPT BACKUP of controlfile completed before 'sysdate-${CTRL_AUTOBKP_RETENTION}';
## Delete the LAST Full backup taken by the same script:
${HASH_DELETE_LAST_BKP}DELETE NOPROMPT BACKUP TAG='${BACKUPTAG}';
# Full Backup Script starts here: [Compressed+Controlfile+Archives]
# ------------------------------
run{
allocate channel F1 type disk;
allocate channel F2 type disk;
allocate channel F3 type disk;
allocate channel F4 type disk;
sql 'alter system archive log current';
BACKUP ${COMPRESSED_BKP}
#MAXSETSIZE ${MAX_BKP_PIECE_SIZE}
NOT BACKED UP SINCE TIME 'SYSDATE-2/24'
#INCREMENTAL LEVEL=0
FORMAT '${BACKUPLOC}/%d_%t_%s_%p.bkp'
FILESPERSET 100
TAG='${BACKUPTAG}'
DATABASE include current controlfile PLUS ARCHIVELOG NOT BACKED UP SINCE TIME 'SYSDATE-2/24';
## Backup the controlfile separately:
BACKUP ${COMPRESSED_BKP} CURRENT CONTROLFILE FORMAT '${BACKUPLOC}/CONTROLFILE_%d_%I_%t_%s_%p.bkp' TAG='CONTROLFILE_BKP' REUSE ;
## Trace backup of Controlfile & SPFILE:
SQL "ALTER DATABASE BACKUP CONTROLFILE TO TRACE AS ''${BACKUPLOC}/controlfile.trc'' REUSE";
SQL "CREATE PFILE=''${BACKUPLOC}/init${ORACLE_SID}.ora'' FROM SPFILE";
}
EOF
# #############
# END OF SCRIPT
# #############
# REPORT BUGS to: mahmmoudadel@hotmail.com
# DOWNLOAD THE LATEST VERSION OF DATABASE ADMINISTRATION BUNDLE FROM:
# http://dba-tips.blogspot.com/2014/02/oracle-database-administration-scripts.html
# DISCLAIMER: THIS SCRIPT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY. IT IS PROVIDED "AS IS".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment