#!/usr/bin/ksh
#File-name: rman_backup.ksh
#---------------------------------------------------------------------
# Author: Larry Roberts 4/27/2004
#       : Changed to work using RMAN
# Changed: Larry Roberts 11/23/2004
#       : Changed to work with Oracle8i, Oracle9i and Oracle10G
# Changed: Murtaza Habib 08/15/2008
#       : Deleting archive logs older than retention policy
#		: Backing up the SPFILE
# E-mail: lroberts@tandbergtv.com
# W-page: http://www.tandbergtv.com
#---------------------------------------------------------------------
# Online, rman backup - will run a full or incremental backup
# of the database.
# Should be run in the following way in crontab
# DEVICE_TYPE should be DISK or TAPE
#  0 0 * * * /usr/local/n2bb/backup/scripts/rman_backup.sh DEVICE_TYPE
#---------------------------------------------------------------------
#
#---------------------------------------------------------------------
#--- Info highlighted like this is the start of a function -----------
#---------------------------------------------------------------------
#
#----------------------------------------------
# Info highlighted like this is for doco only
#----------------------------------------------
#
########## These values can be changed ##################################
export retention_days=14
export backup_home=/usr/local/n2bb/backup
#export MAIL_LIST="xxxxxx@n2bb.com"
#######################################################################
#DEVICE_TYPE to contain backup
DEVICE_TYPE=$1; export DEVICE_TYPE

# REWIND TAPE DRIVE
#    TAPE_DRIVE=/dev/rmt/0m
# NO REWIND TAPE DRIVE
#    TAPE_DRIVE_NR=/dev/rmt/0mn
#
if test -f /var/opt/oracle/oratab
then
    ORATAB=/var/opt/oracle/oratab
fi
if test -f /etc/oratab
then
    ORATAB=/etc/oratab
fi
export ORATAB
#------------------------------------------------------------------------
#----------------------- Initialization ---------------------------------
#------------------------------------------------------------------------
function Initialization
{
########################################################################
export l_date=`date '+%Y%m%d'`
export MAILX="/usr/ucb/Mail"
export BOX=`uname -n`
export BACKUP_DIR=$backup_home
if test ! -d ${BACKUP_DIR}/${ORACLE_SID}
then
        mkdir ${BACKUP_DIR}/${ORACLE_SID}
        chmod 755 ${BACKUP_DIR}/${ORACLE_SID}
fi
BACKUP_DIR=${BACKUP_DIR}/${ORACLE_SID}
l_log=${BACKUP_DIR}/${ORACLE_SID}_${l_date}.log
export RMAN_LOG=${BACKUP_DIR}/rman_${ORACLE_SID}_${l_date}.log
NEWDIR="backup_${l_date}"
    if test ! -d ${BACKUP_DIR}/${NEWDIR}
    then
        mkdir ${BACKUP_DIR}/${NEWDIR}
        chmod 755 ${BACKUP_DIR}/${NEWDIR}
    else
        rm -r ${BACKUP_DIR}/${NEWDIR}
        mkdir ${BACKUP_DIR}/${NEWDIR}
        chmod 755 ${BACKUP_DIR}/${NEWDIR}
    fi
BACKUP_DIR=${BACKUP_DIR}/${NEWDIR}
export dbidlist=${BACKUP_DIR}/dbid.lst
export redologlist=${BACKUP_DIR}/redolog.lst
export tempfilelist=${BACKUP_DIR}/tempfile.lst
export oracle_version=${BACKUP_DIR}/oraclever.lst
echo "Initializing all variables" > $l_log
echo `date '+%m/%d/%y %A %X'` "*** log BEGIN ***" >> $l_log
echo "----------------------------------------------------------------" >> $l_log
echo "Script      : "$0 >> $l_log
echo "Database    : "$ORACLE_SID >> $l_log
echo "Server      : "`uname -n` >> $l_log
echo "----------------------------------------------------------------" >> $l_log

} #END Initialization

############################################################
# things to do before exiting.  any exit from the program  #
# should be done by calling do_exit with a numeric argument#
# a non-numeric argument (or none at all) will generate an #
# error of its own, so be careful                          #
############################################################
function do_exit
{
    exit $1

} #END do_exit

