#!/bin/bash ## Usage: dbaas_restorepoint.sh , where: ## -d|--database ## -o|--operation ## -r|--restorepoint # Static parameters #------------------ typeset ORATAB='/etc/oratab' typeset ROOTDIR='/dbfs_tools/TOOLS/dbaas' typeset ENVIRONMENT='dev' # Global variables #----------------- typeset THIS_SHELL typeset DB_UNIQUE_NAME typeset OHOME typeset OVERSION typeset GHOME typeset EXEC_ID typeset SQLPLUS typeset DB_SRVCTL typeset GRID_SRVCTL typeset -i LAST_RETURN_CODE typeset -i AUX_INTEGER typeset AUX_STRING typeset DB_CONNECT_STRING typeset STEP_MESSAGE typeset STEP typeset OPERATION typeset RESTOREPOINT # Procedures #----------- usage() { [ "$*" ] && echo "$0: $*" sed -n '/^##/,/^$/s/^## \{0,1\}//p' "$0" exit 2 } 2>/dev/null get_oracle_home (){ # Get the last 3 letters of database unique name parameter AUX_STRING=$(echo ${DB_UNIQUE_NAME} | rev | cut -c 1-3 | rev) if [[ "${AUX_STRING}" != "EXA" ]] ; then echo " ERROR: Invalid database name: ${DB_UNIQUE_NAME} [FAILED]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log exit 1 fi # Get GID_HOME GHOME=$(cat ${ORATAB} | grep -v '^#' | grep "+ASM" | cut -d":" -f2 | sed 's/ //g') GRID_SRVCTL=${GHOME}/bin/srvctl ${GRID_SRVCTL} config database -v | grep ${DB_UNIQUE_NAME} | awk '{ print $1 }'> ${ROOTDIR}/workdir/${EXEC_ID}.tmp typeset -i DBCOUNT=$(cat ${ROOTDIR}/workdir/${EXEC_ID}.tmp | wc -l) if [[ ( ${DBCOUNT} > 1 ) || ( ${DBCOUNT} = 0 ) ]] ; then echo " ERROR: ${DBCOUNT} databases founded for the database name: ${DB_UNIQUE_NAME} [FAILED]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log exit 1 else OHOME=$(${GRID_SRVCTL} config database -v | grep ${DB_UNIQUE_NAME} | awk '{ print $2 }') export ORACLE_HOME=${OHOME} OVERSION=$(${GRID_SRVCTL} config database -v | grep ${DB_UNIQUE_NAME} | awk '{ print $3 }') SQLPLUS="${OHOME}/bin/sqlplus -s /nolog" DB_SRVCTL=${OHOME}/bin/srvctl echo " INFO: database name=${DB_UNIQUE_NAME}, oracle home=${OHOME}, version=${OVERSION} [OK]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log fi } ckeck_database_connectivity (){ ${SQLPLUS} < /dev/null set pages 0 set head off set feed off connect ${DB_CONNECT_STRING} as sysdba spool ${ROOTDIR}/workdir/${EXEC_ID}.tmp alter session set NLS_DATE_FORMAT='DD-MM-YYYY HH24:MI:SS'; select sysdate from dual; spool off exit EOF! # Remove the empty lines from the file sed -i '/^[[:space:]]*$/d' ${ROOTDIR}/workdir/${EXEC_ID}.tmp } get_exec_id (){ EXEC_ID="$(date +"%Y%m%d%H%M%S")$$" } count_oracle_error_in_spool (){ typeset SPOOL=${1} typeset -i ORA_COUNT=$(cat ${SPOOL} | grep ORA- |wc -l) typeset -i SP2_COUNT=$(cat ${SPOOL} | grep SP2- |wc -l) typeset -i ERR_COUNT=$(echo $((${ORA_COUNT} + ${SP2_COUNT}))) return ${ERR_COUNT} } create_restore_point (){ ${SQLPLUS} < /dev/null set pages 0 set head off set feed off connect ${DB_CONNECT_STRING} as sysdba spool ${ROOTDIR}/workdir/${EXEC_ID}.tmp create restore point R${EXEC_ID} guarantee flashback database; spool off exit EOF! # Remove the empty lines from the file sed -i '/^[[:space:]]*$/d' ${ROOTDIR}/workdir/${EXEC_ID}.tmp STEP_MESSAGE="create restorepoint R${EXEC_ID}" count_oracle_error_in_spool "${ROOTDIR}/workdir/${EXEC_ID}.tmp" LAST_RETURN_CODE=$? if [[ ( ${LAST_RETURN_CODE} != 0 ) ]] ; then echo " ERROR: ${STEP_MESSAGE} [FAILED]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log exit 1 else AUX_STRING=$(cat "${ROOTDIR}/workdir/${EXEC_ID}.tmp") echo " INFO: ${STEP_MESSAGE} [OK]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log fi } delete_restore_point (){ ${SQLPLUS} < /dev/null set pages 0 set head off set feed off connect ${DB_CONNECT_STRING} as sysdba spool ${ROOTDIR}/workdir/${EXEC_ID}.tmp drop restore point ${RESTOREPOINT}; spool off exit EOF! # Remove the empty lines from the file sed -i '/^[[:space:]]*$/d' ${ROOTDIR}/workdir/${EXEC_ID}.tmp STEP_MESSAGE="drop restorepoint R${EXEC_ID}" count_oracle_error_in_spool "${ROOTDIR}/workdir/${EXEC_ID}.tmp" LAST_RETURN_CODE=$? if [[ ( ${LAST_RETURN_CODE} != 0 ) ]] ; then echo " ERROR: ${STEP_MESSAGE} [FAILED]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log cat ${ROOTDIR}/workdir/${EXEC_ID}.tmp exit 1 else AUX_STRING=$(cat "${ROOTDIR}/workdir/${EXEC_ID}.tmp") echo " INFO: ${STEP_MESSAGE} [OK]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log fi } list_restore_points (){ ${SQLPLUS} < /dev/null connect ${DB_CONNECT_STRING} as sysdba set lines 180 pages 100 set verify off DEFINE BYTES_FORMAT="9,999,999" DEFINE BYTES_HEADING="MB" DEFINE BYTES_DIVIDER="1024/1024" spool ${ROOTDIR}/workdir/${EXEC_ID}.tmp COLUMN time HEADING "Time" FORMAT a18 COLUMN name HEADING "Name" FORMAT a30 COLUMN guarantee_flashback_database HEADING "Guar|anted" FORMAT a5 COLUMN preserved HEADING "Pre|ser|ved" FORMAT a3 COLUMN restore_point_time HEADING "Restore|Point|Time" FORMAT a18 COLUMN scn HEADING "SCN" FORMAT 999999999999999 COLUMN database_incarnation# HEADING "DB|Inc#" FORMAT 9999 COLUMN storage_size HEADING "Size(&&BYTES_HEADING)" FORMAT &&BYTES_FORMAT SELECT TO_CHAR(r.time,'DD-MON-YY HH24:MI:SS') time , r.name , r.guarantee_flashback_database , r.preserved , r.database_incarnation# , r.scn , (r.storage_size)/&&BYTES_DIVIDER storage_size , TO_CHAR(r.restore_point_time,'DD-MON-YY HH24:MI:SS') restore_point_time FROM v\$restore_point r ORDER BY r.time; spool off exit EOF! STEP_MESSAGE="create restorepoint R${EXEC_ID}" count_oracle_error_in_spool "${ROOTDIR}/workdir/${EXEC_ID}.tmp" LAST_RETURN_CODE=$? if [[ ( ${LAST_RETURN_CODE} != 0 ) ]] ; then echo " ERROR: ${STEP_MESSAGE} [FAILED]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log exit 1 else sed -i 's/no rows selected/ INFO: no restorepoint found [OK]/g' ${ROOTDIR}/workdir/${EXEC_ID}.tmp cat "${ROOTDIR}/workdir/${EXEC_ID}.tmp" fi } flashback_to_restore_point (){ STEP_MESSAGE="stop database" # Get the first node of the database typeset FIRST_DB_INSTANCE=$(${DB_SRVCTL} status database -d ${DB_UNIQUE_NAME} | head -n 1| awk -F " " '{print $2}') /dbfs_tools/TOOLS/admin/sh/db_blackout.sh ${DB_UNIQUE_NAME} ON ${DB_SRVCTL} stop database -d ${DB_UNIQUE_NAME} LAST_RETURN_CODE=$? if [[ ( ${LAST_RETURN_CODE} != 0 ) ]] ; then echo " ERROR: ${STEP_MESSAGE} [FAILED]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log exit 1 else AUX_STRING=$(cat "${ROOTDIR}/workdir/${EXEC_ID}.tmp") echo " INFO: ${STEP_MESSAGE} [OK]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log fi STEP_MESSAGE="start in mount mode ${FIRST_DB_INSTANCE} instance of ${DB_UNIQUE_NAME} database " ${DB_SRVCTL} start instance -i ${FIRST_DB_INSTANCE} -d ${DB_UNIQUE_NAME} -o "mount" LAST_RETURN_CODE=$? if [[ ( ${LAST_RETURN_CODE} != 0 ) ]] ; then echo " ERROR: ${STEP_MESSAGE} [FAILED]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log exit 1 else AUX_STRING=$(cat "${ROOTDIR}/workdir/${EXEC_ID}.tmp") echo " INFO: ${STEP_MESSAGE} [OK]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log fi sleep 30 ${SQLPLUS} < /dev/null set pages 0 set head off set feed off connect ${DB_CONNECT_STRING} as sysdba spool ${ROOTDIR}/workdir/${EXEC_ID}.tmp flashback database to restore point ${RESTOREPOINT}; alter database open resetlogs; spool off exit EOF! cat ${ROOTDIR}/workdir/${EXEC_ID}.tmp # Remove the empty lines from the file sed -i '/^[[:space:]]*$/d' ${ROOTDIR}/workdir/${EXEC_ID}.tmp STEP_MESSAGE="flashback to restorepoint ${RESTOREPOINT}" count_oracle_error_in_spool "${ROOTDIR}/workdir/${EXEC_ID}.tmp" LAST_RETURN_CODE=$? if [[ ( ${LAST_RETURN_CODE} != 0 ) ]] ; then echo " ERROR: ${STEP_MESSAGE} [FAILED]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log cat ${ROOTDIR}/workdir/${EXEC_ID}.tmp exit 1 else AUX_STRING=$(cat "${ROOTDIR}/workdir/${EXEC_ID}.tmp") echo " INFO: ${STEP_MESSAGE} [OK]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log fi STEP_MESSAGE="restart database" ${DB_SRVCTL} stop database -d ${DB_UNIQUE_NAME} ${DB_SRVCTL} start database -d ${DB_UNIQUE_NAME} LAST_RETURN_CODE=$? ${DB_SRVCTL} start service -d ${DB_UNIQUE_NAME} /dbfs_tools/TOOLS/admin/sh/db_blackout.sh ${DB_UNIQUE_NAME} OFF if [[ ( ${LAST_RETURN_CODE} != 0 ) ]] ; then echo " ERROR: ${STEP_MESSAGE} [FAILED]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log exit 1 else AUX_STRING=$(cat "${ROOTDIR}/workdir/${EXEC_ID}.tmp") echo " INFO: ${STEP_MESSAGE} [OK]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log fi } # -------- # M a i n #--------- # Get the execution id of the shell #---------------------------------- get_exec_id THIS_SHELL=$(basename "$0") # Parse the input parameters while [ "$1" != "" ]; do case $1 in -d | --database ) shift # Uppercase the database name AUX_STRING=$1 DB_UNIQUE_NAME=${AUX_STRING^^} ;; -r | --restorepoint ) shift RESTOREPOINT=$1 ;; -o | --operation ) shift OPERATION=$1 ;; -h | --help ) usage exit ;; * ) usage exit 1 esac shift done # Check for parameter consistance #-------------------------------- if [ -z "${DB_UNIQUE_NAME}" ]; then usage; exit 1; fi if ! [[ "${OPERATION}" == "list" || "${OPERATION}" == "create" || "${OPERATION}" == "delete" || "${OPERATION}" == "flashback" ]] ; then usage exit 1 fi if [[ "${OPERATION}" == "delete" || "${OPERATION}" == "flashback" ]] ; then if [ -z "${RESTOREPOINT}" ]; then usage exit 1 fi fi if [[ "${ENVIRONMENT}" == "prod" ]] ; then DB_CONNECT_STRING="sys/plusdacces@dmp01-scan/${DB_UNIQUE_NAME}" else DB_CONNECT_STRING="sys/plusdacces@dmt01-scan/${DB_UNIQUE_NAME}" fi # Get the ORACLE_HOME of the database #------------------------------------ get_oracle_home # Try to connect sys as sysdba and get the SYSDATE ckeck_database_connectivity STEP_MESSAGE="call sysdate() in ${DB_UNIQUE_NAME} to check database connectivity" count_oracle_error_in_spool "${ROOTDIR}/workdir/${EXEC_ID}.tmp" LAST_RETURN_CODE=$? if [[ ( ${LAST_RETURN_CODE} != 0 ) ]] ; then echo " ERROR: ${STEP_MESSAGE} [FAILED]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log exit 1 else AUX_STRING=$(cat "${ROOTDIR}/workdir/${EXEC_ID}.tmp") echo " INFO: ${STEP_MESSAGE}: ${AUX_STRING} [OK]" | tee -a ${ROOTDIR}/log/${THIS_SHELl}_${EXEC_ID}.log fi if [[ "${OPERATION}" == "create" ]] ; then create_restore_point exit $? fi if [[ "${OPERATION}" == "list" ]] ; then list_restore_points exit $? fi if [[ "${OPERATION}" == "flashback" ]] ; then flashback_to_restore_point exit $? fi if [[ "${OPERATION}" == "delete" ]] ; then delete_restore_point exit $? fi