#------------------------------------------------------------------------
#------------------ Verify a database is up and running -----------------
#------------------------------------------------------------------------
function verifyDatabase
{
echo "Verifying database up and running" >> $l_log
STATUS=`ps -fu oracle | grep "ora_[a-z]*_${ORACLE_SID}" `
if [ $? != 0 ]; then
        echo " DATABASE ${ORACLE_SID} WAS NOT RUNNING" >> $l_log
        db_not_up=0
else
        db_not_up=1
fi
echo "Running sqlplus to obtain Database DBID, tempfile list and redolog list" >> $l_log
sqlplus /nolog <<EOF
        connect / as sysdba
        set termout off
        set pagesize 0
        set heading off
        set feedback off

        spool ${dbidlist};
        select dbid,log_mode from v\$database;
        spool off;
        column member FORMAT A40;
        spool ${redologlist};
        select group#, member FROM v\$logfile;
        spool off;
        column file_name FORMAT A40;
        spool $tempfilelist;
        select file_name,tablespace_name from dba_temp_files;
        spool off;
        spool $oracle_version;
        select substr(banner,instr(banner,'.')-2,8) from v\$version where banner like 'Oracle%';
        spool off;
        exit;
EOF

SED="sed -e '/^SQL/d' -e '/^ /d' \$dbidlist"
eval $SED | while read DB LM
do
    export DBID=$DB
    export LOGMODE=$LM
done
SED="sed -e '/^SQL/d' -e '/^ /d' \$oracle_version"
eval $SED | while read OV
do
    export ORACLE_VER=$OV
done
if [ "${LOGMODE}" = "NOARCHIVELOG" ]
then
   db_not_up=2
fi

} # END verifyDatabase

#------------------------------------------------------------------------
#----------------------- RMAN execution ---------------------------------
#------------------------------------------------------------------------
function run_rman
{

#------------------------------------------------
#          Delete backup directories
#------------------------------------------------
echo "Removing old control files and backup directories " >> $l_log
 find ${backup_home}/${ORACLE_SID} -follow -name "backup_*" -mtime +$retention_days -exec rm -r {} \; >> $l_log
 find ${backup_home}/${ORACLE_SID} -follow -name "purge_*" -mtime +$retention_days -exec rm -r {} \; >> $l_log
 find ${backup_home}/${ORACLE_SID} -follow -name "*.log" -mtime +$retention_days -exec rm -r {} \; >> $l_log
#------------------------------------------------

echo "run crosscheck on archivelog to see if any expired" >> $l_log
rman log=${RMAN_LOG} >> $l_log <<EOF
   connect target /;
RUN{
    crosscheck archivelog all;
    delete noprompt expired archivelog all;
  }
EOF

echo "Running RMAN to backup database" >> $l_log
rman log=${RMAN_LOG} >> $l_log <<EOF
   connect target /;
RUN{
        configure retention policy to recovery window of $retention_days days;
        configure backup optimization on;
        configure controlfile autobackup off;
        configure default device type to DISK;
        configure channel device type DISK format '${BACKUP_DIR}/${ORACLE_SID}_${l_date}_%t.bus';
        configure maxsetsize to UNLIMITED;
        configure snapshot controlfile name to '${BACKUP_DIR}/control_spfile.bck';
   }
EOF
if [ "${db_not_up}" = "1" ]
then
rman log=${RMAN_LOG} >> $l_log <<EOF1
   connect target /;
RUN{
        backup incremental level 0 database;
        backup format '${BACKUP_DIR}/${ORACLE_SID}_${l_date}_%t.arc'
                filesperset=10
                archivelog all;
        backup (current controlfile format '${BACKUP_DIR}/controlfile_${l_date}.ctl');
        delete noprompt obsolete device type DISK;
        delete force noprompt archivelog until time 'sysdate - ${retention_days} ';
        backup spfile format '${BACKUP_DIR}/spfile_${ORACLE_SID}_${l_date}.ora';
  }
EOF1
else
rman log=${RMAN_LOG} >> $l_log <<EOF2
   connect target /;
RUN{
        shutdown immediate;
        startup mount;
        backup database;
        backup (current controlfile format '${BACKUP_DIR}/controlfile_${l_date}.ctl');
        alter database open;
        delete noprompt obsolete device type DISK;
   }
EOF2
fi

#------------------------------------------------
#           Send Emails to whomever
#------------------------------------------------
#if [ $? != 0 ]; then
#cat ${RMAN_LOG} | $MAILX -s "RMAN backup of ${ORACLE_SID} on ${BOX} failed" ${MAIL_LIST}
#else
#$MAILX -s "RMAN backup of ${ORACLE_SID} on ${BOX} ran OK" ${MAIL_LIST}
#fi

} #END run_rman

#------------------------------------------------------------------------
#----------- Check Tape Drive for tape mounted and rewound --------------
#------------------------------------------------------------------------
function checkTape
{
echo "Checking the Status of Tape Drive ${TAPE_DRIVE_NR}" >> $l_log
MSG_CNT=0
while
   mt -f ${TAPE_DRIVE_NR} status
   tapeStatus=${?}
   [ "${tapeStatus}" != "0" ]
   do
      if [ "${MSG_CNT}" != "0" ]
         then echo "Message: Tape is not in drive: ${TAPE_DRIVE_NR}" >> $l_log
      fi

     sleep 60

      MSG_CNT=`expr ${MSG_CNT} + 1`
      if [ "${MSG_CNT}" = "30" ]
         then echo "Message: Tape was not in drive: ${TAPE_DRIVE_NR}"  >> $l_log
              echo "Checked for 30 minutes.\n"
              echo "Terminating\n"
              do_exit 1
      fi
   done
   mt -f ${TAPE_DRIVE} rew
}  # END  checkTape

#---------------------------------------------------------------------
# Copy backup Directory to tape --------------------------------------
#---------------------------------------------------------------------
function CopytoTape
{

echo "Copying Directory $BACKUP_DIR to tape." >> $l_log
    tar -cvf ${TAPE_DRIVE_NR} ${BACKUP_DIR}

echo "Successfully Copied Directory $BACKUP_DIR to tape." >> $l_log
echo "Removing Directory $BACKUP_DIR from DISK." >> $l_log
    cd $BACKUP_DIR
    rm -r *

} #END CopytoTape

#------------------------------------------------------------------------
# print a footer into a log file
#------------------------------------------------------------------------
function Print_Footer
{
    echo "----------------------------------------------------------------" >> $l_log
    echo `date '+%m/%d/%y'` `date '+%H:%M:%S'` "*** log END ***" >>  $l_log

} #END Print_Footer

#------------------------------------------------------------------------
#----------------------- Main Search of Oratab --------------------------
#------------------------------------------------------------------------
#if [ "${HOSTTYPE}" = "sparc" ]
#then
#   if [ "${LOGNAME}" != "oracle" ]
#   then
#     echo "MUST run this as the oracle user"
#     do_exit 1
#   fi
#else
#   oracleuid=`grep oracle /etc/passwd | cut -d ":" -f 3`
#   loginuid=`id -u`
#   if [ "${loginuid}" != "${oracleuid}" ]
#   then
#      echo "MUST run this as the oracle user"
#      do_exit 1
#   fi
#fi

if [ "${DEVICE_TYPE}" = "TAPE" ]
then
checkTape
fi

cat $ORATAB | while read LINE
do
    case $LINE in
        \#*)                ;;        #comment-line in oratab
        *)
#       Proceed only if third field is 'Y'.
        if [ "`echo $LINE | awk -F: '{print $3}' -`" = "Y" ] ; then
            ORACLE_SID=`echo $LINE | awk -F: '{print $1}' -`
            if [ "$ORACLE_SID" = '*' ] ; then
                ORACLE_SID=""
            fi
#           Called programs use same database ID
            export ORACLE_SID
            ORACLE_HOME=`echo $LINE | awk -F: '{print $2}' -`
#           Called scripts use same home directory
            export ORACLE_HOME
#           Put $ORACLE_HOME/bin into PATH and export.
            PATH=$ORACLE_HOME/bin:/bin:/usr/bin:/etc ; export PATH
            LD_LIBRARY_PATH=${ORACLE_HOME}/lib ; export LD_LIBRARY_PATH
            Initialization
            verifyDatabase
            if [ "${db_not_up}" != "0" ]
            then
            run_rman
            if [ "${DEVICE_TYPE}" = "TAPE" ]
            then
                echo "done"
                CopytoTape
            fi

            Print_Footer

            fi
        fi
    esac
done

do_exit 0
#-----------------------------------------------------
# End of file

