Skip to main content

Template shell scripts for Linux and Solaris RMAN hosts

Druva provides template shell scripts for Linux and Solaris RMAN hosts that you can use to back up databases. The scripts are:

  • phoenix_get_mount_details.sh: This script provides the details of the backup mount and the Phoenix Backup Store. Use this script to get the location of the backup mount so that you can map it to the RMAN host.

  • oracle_rman_data_backup.sh: This script runs RMAN commands that perform incremental merge backup of databases, archive log backups, and store the backup on the backup mount. You can modify the script to modify RMAN parameters.

  • oracle_rman_archivelog_backup.sh: This script runs RMAN commands that back up archived log files on Linux RMAN hosts, create an Oracle RMAN backup for archived logs, and store it on the backup mount. You can modify the script to modify RMAN parameters.

  • oracle_rman_data_backup_solaris: This script runs RMAN commands that back up data files on Solaris RMAN hosts, create an Oracle RMAN backup, and store it on the backup mount. You can modify the script to modify RMAN parameters.

  • oracle_rman_archivelog_backup_solaris: This script runs RMAN commands that back up archived log files on Solaris RMAN hosts, create an Oracle RMAN backup for archived logs, and store it on the backup mount. You can modify the script to modify RMAN parameters.

Druva provides the following scripts to enhance the backup performance and also provides extended recovery windows locally on PBS:

  • oracle_rman_data_full_merge_weekly_backup.sh: This script recovers and applies incremental backup set copies to the full image base copies of the backup. You can schedule this script to run on crontab based on the recovery window. For example, if the recovery window is set to 7 days, this script can be scheduled to run every week and the incremental backup pieces will be applied to the full image copies once every week.

  • oracle_rman_data_incremental_daily_backup.sh: This script backs up only incremental backups without performing recovery operations. You can schedule this script to run daily and ensure a recovery window from local PBS up to 7 days or based on the rman retention set for recovery window.


    📝 Note
    The recovery window resets once the full merge script is run and hence you cannot recover your database from PBS to older backups that were backed up in the previous week.


The following sections provide the contents of the shell scripts. You can edit these scripts to suit your requirements.

phoenix_get_mount_details.sh

Click here to view script

#!/bin/bash

if [ "$#" -ne 2 ]; then
echo ""
echo "Usage: $0 <backup_store_IP> <backup_mount_name>"
echo ""
echo " <backup_store_IP> : IP address of the Phoenix Backup Store"
echo " <backup_mount_name> : Name of the backup mount configured in Phoenix, e.g. mount1"

exit 1
fi

BACKUP_STORE_IP=$1
BACKUP_MOUNT=$2

res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res
exit 1
fi

# Sample output format
# {"error_code":4295622665,"error_msg":"Backup mount does not exist on Export Service.","result":{"mount_name":"mount4","mount_path":""}}
ERROR_CODE=$(echo $res|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$res
echo "Error getting mount details... exiting"
exit 1
fi

REMOTE_MOUNTPOINT=$BACKUP_STORE_IP:$(echo $res|awk -F "mount_path" '{print $2}'|cut -d '"' -f3)
echo ""
echo "Remote mountpath is $REMOTE_MOUNTPOINT"
MOUNT_OPTS=$(echo $res|awk -F "mount_params" '{print $2}'|cut -d '{' -f2|cut -d '}' -f1)
echo "Mount options : rw,user,$MOUNT_OPTS"

oracle_rman_data_backup.sh

Use this script for Enterprise Workloads agent version 7.0.2-1003652 or later.

#!/bin/bash

if [ "$#" -ne 2 ]; then
echo ""
echo "Usage: $0 <backup_store_IP> <backup_mount_name>"
echo ""
echo " <backup_store_IP> : IP address of the Phoenix Backup Store"
echo " <backup_mount_name> : Name of the backup mount configured in Phoenix, e.g. mount1"

exit 1
fi

BACKUP_STORE_IP=$1
BACKUP_MOUNT=$2

PARALLELISM=1

if [[ -z "${ORACLE_HOME}" ]];
then
echo "Environment variable ORACLE_HOME not set... exiting"
exit 1
fi

if [[ -z "${ORACLE_SID}" ]];
then
echo "Environment variable ORACLE_SID not set... exiting"
exit 1
fi
SID=${ORACLE_SID}

# --- ENHANCED FAILURE NOTIFICATION TRAP ---
export RMAN_SCRIPT_STAGE="Initialization"
export RMAN_SCRIPT_ERROR_MSG="Unexpected termination during initialization"
export RMAN_SCRIPT_RESOLUTION_MSG="Check export service logs or contact Druva Support"

rman_script_failure_notify() {
local ec="${1:-1}"

# Only fire the alert if the exit code is strictly greater than 0
[ "$ec" -eq 0 ] && return 0

local stage="${RMAN_SCRIPT_STAGE}"
local sid="${ORACLE_SID}"
local err_msg="${RMAN_SCRIPT_ERROR_MSG}"
local resolution_msg="${RMAN_SCRIPT_RESOLUTION_MSG}"

# Escape internal double quotes and newlines to prevent JSON payload corruption
local stage_escaped="${stage//\"/\\\"}"
local sid_escaped="${sid//\"/\\\"}"
local err_msg_escaped="${err_msg//\"/\\\"}"
err_msg_escaped="${err_msg_escaped//$'\n'/ }" # Replace newlines with spaces
local resolution_msg_escaped="${resolution_msg//\"/\\\"}"
resolution_msg_escaped="${resolution_msg_escaped//$'\n'/ }" # Replace newlines with spaces

# Construct JSON payload natively using printf
local body
body=$(printf '{"exit_code":%d,"failure_stage":"%s","db_sid":"%s","error_msg":"%s","resolution_msg":"%s"}' \
"$ec" "$stage_escaped" "$sid_escaped" "$err_msg_escaped" "$resolution_msg_escaped")

# Network-hardened API call with a 30-second maximum timeout ceiling
curl -sS --max-time 30 -X POST "http://${BACKUP_STORE_IP}:9090/druva-phoenix/v1/mounts/${BACKUP_MOUNT}/rmanbackup/failure-alert" \
-H "Content-Type: application/json" \
-d "$body" >/dev/null 2>&1 || true
}

# Register trap to catch any exit and pass the true exit code
trap 'rman_script_failure_notify $?' EXIT
# ------------------------------------------

export RMAN_SCRIPT_STAGE="Validate Backup Request"
echo "Validating backup request"

validate_resp=$(curl -X GET http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/1.2/backup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Backup validation request failed with response: $validate_resp"
echo "Backup validation request failed with response: $validate_resp... exiting"
exit 1
fi

VALIDATE_ERROR_CODE=$(echo "$validate_resp" | awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$VALIDATE_ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Backup validation failed (error_code: ${VALIDATE_ERROR_CODE})"
echo "Backup validation request failed... exiting"
exit 1
fi

# Sample output format
# {"error_code":0,"error_msg":"","result":{"is_reached_max_snapshots":false,"mount_name":"m2"}}
IS_REACHED_MAX_SNAPSHOTS=$(echo "$validate_resp" | awk -F "is_reached_max_snapshots" '{print $2}' | cut -d ',' -f1 | cut -d ':' -f2)
if [ "$IS_REACHED_MAX_SNAPSHOTS" = "false" ];
then
echo "Validation for phoenix backup succeeded"
else
export RMAN_SCRIPT_ERROR_MSG="Backup mount reached max snapshot limit"
export RMAN_SCRIPT_RESOLUTION_MSG="Increase max snapshots limit or wait for pending uploads"
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Validation for phoenix backup failed... exiting"
exit 1
fi

export RMAN_SCRIPT_STAGE="Start Phoenix Backup"
echo "Notifying Phoenix to start backup - Phoenix Backup Store=$BACKUP_STORE_IP mount name=$BACKUP_MOUNT"

res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to start Phoenix Backup session"
echo "Request to start Phoenix Backup failed with response: $res... exiting"
exit 1
fi

# Sample output format
# {"error_code":4295622665,"error_msg":"Backup mount does not exist on Export Service.","result":{"mount_name":"mount4","mount_path":""}}
ERROR_CODE=$(echo "$res" | awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Phoenix Backup init failed (error_code: ${ERROR_CODE})"
echo "Request to start Phoenix Backup failed with response: $res... exiting"
exit 1
fi

export RMAN_SCRIPT_STAGE="Mount Phoenix Backup Store"
REMOTE_MOUNTPOINT=$BACKUP_STORE_IP:$(echo "$res" | awk -F "mount_path" '{print $2}' | cut -d '"' -f3)
RMANBACKUP_MOUNTPOINT=$(grep "^$REMOTE_MOUNTPOINT" /etc/fstab | sed 's/\s\+/ /g' | cut -d ' ' -f2)

if [ -z "$RMANBACKUP_MOUNTPOINT" ];
then
export RMAN_SCRIPT_ERROR_MSG="Mount entry missing from /etc/fstab"
export RMAN_SCRIPT_RESOLUTION_MSG="Add mount entry to /etc/fstab"
echo "Entry for Phoenix Backup Store mount not found in /etc/fstab... exiting"
exit 1
fi

ACTUAL_MOUNTPOINT=$(mount | grep "^$REMOTE_MOUNTPOINT" | sed 's/\s\+/ /g' | cut -d " " -f3 2> /dev/null)
if [ -z "$ACTUAL_MOUNTPOINT" ];
then
mount "$RMANBACKUP_MOUNTPOINT" 2> /dev/null
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to mount backup store"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify mount entry in /etc/fstab"
echo "Unable to mount $RMANBACKUP_MOUNTPOINT... exiting"
exit 1
fi
else
RMANBACKUP_MOUNTPOINT=$ACTUAL_MOUNTPOINT
fi

export PATH=$ORACLE_HOME/bin:$PATH
full_backup () {

export RMAN_SCRIPT_STAGE="Create Full Backup Directory"
echo "Creating Dir $RMANBACKUP_MOUNTPOINT/$SID'/full'"

if [ ! -e "$RMANBACKUP_MOUNTPOINT/$SID/full" ]
then
mkdir -p "$RMANBACKUP_MOUNTPOINT/$SID/full"
if [ $? -eq 0 ];
then
echo "Created directory for full backup $RMANBACKUP_MOUNTPOINT/$SID/full"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create full backup directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "Failed to create full backup directory... exiting"
exit 1
fi
elif [ ! -d "$RMANBACKUP_MOUNTPOINT/${SID}/full" ];
then
export RMAN_SCRIPT_ERROR_MSG="Path conflict: full path is a file, expected directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Remove conflicting file and retry"
echo "$RMANBACKUP_MOUNTPOINT/$SID is not a directory... exiting"
exit 1
fi

export RMAN_SCRIPT_STAGE="Create Archivelogs Backup Directory"
if [ ! -e "$RMANBACKUP_MOUNTPOINT/${SID}/archivelogs" ]
then
mkdir -p "$RMANBACKUP_MOUNTPOINT/${SID}/archivelogs"
if [ $? -eq 0 ];
then
echo "Created directory for archivelogs backup $RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create archivelogs directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "Failed to create archivelogs directory... exiting"
exit 1
fi
elif [ ! -d "$RMANBACKUP_MOUNTPOINT/${SID}/archivelogs" ];
then
export RMAN_SCRIPT_ERROR_MSG="Path conflict: archivelogs path is a file, expected directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Remove conflicting file and retry"
echo "$RMANBACKUP_MOUNTPOINT/$SID is not a directory... exiting"
exit 1
fi

LOG_FILE_DIR=$RMANBACKUP_MOUNTPOINT/'_workspace/RMAN_Logs'
echo "Creating Log File Dir: =$RMANBACKUP_MOUNTPOINT'/_workspace/RMAN_Logs'"

if [ ! -e "$LOG_FILE_DIR" ]
then
mkdir -p "$LOG_FILE_DIR"
if [ $? -eq 0 ];
then
echo "Created log directory for oracle backup $LOG_FILE_DIR"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create RMAN log directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "Failed to create RMAN log directory... exiting"
exit 1
fi
fi

echo -n > "$LOG_FILE_DIR/rman_full_backup.log"
RMANBACKUP_MOUNTPOINT_FULL=$RMANBACKUP_MOUNTPOINT/$SID

touch "$RMANBACKUP_MOUNTPOINT/_workspace/" 2>/dev/null
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to write to workspace folder"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "$RMANBACKUP_MOUNTPOINT directory is not writable.. exiting"
exit 1
fi

#Checking if any .lock file is present and deleting the same if the PID is NOT running.
echo "Checking for backup lock file"
export RMAN_SCRIPT_STAGE="Check for Backup Lock File"
export BKP_CONTINUE=0
is_lock_file_present=$(find "${RMANBACKUP_MOUNTPOINT}" -type f -name ".RMAN_BACKUP_lock_*" | wc -l)
if [[ ${is_lock_file_present} -ne 0 ]]
then
for _lock_file in $(find "${RMANBACKUP_MOUNTPOINT}" -type f -name ".RMAN_BACKUP_lock_*" | xargs)
do
_pid=$(echo "${_lock_file}" | cut -d"_" -f4)
is_pid_proc_running=$(ps -ef | grep "${_pid}" | grep -v grep | wc -l)
if [[ ${is_pid_proc_running} -ne 0 ]]
then
echo "[INFO] backup Lock File: ${_lock_file} is present and PID is active"
export BKP_CONTINUE=1
else
echo "[INFO] backup Lock File: ${_lock_file} is present and PID is NOT active"
echo "Deleting ${_lock_file}"
rm "${_lock_file}"
if [ -e "${_lock_file}" ]
then
echo "ERROR deleting file ${_lock_file}"
export BKP_CONTINUE=1
fi
fi
done
if [[ ${BKP_CONTINUE} -eq 1 ]]
then
export RMAN_SCRIPT_ERROR_MSG="Skipping backup: active RMAN backup or lock file present"
export RMAN_SCRIPT_RESOLUTION_MSG="Wait for active backup to finish or remove stale lock file"
echo "Skipping backup: active RMAN backup or lock file present... exiting"
exit 1
fi
fi

export file_stamp=$(date | sed -e 's/ /_/g')
PID=$$
LOCK_FILE="${RMANBACKUP_MOUNTPOINT}/.RMAN_BACKUP_lock_${PID}_${file_stamp}"
echo -n > "${LOCK_FILE}"
if [ -e "${LOCK_FILE}" ]
then
echo "[INFO] Lock file created: ${LOCK_FILE}"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create backup lock file"
export RMAN_SCRIPT_RESOLUTION_MSG="Check backup mount disk space and permissions"
echo "Error creating lock file: ${LOCK_FILE}"
echo "[ERROR] Backup will now stop"
exit 1
fi

echo "Starting with RMAN backup"

export RMAN_SCRIPT_STAGE="Request RMAN Snapshot for Full Backup"
res_rmanbackup=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/${SID}/full/rmanbackup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to request RMAN snapshot"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify backup mount configuration"
echo "Request to start Phoenix Backup failed with response: $res_rmanbackup... exiting"
rm "${LOCK_FILE}"
exit 1
fi

echo "Response RMAN Backup: ${res_rmanbackup}"

SNAPSHOT_NAME=$(echo "$res_rmanbackup" | awk -F "snap_name" '{print $2}' | cut -d '"' -f3)
if [ -z "$SNAPSHOT_NAME" ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to get snapshot name"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify backup mount configuration"
echo "Failed to get Snapshot name... exiting with response: $res_rmanbackup"
rm "${LOCK_FILE}"
exit 1
fi

echo "Snapshot to be created ${SNAPSHOT_NAME}"

export RMAN_SCRIPT_STAGE="Run RMAN Backup"
RMAN_LOGFILE=$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'
echo -n > "$RMAN_LOGFILE"
echo "RMAN Logfile: ${RMAN_LOGFILE}"

rman log="$RMAN_LOGFILE" 2> /dev/null << EOF
connect target /
set echo on;
configure backup optimization on;
configure controlfile autobackup on;
configure device type disk parallelism $PARALLELISM BACKUP TYPE TO COPY;
configure datafile backup copies for device type disk to 1;
configure archivelog backup copies for device type disk to 1;
configure channel device type disk format '${RMANBACKUP_MOUNTPOINT_FULL}/full/datafile_%U.bkp';
configure controlfile autobackup format for device type disk to '${RMANBACKUP_MOUNTPOINT_FULL}/full/full_controlfile_%d_%F.bkp';
run
{
sql 'alter system archive log current';
backup incremental level 1 for recover of copy with tag 'phoenix_oracle_backup' database;
recover copy of database with tag 'phoenix_oracle_backup';
sql 'alter system archive log current';
backup as backupset format '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/%d_%h_%e_%s_%t.arc' archivelog all not backed up;

#Force is to ignore I/O errors
delete noprompt obsolete device type disk;
delete force NOPROMPT expired copy;
delete force NOPROMPT expired backup;
crosscheck backup;
crosscheck copy;
}
configure backup optimization clear;
configure controlfile autobackup clear;
exit
EOF

RMAN_EXIT_STATUS=$?
if [ $RMAN_EXIT_STATUS -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="RMAN backup failed (exit_code: ${RMAN_EXIT_STATUS})"
export RMAN_SCRIPT_RESOLUTION_MSG="Check RMAN logs and fix the issue"
echo ""
echo "RMAN backup failed (exit_code: ${RMAN_EXIT_STATUS})... exiting"
rm "${LOCK_FILE}"
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

echo "RMAN log location: $LOG_FILE_DIR/rman_full_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log"

export RMAN_SCRIPT_STAGE="Upload RMAN Logs"
echo "Notifying Phoenix to upload RMAN Logs"

rman_uploadlog_res=$(curl -X POST -H "Content-Type: multipart/form-data" -F "file=@$LOG_FILE_DIR/rman_full_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log" -F mountpoint=$RMANBACKUP_MOUNTPOINT -F platform=linux http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/uploadlog 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to send RMAN Logs failed..."
echo "Response from Phoenix Backup Store: "$rman_uploadlog_res
fi

rm "${LOCK_FILE}"
if [ -e "${LOCK_FILE}" ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=$(date | sed -e 's/ /_/g')
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi

export RMAN_SCRIPT_STAGE="End Backup"
echo "Notifying Phoenix to end backup"
final_res=$(curl -X PUT http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)

if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to end Phoenix Backup with response: $final_res"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify export service is reachable and check its logs"
echo "Request to end Phoenix Backup failed with response: $final_res... exiting"
rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

ERROR_CODE=$(echo "$final_res" | awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to end Phoenix Backup (error_code: ${ERROR_CODE})"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify export service is reachable and check its logs"
echo "Response from Phoenix Backup Store: "$final_res
echo "Request to end Phoenix Backup failed... exiting"
exit 1
fi
echo "$final_res"

echo "Exiting with successful status"
}

# Main
full_backup

Use this script for Enterprise Workloads agent version 7.0.2-985623 or earlier.

#!/bin/bash

if [ "$#" -ne 2 ]; then
echo ""
echo "Usage: $0 <backup_store_IP> <backup_mount_name>"
echo ""
echo " <backup_store_IP> : IP address of the Phoenix Backup Store"
echo " <backup_mount_name> : Name of the backup mount configured in Phoenix, e.g. mount1"

exit 1
fi

BACKUP_STORE_IP=$1
BACKUP_MOUNT=$2

PARALLELISM=1

if [[ -z "${ORACLE_HOME}" ]];
then
echo "Environment variable ORACLE_HOME not set... exiting"
exit 1
fi

if [[ -z "${ORACLE_SID}" ]];
then
echo "Environment variable ORACLE_SID not set... exiting"
exit 1
fi
SID=${ORACLE_SID}

echo "Validating backup request"
validate_resp=$(curl -X GET http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/1.2/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to validate phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$validate_resp
exit 1
fi

VALIDATE_ERROR_CODE=$(echo $validate_resp|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $VALIDATE_ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Request to validate Phoenix backup failed... exiting"
exit 1
fi

# Sample output format
# {"error_code":0,"error_msg":"","result":{"is_reached_max_snapshots":false,"mount_name":"m2"}}
IS_REACHED_MAX_SNAPSHOTS=$(echo $validate_resp|awk -F "is_reached_max_snapshots" '{print $2}'|cut -d ',' -f1 |cut -d ':' -f2)
if [ $IS_REACHED_MAX_SNAPSHOTS == "false" ];
then
echo "Validation for phoenix backup succeeded"
else
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Validation for phoenix backup failed... exiting"
exit 1
fi

echo "Notifying Phoenix to start backup - Phoenix Backup Store=$BACKUP_STORE_IP mount name=$BACKUP_MOUNT"

#res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/$SID/full/backup 2> /dev/null)
res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res
exit 1
fi

# Sample output format
# {"error_code":4295622665,"error_msg":"Backup mount does not exist on Export Service.","result":{"mount_name":"mount4","mount_path":""}}
ERROR_CODE=$(echo $res|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)

if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$res
echo "Request to start Phoenix backup failed... exiting"
exit 1
fi


REMOTE_MOUNTPOINT=$BACKUP_STORE_IP:$(echo $res|awk -F "mount_path" '{print $2}'|cut -d '"' -f3)
RMANBACKUP_MOUNTPOINT=$(grep "^$REMOTE_MOUNTPOINT" /etc/fstab| sed 's/\s\+/ /g' |cut -d ' ' -f2)

if [ -z "$RMANBACKUP_MOUNTPOINT" ];
then
echo "Entry for Phoenix Backup Store mount not found in /etc/fstab... exiting"
exit 1
fi

ACTUAL_MOUNTPOINT=$(mount|grep "^$REMOTE_MOUNTPOINT"|sed 's/\s\+/ /g' |cut -d " " -f3 2> /dev/null)
if [ -z "$ACTUAL_MOUNTPOINT" ];
then
mount $RMANBACKUP_MOUNTPOINT 2> /dev/null
if [ $? -ne 0 ];
then
echo "Unable to mount $RMANBACKUP_MOUNTPOINT... exiting"
exit 1
fi
else
RMANBACKUP_MOUNTPOINT=$ACTUAL_MOUNTPOINT
fi

export PATH=$ORACLE_HOME/bin:$PATH
full_backup () {

echo "Creating Dir $RMANBACKUP_MOUNTPOINT/$SID'/full'"

if [ ! -e $RMANBACKUP_MOUNTPOINT/$SID'/full' ]
then
mkdir -p $RMANBACKUP_MOUNTPOINT/$SID'/full'
if [ $? -eq 0 ];
then
echo "Created directory for full backup $RMANBACKUP_MOUNTPOINT/$SID/full"
else
echo "Oracle user does not have permission for $RMANBACKUP_MOUNTPOINT directory... exiting"
exit 1
fi
elif [ ! -d $RMANBACKUP_MOUNTPOINT/${SID}'/full' ];
then
echo "$RMANBACKUP_MOUNTPOINT is not a directory... exiting"
exit 1
fi

#Creating Archivelog Directory

if [ ! -e $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs' ]
then
mkdir -p $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs'
if [ $? -eq 0 ];
then
echo "Created directory for archivelogs backup $RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
else
echo "Oracle user does not have permission for $RMANBACKUP_MOUNTPOINT directory... exiting"
exit 1
fi

elif [ ! -d $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs' ];
then
echo "$RMANBACKUP_MOUNTPOINT is not a directory... exiting"
exit 1
fi

LOG_FILE_DIR=$RMANBACKUP_MOUNTPOINT/'_workspace/RMAN_Logs'
echo "Creating Log File Dir: =$RMANBACKUP_MOUNTPOINT'/_workspace/RMAN_Logs'"

if [ ! -e $LOG_FILE_DIR ]
then
mkdir -p $LOG_FILE_DIR
if [ $? -eq 0 ];
then
echo "Created log directory for oracle backup $LOG_FILE_DIR"
else
echo "Oracle user does not have permission for $LOG_FILE_DIR directory... exiting"
exit 1
fi
fi

RMANBACKUP_MOUNTPOINT_FULL=$RMANBACKUP_MOUNTPOINT/$SID

touch $RMANBACKUP_MOUNTPOINT/_workspace/
if [ $? -ne 0 ];
then
echo "$RMANBACKUP_MOUNTPOINT directory is not writable.. exiting"
exit 1
fi

#Checking if any .lock file is present and deleting the same if the PID is NOT running.
export BKP_CONTINUE=0
is_lock_file_present=`find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_BACKUP_lock_*"|wc -l `
if [[ ${is_lock_file_present} -ne 0 ]]
then
for _lock_file in `find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_BACKUP_lock_*" | xargs `
do
_pid=`echo ${_lock_file}|cut -d"_" -f4`
is_pid_proc_running=`ps -ef|grep ${_pid}|grep -v grep | wc -l`
if [[ ${is_pid_proc_running} -ne 0 ]]
then
echo "[INFO] backup Lock File: ${_lock_file} is present and PID is active"
export BKP_CONTINUE=1
else
echo "[INFO] backup Lock File: ${_lock_file} is present and PID is NOT active"
echo "Deleting ${_lock_file}"
rm ${_lock_file}
if [ -e ${_lock_file} ]
then
echo "ERROR deleting file ${_lock_file}"
export BKP_CONTINUE=1
fi
fi
done
if [[ ${BKP_CONTINUE} -eq 1 ]]
then
echo "[WARNING] There is a backup running or the lock file for an already running backup is present"
echo "[ERROR] Exiting the current backup"
exit 5
fi
fi

# Creating a .lock file to represnt current active full/diff backup.
export file_stamp=`date | sed -e 's/ /_/g'`
PID=`echo $$`
LOCK_FILE=`echo ${RMANBACKUP_MOUNTPOINT}/.RMAN_BACKUP_lock_${PID}_${file_stamp}`
echo -n > ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[INFO] Lock file created: ${LOCK_FILE}"
else
echo "Error creating lock file: ${LOCK_FILE}"
echo "[ERROR] Backup will now stop"
exit -3
fi


echo "Starting with RMAN backup"

#Calling Start RMAN Backup
res_rmanbackup=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/${SID}/full/rmanbackup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res_rmanbackup
exit 1
fi

echo "Response RMAN Backup: ${res_rmanbackup}"

SNAPSHOT_NAME=`echo $res_rmanbackup|awk -F "snap_name" '{print $2}'|cut -d '"' -f3`
if [ -z "$SNAPSHOT_NAME" ];
then
echo "Failed to get Snapshot name. Exiting. Please check Export Service Logs in PBS"
exit 1
fi

echo "Snapshot to be created ${SNAPSHOT_NAME}"

echo -n >$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'

RMAN_LOGFILE=$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'
echo "RMAN Logfile: ${RMAN_LOGFILE}"
rman log=$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log' 2> /dev/null << EOF


connect target /
set echo on;

configure backup optimization on;
configure controlfile autobackup on;
configure device type disk parallelism $PARALLELISM BACKUP TYPE TO COPY;
configure datafile backup copies for device type disk to 1;
configure archivelog backup copies for device type disk to 1;
configure channel device type disk format '${RMANBACKUP_MOUNTPOINT_FULL}/full/datafile_%U.bkp';
configure controlfile autobackup format for device type disk to '${RMANBACKUP_MOUNTPOINT_FULL}/full/full_controlfile_%d_%F.bkp';

run
{

sql 'alter system archive log current';
backup incremental level 1 for recover of copy with tag 'phoenix_oracle_backup' database;
recover copy of database with tag 'phoenix_oracle_backup';
sql 'alter system archive log current';
backup as backupset format '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/%d_%h_%e_%s_%t.arc' archivelog all not backed up;

#Force is to ignore I/O errors
delete noprompt obsolete device type disk;
delete force NOPROMPT expired copy;
delete force NOPROMPT expired backup;

crosscheck backup;
crosscheck copy;
}

configure backup optimization clear;
configure controlfile autobackup clear;

exit

EOF

RMAN_EXIT_STATUS=$?
if [ $RMAN_EXIT_STATUS -ne 0 ];
then
echo ""
echo "rman failed with status $RMAN_EXIT_STATUS.. exiting"
rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi


echo "RMAN log location: $LOG_FILE_DIR/rman_full_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log"

echo "Notifying Phoenix to upload RMAN Logs"

rman_uploadlog_res=$(curl -X POST -H "Content-Type: multipart/form-data" -F "file=@$LOG_FILE_DIR/rman_full_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log" -F mountpoint=$RMANBACKUP_MOUNTPOINT -F platform=linux http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/uploadlog 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to send RMAN Logs failed..."
echo "Response from Phoenix Backup Store: "$rman_uploadlog_res
fi



rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi

echo "Notifying Phoenix to end backup"
final_res=$(curl -X PUT http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)

if [ $? -ne 0 ];
then
echo "Request to end phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$final_res

rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

ERROR_CODE=$(echo $final_res|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$final_res
echo "Request to End Phoenix backup failed... exiting"
fi
echo $final_res

echo "Exiting with successful status"
}

# Main
full_backup

oracle_rman_archivelog_backup.sh

Use this script for Enterprise Workloads agent version 7.0.2-1003652 or later

.

#!/bin/bash

if [ "$#" -ne 2 ]; then
echo ""
echo "Usage: $0 <backup_store_IP> <backup_mount_name>"
echo ""
echo " <backup_store_IP> : IP address of the Phoenix Backup Store"
echo " <backup_mount_name> : Name of the backup mount configured in Phoenix, e.g. mount1"
exit 1
fi

BACKUP_STORE_IP=$1
BACKUP_MOUNT=$2

PARALLELISM=1

if [[ -z "${ORACLE_HOME}" ]];
then
echo "Environment variable ORACLE_HOME not set... exiting"
exit 1
fi

if [[ -z "${ORACLE_SID}" ]];
then
echo "Environment variable ORACLE_SID not set... exiting"
exit 1
fi

SID=${ORACLE_SID}

# --- ENHANCED FAILURE NOTIFICATION TRAP ---
export RMAN_SCRIPT_STAGE="Initialization"
export RMAN_SCRIPT_ERROR_MSG="Unexpected termination during initialization"
export RMAN_SCRIPT_RESOLUTION_MSG="Check export service logs or contact Druva Support"

rman_script_failure_notify() {
local ec="${1:-1}"

# Only fire the alert if the exit code is strictly greater than 0
[ "$ec" -eq 0 ] && return 0

local stage="${RMAN_SCRIPT_STAGE}"
local sid="${ORACLE_SID}"
local err_msg="${RMAN_SCRIPT_ERROR_MSG}"
local resolution_msg="${RMAN_SCRIPT_RESOLUTION_MSG}"

# Escape internal double quotes and newlines to prevent JSON payload corruption
local stage_escaped="${stage//\"/\\\"}"
local sid_escaped="${sid//\"/\\\"}"
local err_msg_escaped="${err_msg//\"/\\\"}"
err_msg_escaped="${err_msg_escaped//$'\n'/ }" # Replace newlines with spaces
local resolution_msg_escaped="${resolution_msg//\"/\\\"}"
resolution_msg_escaped="${resolution_msg_escaped//$'\n'/ }" # Replace newlines with spaces

# Construct JSON payload natively using printf
local body
body=$(printf '{"exit_code":%d,"failure_stage":"%s","db_sid":"%s","error_msg":"%s","resolution_msg":"%s"}' \
"$ec" "$stage_escaped" "$sid_escaped" "$err_msg_escaped" "$resolution_msg_escaped")

# Network-hardened API call with a 30-second maximum timeout ceiling
curl -sS --max-time 30 -X POST "http://${BACKUP_STORE_IP}:9090/druva-phoenix/v1/mounts/${BACKUP_MOUNT}/rmanbackup/failure-alert" \
-H "Content-Type: application/json" \
-d "$body" >/dev/null 2>&1 || true
}

# Register trap to catch any exit and pass the true exit code
trap 'rman_script_failure_notify $?' EXIT
# ------------------------------------------

export RMAN_SCRIPT_STAGE="Validate Backup Request"
echo "Validating backup request"
validate_resp=$(curl -X GET http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/1.2/backup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Backup validation request failed with response: $validate_resp"
echo "Backup validation request failed with response: $validate_resp... exiting"
exit 1
fi

VALIDATE_ERROR_CODE=$(echo "$validate_resp" | awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$VALIDATE_ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Backup validation failed (error_code: ${VALIDATE_ERROR_CODE})"
echo "Backup validation request failed... exiting"
exit 1
fi

# Sample output format
# {"error_code":0,"error_msg":"","result":{"is_reached_max_snapshots":false,"mount_name":"m2"}}
IS_REACHED_MAX_SNAPSHOTS=$(echo "$validate_resp" | awk -F "is_reached_max_snapshots" '{print $2}' | cut -d ',' -f1 | cut -d ':' -f2)
if [ "$IS_REACHED_MAX_SNAPSHOTS" = "false" ];
then
echo "Validation for phoenix backup succeeded"
else
export RMAN_SCRIPT_ERROR_MSG="Backup mount reached max snapshot limit"
export RMAN_SCRIPT_RESOLUTION_MSG="Increase max snapshots limit or wait for pending uploads"
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Validation for phoenix backup failed... exiting"
exit 1
fi

export RMAN_SCRIPT_STAGE="Start Phoenix Backup"
echo "Notifying Phoenix to start backup - Phoenix Backup Store=$BACKUP_STORE_IP mount name=$BACKUP_MOUNT"

res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to start Phoenix Backup session"
echo "Request to start Phoenix Backup failed with response: $res... exiting"
exit 1
fi

# Sample output format
# {"error_code":4295622665,"error_msg":"Backup mount does not exist on Export Service.","result":{"mount_name":"mount4","mount_path":""}}
ERROR_CODE=$(echo "$res" | awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Phoenix Backup init failed (error_code: ${ERROR_CODE})"
echo "Request to start Phoenix Backup failed with response: $res... exiting"
exit 1
fi

export RMAN_SCRIPT_STAGE="Mount Phoenix Backup Store"
REMOTE_MOUNTPOINT=$BACKUP_STORE_IP:$(echo "$res" | awk -F "mount_path" '{print $2}' | cut -d '"' -f3)
RMANBACKUP_MOUNTPOINT=$(grep "^$REMOTE_MOUNTPOINT" /etc/fstab | sed 's/\s\+/ /g' | cut -d ' ' -f2)

if [ -z "$RMANBACKUP_MOUNTPOINT" ];
then
export RMAN_SCRIPT_ERROR_MSG="Mount entry missing from /etc/fstab"
export RMAN_SCRIPT_RESOLUTION_MSG="Add mount entry to /etc/fstab"
echo "Entry for Phoenix Backup Store mount not found in /etc/fstab... exiting"
exit 1
fi

ACTUAL_MOUNTPOINT=$(mount | grep "^$REMOTE_MOUNTPOINT" | sed 's/\s\+/ /g' | cut -d " " -f3 2> /dev/null)
if [ -z "$ACTUAL_MOUNTPOINT" ];
then
mount "$RMANBACKUP_MOUNTPOINT" 2> /dev/null
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to mount backup store"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify mount entry in /etc/fstab"
echo "Unable to mount $RMANBACKUP_MOUNTPOINT... exiting"
exit 1
fi
else
RMANBACKUP_MOUNTPOINT=$ACTUAL_MOUNTPOINT
fi

export PATH=$ORACLE_HOME/bin:$PATH
arch_backup () {

export RMAN_SCRIPT_STAGE="Create Archivelogs Backup Directory"
if [ ! -e "$RMANBACKUP_MOUNTPOINT/$SID/archivelogs" ]
then
mkdir -p "$RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
if [ $? -eq 0 ];
then
echo "Created directory for archivelogs backup $RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create archivelogs directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "Failed to create archivelogs directory... exiting"
exit 1
fi
elif [ ! -d "$RMANBACKUP_MOUNTPOINT/$SID/archivelogs" ];
then
export RMAN_SCRIPT_ERROR_MSG="Path conflict: archivelogs path is a file, expected directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Remove conflicting file and retry"
echo "$RMANBACKUP_MOUNTPOINT/$SID is not a directory... exiting"
exit 1
fi

LOG_FILE_DIR=$RMANBACKUP_MOUNTPOINT/'_workspace/RMAN_Logs'
echo "Creating Log File Dir: =$RMANBACKUP_MOUNTPOINT'/_workspace/RMAN_Logs'"

if [ ! -e "$LOG_FILE_DIR" ]
then
mkdir -p "$LOG_FILE_DIR"
if [ $? -eq 0 ];
then
echo "Created log directory for oracle backup $LOG_FILE_DIR"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create RMAN log directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "Failed to create RMAN log directory... exiting"
exit 1
fi
fi

echo -n > "$LOG_FILE_DIR/archivelogs_backup.log"
touch "$RMANBACKUP_MOUNTPOINT/_workspace/" 2>/dev/null
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to write to workspace folder"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "$RMANBACKUP_MOUNTPOINT directory is not writable.. exiting"
exit 1
fi

#Checking if any .lock file is present and deleting the same if the PID is NOT running.
echo "Checking for backup lock file"
export RMAN_SCRIPT_STAGE="Check for Backup Lock File"
export BKP_CONTINUE=0
is_lock_file_present=$(find "${RMANBACKUP_MOUNTPOINT}" -type f -name ".RMAN_BACKUP_lock_*" | wc -l)
if [[ ${is_lock_file_present} -ne 0 ]]
then
for _lock_file in $(find "${RMANBACKUP_MOUNTPOINT}" -type f -name ".RMAN_BACKUP_lock_*" | xargs)
do
_pid=$(echo "${_lock_file}" | cut -d"_" -f4)
is_pid_proc_running=$(ps -ef | grep "${_pid}" | grep -v grep | wc -l)
if [[ ${is_pid_proc_running} -ne 0 ]]
then
echo "[INFO] backup Lock File: ${_lock_file} is present and PID is active"
export BKP_CONTINUE=1
else
echo "[INFO] backup Lock File: ${_lock_file} is present and PID is NOT active"
echo "Deleting ${_lock_file}"
rm "${_lock_file}"
if [ -e "${_lock_file}" ]
then
echo "ERROR deleting file ${_lock_file}"
export BKP_CONTINUE=1
fi
fi
done
if [[ ${BKP_CONTINUE} -eq 1 ]]
then
export RMAN_SCRIPT_ERROR_MSG="Skipping backup: active RMAN backup or lock file present"
export RMAN_SCRIPT_RESOLUTION_MSG="Wait for active backup to finish or remove stale lock file"
echo "Skipping backup: active RMAN backup or lock file present... exiting"
exit 1
fi
fi

export file_stamp=$(date | sed -e 's/ /_/g')
PID=$$
LOCK_FILE="${RMANBACKUP_MOUNTPOINT}/.RMAN_BACKUP_lock_${PID}_${file_stamp}"
echo -n > "${LOCK_FILE}"
if [ -e "${LOCK_FILE}" ]
then
echo "[INFO] Lock file created: ${LOCK_FILE}"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create backup lock file"
export RMAN_SCRIPT_RESOLUTION_MSG="Check backup mount disk space and permissions"
echo "Error creating lock file: ${LOCK_FILE}"
echo "[ERROR] Backup will now stop"
exit 1
fi

echo "Starting with RMAN backup"
RMANBACKUP_MOUNTPOINT_FULL=$RMANBACKUP_MOUNTPOINT/$SID

export RMAN_SCRIPT_STAGE="Request RMAN Snapshot for Archivelog Backup"
res_rmanbackup=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/${SID}/archivelog/rmanbackup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to request RMAN snapshot"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify backup mount configuration"
echo "Request to start Phoenix Backup failed with response: $res_rmanbackup... exiting"
rm "${LOCK_FILE}"
exit 1
fi

echo "Response RMAN Backup: ${res_rmanbackup}"

SNAPSHOT_NAME=$(echo "$res_rmanbackup" | awk -F "snap_name" '{print $2}' | cut -d '"' -f3)
if [ -z "$SNAPSHOT_NAME" ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to get snapshot name"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify backup mount configuration"
echo "Failed to get Snapshot name... exiting with response: $res_rmanbackup"
rm "${LOCK_FILE}"
exit 1
fi

echo "Snapshot to be created ${SNAPSHOT_NAME}"

export RMAN_SCRIPT_STAGE="Run RMAN Backup"
RMAN_LOGFILE=$LOG_FILE_DIR'/rman_archivelog_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'
echo -n > "$RMAN_LOGFILE"
echo "RMAN Logfile: ${RMAN_LOGFILE}"

rman log="$RMAN_LOGFILE" 2> /dev/null << EOF
connect target /
set echo on;

configure backup optimization on;
configure controlfile autobackup on;
configure device type disk parallelism ${PARALLELISM} BACKUP TYPE TO COPY;
configure datafile backup copies for device type disk to 1;
configure archivelog backup copies for device type disk to 1;
configure controlfile autobackup format for device type disk to '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/arch_controlfile_%d_%F.bkp';

run
{
sql 'alter system archive log current';
backup as backupset format '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/%d_%h_%e_%s_%t.arc' archivelog all not backed up;

#Force is to ignore I/O errors
delete noprompt obsolete device type disk;
delete force NOPROMPT expired copy;
delete force NOPROMPT expired backup;

crosscheck backup;
crosscheck copy;
}

configure backup optimization clear;
configure controlfile autobackup clear;
exit
EOF

RMAN_EXIT_STATUS=$?
if [ $RMAN_EXIT_STATUS -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="RMAN backup failed (exit_code: ${RMAN_EXIT_STATUS})"
export RMAN_SCRIPT_RESOLUTION_MSG="Check RMAN logs and fix the issue"
echo ""
echo "RMAN backup failed (exit_code: ${RMAN_EXIT_STATUS})... exiting"
rm "${LOCK_FILE}"
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

export RMAN_SCRIPT_STAGE="Upload RMAN Logs"
echo "Notifying Phoenix to upload RMAN Logs"

rman_uploadlog_res=$(curl -X POST -H "Content-Type: multipart/form-data" -F "file=@$LOG_FILE_DIR/rman_archivelog_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log" -F mountpoint=$RMANBACKUP_MOUNTPOINT -F platform=linux http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/uploadlog 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to send RMAN Logs failed..."
echo "Response from Phoenix Backup Store: "$rman_uploadlog_res
fi

rm "${LOCK_FILE}"
if [ -e "${LOCK_FILE}" ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=$(date | sed -e 's/ /_/g')
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi

export RMAN_SCRIPT_STAGE="End Backup"
echo "Notifying Phoenix to end backup"
final_res=$(curl -X PUT http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)

if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to end Phoenix Backup with response: $final_res"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify export service is reachable and check its logs"
echo "Request to end Phoenix Backup failed with response: $final_res... exiting"
rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

ERROR_CODE=$(echo "$final_res" | awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to end Phoenix Backup (error_code: ${ERROR_CODE})"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify export service is reachable and check its logs"
echo "Response from Phoenix Backup Store: "$final_res
echo "Request to end Phoenix Backup failed... exiting"
exit 1
fi
echo "$final_res"

echo "Exiting with successful status"
}

# Main
arch_backup

Use this script for Enterprise Workloads agent version 7.0.2-985623 or earlier.

#!/bin/bash

if [ "$#" -ne 2 ]; then
echo ""
echo "Usage: $0 <backup_store_IP> <backup_mount_name>"
echo ""
echo " <backup_store_IP> : IP address of the Phoenix Backup Store"
echo " <backup_mount_name> : Name of the backup mount configured in Phoenix, e.g. mount1"
exit 1
fi

BACKUP_STORE_IP=$1
BACKUP_MOUNT=$2

PARALLELISM=1

if [[ -z "${ORACLE_HOME}" ]];
then
echo "Environment variable ORACLE_HOME not set... exiting"
exit 1
fi

if [[ -z "${ORACLE_SID}" ]];
then
echo "Environment variable ORACLE_SID not set... exiting"
exit 1
fi

SID=${ORACLE_SID}

echo "Validating backup request"
validate_resp=$(curl -X GET http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/1.2/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to validate phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$validate_resp
exit 1
fi

VALIDATE_ERROR_CODE=$(echo $validate_resp|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $VALIDATE_ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Request to validate Phoenix backup failed... exiting"
exit 1
fi

# Sample output format
# {"error_code":0,"error_msg":"","result":{"is_reached_max_snapshots":false,"mount_name":"m2"}}
IS_REACHED_MAX_SNAPSHOTS=$(echo $validate_resp|awk -F "is_reached_max_snapshots" '{print $2}'|cut -d ',' -f1 |cut -d ':' -f2)
if [ $IS_REACHED_MAX_SNAPSHOTS == "false" ];
then
echo "Validation for phoenix backup succeeded"
else
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Validation for phoenix backup failed... exiting"
exit 1
fi

echo "Notifying Phoenix to start backup - Phoenix Backup Store=$BACKUP_STORE_IP mount name=$BACKUP_MOUNT"

res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res
exit 1
fi

# Sample output format
# {"error_code":4295622665,"error_msg":"Backup mount does not exist on Export Service.","result":{"mount_name":"mount4","mount_path":""}}
ERROR_CODE=$(echo $res|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)

if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$res
echo "Request to start Phoenix backup failed... exiting"
exit 1
fi

REMOTE_MOUNTPOINT=$BACKUP_STORE_IP:$(echo $res|awk -F "mount_path" '{print $2}'|cut -d '"' -f3)
RMANBACKUP_MOUNTPOINT=$(grep "^$REMOTE_MOUNTPOINT" /etc/fstab| sed 's/\s\+/ /g' |cut -d ' ' -f2)

if [ -z "$RMANBACKUP_MOUNTPOINT" ];
then
echo "Entry for Phoenix Backup Store mount not found in /etc/fstab... exiting"
exit 1
fi

ACTUAL_MOUNTPOINT=$(mount|grep "^$REMOTE_MOUNTPOINT"|sed 's/\s\+/ /g' |cut -d " " -f3 2> /dev/null)
if [ -z "$ACTUAL_MOUNTPOINT" ];
then
mount $RMANBACKUP_MOUNTPOINT 2> /dev/null
if [ $? -ne 0 ];
then
echo "Unable to mount $RMANBACKUP_MOUNTPOINT... exiting"
exit 1
fi
else
RMANBACKUP_MOUNTPOINT=$ACTUAL_MOUNTPOINT
fi

export PATH=$ORACLE_HOME/bin:$PATH
arch_backup () {

if [ ! -e $RMANBACKUP_MOUNTPOINT/$SID'/archivelogs' ]
then
mkdir -p $RMANBACKUP_MOUNTPOINT/$SID'/archivelogs'
if [ $? -eq 0 ];
then
echo "Created directory for archivelogs backup $RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
else
echo "Oracle user does not have permission for $RMANBACKUP_MOUNTPOINT/$SID directory... exiting"
exit 1
fi
elif [ ! -d $RMANBACKUP_MOUNTPOINT/$SID'/archivelogs' ];
then
echo "$RMANBACKUP_MOUNTPOINT/$SID is not a directory... exiting"
fi

LOG_FILE_DIR=$RMANBACKUP_MOUNTPOINT/'_workspace/RMAN_Logs'
echo "Creating Log File Dir: =$RMANBACKUP_MOUNTPOINT'/_workspace/RMAN_Logs'"

if [ ! -e $LOG_FILE_DIR ]
then
mkdir -p $LOG_FILE_DIR
if [ $? -eq 0 ];
then
echo "Created log directory for oracle backup $LOG_FILE_DIR"
else
echo "Oracle user does not have permission for $LOG_FILE_DIR directory... exiting"
exit 1
fi
fi

echo -n >$LOG_FILE_DIR'/archivelogs_backup.log'
touch $RMANBACKUP_MOUNTPOINT/_workspace/
if [ $? -ne 0 ];
then
echo "$RMANBACKUP_MOUNTPOINT directory is not writable.. exiting"
exit 1
fi


#Checking if any .lock file is present and deleting the same if the PID is NOT running.
export BKP_CONTINUE=0
is_lock_file_present=`find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_BACKUP_lock_*"|wc -l `
if [[ ${is_lock_file_present} -ne 0 ]]
then
for _lock_file in `find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_BACKUP_lock_*" | xargs `
do
_pid=`echo ${_lock_file}|cut -d"_" -f4`
is_pid_proc_running=`ps -ef|grep ${_pid}|grep -v grep | wc -l`
if [[ ${is_pid_proc_running} -ne 0 ]]
then
echo "[INFO] backup Lock File: ${_lock_file} is present and PID is active"
export BKP_CONTINUE=1
else
echo "[INFO] backup Lock File: ${_lock_file} is present and PID is NOT active"
echo "Deleting ${_lock_file}"
rm ${_lock_file}
if [ -e ${_lock_file} ]
then
echo "ERROR deleting file ${_lock_file}"
export BKP_CONTINUE=1
fi
fi
done
if [[ ${BKP_CONTINUE} -eq 1 ]]
then
echo "[WARNING] There is a backup running or the lock file for an already running backup is present"
echo "[ERROR] Exiting the current backup"
exit 5
fi
fi

# Creating a .lock file to represnt current active archivelog backup.
export file_stamp=`date | sed -e 's/ /_/g'`
PID=`echo $$`
LOCK_FILE=`echo ${RMANBACKUP_MOUNTPOINT}/.RMAN_BACKUP_lock_${PID}_${file_stamp}`
echo -n > ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[INFO] Lock file created: ${LOCK_FILE}"
else
echo "Error creating lock file: ${LOCK_FILE}"
echo "[ERROR] Backup will now stop"
exit -3
fi

echo "Starting with RMAN backup"
RMANBACKUP_MOUNTPOINT_FULL=$RMANBACKUP_MOUNTPOINT/$SID

#Calling Start RMAN Backup
res_rmanbackup=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/${SID}/archivelog/rmanbackup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res_rmanbackup
rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

echo "Response RMAN Backup: ${res_rmanbackup}"

SNAPSHOT_NAME=`echo $res_rmanbackup|awk -F "snap_name" '{print $2}'|cut -d '"' -f3`
if [ -z "$SNAPSHOT_NAME" ];
then
echo "Failed to get Snapshot name. Exiting. Please check Export Service Logs in PBS"
rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

echo "Snapshot to be created ${SNAPSHOT_NAME}"

echo -n >$LOG_FILE_DIR'/rman_archivelog_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'

RMAN_LOGFILE=$LOG_FILE_DIR'/rman_archivelog_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'
echo "RMAN Logfile: ${RMAN_LOGFILE}"
rman log=$LOG_FILE_DIR'/rman_archivelog_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log' 2> /dev/null << EOF

connect target /
set echo on;

configure backup optimization on;
configure controlfile autobackup on;
configure device type disk parallelism ${PARALLELISM} BACKUP TYPE TO COPY;
configure datafile backup copies for device type disk to 1;
configure archivelog backup copies for device type disk to 1;
configure controlfile autobackup format for device type disk to '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/arch_controlfile_%d_%F.bkp';

run
{
sql 'alter system archive log current';
backup as backupset format '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/%d_%h_%e_%s_%t.arc' archivelog all not backed up;

#Force is to ignore I/O errors
delete noprompt obsolete device type disk;
delete force NOPROMPT expired copy;
delete force NOPROMPT expired backup;

crosscheck backup;
crosscheck copy;
}

configure backup optimization clear;
configure controlfile autobackup clear;

exit

EOF

RMAN_EXIT_STATUS=$?
if [ $RMAN_EXIT_STATUS -ne 0 ];
then
echo ""
echo "rman failed with status $RMAN_EXIT_STATUS.. exiting"
rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

echo ""


echo "Notifying Phoenix to upload RMAN Logs"

rman_uploadlog_res=$(curl -X POST -H "Content-Type: multipart/form-data" -F "file=@$LOG_FILE_DIR/rman_archivelog_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log" -F mountpoint=$RMANBACKUP_MOUNTPOINT -F platform=linux http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/uploadlog 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to send RMAN Logs failed..."
echo "Response from Phoenix Backup Store: "$rman_uploadlog_res
fi



rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi

echo "Notifying Phoenix to end backup"
final_res=$(curl -X PUT http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)

if [ $? -ne 0 ];
then
echo "Request to end phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$final_res

rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi
ERROR_CODE=$(echo $final_res|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$final_res
echo "Request to start Phoenix backup failed... exiting"
fi
echo $final_res

echo "Exiting with successful status"
}

# Main
arch_backup

oracle_rman_data_backup_Solaris.sh

Use this script for Enterprise Workloads agent version 7.0.2-1003652 or later.

#!/bin/bash

if [ "$#" -ne 2 ]; then
echo ""
echo "Usage: $0 <backup_store_IP> <backup_mount_name>"
echo ""
echo " <backup_store_IP> : IP address of the Phoenix Backup Store"
echo " <backup_mount_name> : Name of the backup mount configured in Phoenix, e.g. mount1"
exit 1
fi

BACKUP_STORE_IP=$1
BACKUP_MOUNT=$2

PARALLELISM=1

if [[ -z "${ORACLE_HOME}" ]];
then
echo "Environment variable ORACLE_HOME not set... exiting"
exit 1
fi

if [[ -z "${ORACLE_SID}" ]];
then
echo "Environment variable ORACLE_SID not set... exiting"
exit 1
fi

SID=${ORACLE_SID}

# --- ENHANCED FAILURE NOTIFICATION TRAP ---
export RMAN_SCRIPT_STAGE="Initialization"
export RMAN_SCRIPT_ERROR_MSG="Unexpected termination during initialization"
export RMAN_SCRIPT_RESOLUTION_MSG="Check export service logs or contact Druva Support"

rman_script_failure_notify() {
local ec="${1:-1}"

# Only fire the alert if the exit code is strictly greater than 0
[ "$ec" -eq 0 ] && return 0

local stage="${RMAN_SCRIPT_STAGE}"
local sid="${ORACLE_SID}"
local err_msg="${RMAN_SCRIPT_ERROR_MSG}"
local resolution_msg="${RMAN_SCRIPT_RESOLUTION_MSG}"

# Escape internal double quotes and newlines to prevent JSON payload corruption
local stage_escaped="${stage//\"/\\\"}"
local sid_escaped="${sid//\"/\\\"}"
local err_msg_escaped="${err_msg//\"/\\\"}"
err_msg_escaped="${err_msg_escaped//$'\n'/ }" # Replace newlines with spaces
local resolution_msg_escaped="${resolution_msg//\"/\\\"}"
resolution_msg_escaped="${resolution_msg_escaped//$'\n'/ }" # Replace newlines with spaces

# Construct JSON payload natively using printf
local body
body=$(printf '{"exit_code":%d,"failure_stage":"%s","db_sid":"%s","error_msg":"%s","resolution_msg":"%s"}' \
"$ec" "$stage_escaped" "$sid_escaped" "$err_msg_escaped" "$resolution_msg_escaped")

# Network-hardened API call with a 30-second maximum timeout ceiling
curl -sS --max-time 30 -X POST "http://${BACKUP_STORE_IP}:9090/druva-phoenix/v1/mounts/${BACKUP_MOUNT}/rmanbackup/failure-alert" \
-H "Content-Type: application/json" \
-d "$body" >/dev/null 2>&1 || true
}

# Register trap to catch any exit and pass the true exit code
trap 'rman_script_failure_notify $?' EXIT
# ------------------------------------------

export RMAN_SCRIPT_STAGE="Validate Backup Request"
echo "Validating backup request"

validate_resp=$(curl -X GET http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/1.2/backup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Backup validation request failed with response: $validate_resp"
echo "Backup validation request failed with response: $validate_resp... exiting"
exit 1
fi

VALIDATE_ERROR_CODE=$(echo "$validate_resp" | /usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$VALIDATE_ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Backup validation failed (error_code: ${VALIDATE_ERROR_CODE})"
echo "Backup validation request failed... exiting"
exit 1
fi

# Sample output format
# {"error_code":0,"error_msg":"","result":{"is_reached_max_snapshots":false,"mount_name":"m2"}}
IS_REACHED_MAX_SNAPSHOTS=$(echo "$validate_resp" | /usr/xpg4/bin/awk -F "is_reached_max_snapshots" '{print $2}' | cut -d ',' -f1 | cut -d ':' -f2)
if [ "$IS_REACHED_MAX_SNAPSHOTS" = "false" ];
then
echo "Validation for phoenix backup succeeded"
else
export RMAN_SCRIPT_ERROR_MSG="Backup mount reached max snapshot limit"
export RMAN_SCRIPT_RESOLUTION_MSG="Increase max snapshots limit or wait for pending uploads"
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Validation for phoenix backup failed... exiting"
exit 1
fi

export RMAN_SCRIPT_STAGE="Start Phoenix Backup"
echo "Notifying Phoenix to start backup - Phoenix Backup Store=$BACKUP_STORE_IP mount name=$BACKUP_MOUNT"

res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to start Phoenix Backup session"
echo "Request to start Phoenix Backup failed with response: $res... exiting"
exit 1
fi

# Sample output format
# {"error_code":4295622665,"error_msg":"Backup mount does not exist on Export Service.","result":{"mount_name":"mount4","mount_path":""}}
ERROR_CODE=$(echo "$res" | /usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Phoenix Backup init failed (error_code: ${ERROR_CODE})"
echo "Request to start Phoenix Backup failed with response: $res... exiting"
exit 1
fi

export RMAN_SCRIPT_STAGE="Mount Phoenix Backup Store"
REMOTE_MOUNTPOINT=$BACKUP_STORE_IP:$(echo "$res" | /usr/xpg4/bin/awk -F "mount_path" '{print $2}' | cut -d '"' -f3)
RMANBACKUP_MOUNTPOINT=$(grep "^$REMOTE_MOUNTPOINT" /etc/vfstab | sed 's/\s\+/ /g' | cut -d ' ' -f3)

if [ -z "$RMANBACKUP_MOUNTPOINT" ];
then
export RMAN_SCRIPT_ERROR_MSG="Mount entry missing from /etc/vfstab"
export RMAN_SCRIPT_RESOLUTION_MSG="Add mount entry to /etc/vfstab"
echo "Entry for Phoenix Backup Store mount not found in /etc/vfstab... exiting"
exit 1
fi

ACTUAL_MOUNTPOINT=$(mount | grep -w "$REMOTE_MOUNTPOINT" | cut -d" " -f1 | head -1 | sed 's/\s\+/ /g' 2> /dev/null)
if [ -z "$ACTUAL_MOUNTPOINT" ];
then
mount "$RMANBACKUP_MOUNTPOINT" 2> /dev/null
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to mount backup store"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify mount entry in /etc/vfstab"
echo "Unable to mount $RMANBACKUP_MOUNTPOINT... exiting"
exit 1
fi
else
RMANBACKUP_MOUNTPOINT=$ACTUAL_MOUNTPOINT
fi

export PATH=$ORACLE_HOME/bin:$PATH
full_backup () {

export RMAN_SCRIPT_STAGE="Create Full Backup Directory"
echo "Creating Dir $RMANBACKUP_MOUNTPOINT/$SID'/full'"

if [ ! -e "$RMANBACKUP_MOUNTPOINT/$SID/full" ]
then
mkdir -p "$RMANBACKUP_MOUNTPOINT/$SID/full"
if [ $? -eq 0 ];
then
echo "Created directory for full backup $RMANBACKUP_MOUNTPOINT/$SID/full"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create full backup directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "Failed to create full backup directory... exiting"
exit 1
fi
elif [ ! -d "$RMANBACKUP_MOUNTPOINT/${SID}/full" ];
then
export RMAN_SCRIPT_ERROR_MSG="Path conflict: full path is a file, expected directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Remove conflicting file and retry"
echo "$RMANBACKUP_MOUNTPOINT/$SID is not a directory... exiting"
exit 1
fi

export RMAN_SCRIPT_STAGE="Create Archivelogs Backup Directory"
if [ ! -e "$RMANBACKUP_MOUNTPOINT/${SID}/archivelogs" ]
then
mkdir -p "$RMANBACKUP_MOUNTPOINT/${SID}/archivelogs"
if [ $? -eq 0 ];
then
echo "Created directory for archivelogs backup $RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create archivelogs directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "Failed to create archivelogs directory... exiting"
exit 1
fi
elif [ ! -d "$RMANBACKUP_MOUNTPOINT/${SID}/archivelogs" ];
then
export RMAN_SCRIPT_ERROR_MSG="Path conflict: archivelogs path is a file, expected directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Remove conflicting file and retry"
echo "$RMANBACKUP_MOUNTPOINT/$SID is not a directory... exiting"
exit 1
fi

LOG_FILE_DIR=$RMANBACKUP_MOUNTPOINT/'_workspace/RMAN_Logs'
echo "Creating Log File Dir: =$RMANBACKUP_MOUNTPOINT'/_workspace/RMAN_Logs'"

if [ ! -e "$LOG_FILE_DIR" ]
then
mkdir -p "$LOG_FILE_DIR"
if [ $? -eq 0 ];
then
echo "Created log directory for oracle backup $LOG_FILE_DIR"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create RMAN log directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "Failed to create RMAN log directory... exiting"
exit 1
fi
fi

echo -n > "$LOG_FILE_DIR/rman_full_backup.log"
RMANBACKUP_MOUNTPOINT_FULL=$RMANBACKUP_MOUNTPOINT/$SID

touch "$RMANBACKUP_MOUNTPOINT/_workspace/" 2>/dev/null
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to write to workspace folder"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "$RMANBACKUP_MOUNTPOINT directory is not writable.. exiting"
exit 1
fi

#Checking if any .lock file is present and deleting the same if the PID is NOT running.
echo "Checking for backup lock file"
export RMAN_SCRIPT_STAGE="Check for Backup Lock File"
export BKP_CONTINUE=0
is_lock_file_present=$(find "${RMANBACKUP_MOUNTPOINT}" -type f -name ".RMAN_FULL_lock_*" | wc -l)
if [[ ${is_lock_file_present} -ne 0 ]]
then
for _lock_file in $(find "${RMANBACKUP_MOUNTPOINT}" -type f -name ".RMAN_FULL_lock_*" | xargs)
do
_pid=$(echo "${_lock_file}" | cut -d"_" -f4)
is_pid_proc_running=$(ps -ef | grep "${_pid}" | grep -v grep | wc -l)
if [[ ${is_pid_proc_running} -ne 0 ]]
then
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is active"
export BKP_CONTINUE=1
else
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is NOT active"
echo "Deleting ${_lock_file}"
rm "${_lock_file}"
if [ -e "${_lock_file}" ]
then
echo "ERROR deleting file ${_lock_file}"
export BKP_CONTINUE=1
fi
fi
done
if [[ ${BKP_CONTINUE} -eq 1 ]]
then
export RMAN_SCRIPT_ERROR_MSG="Skipping backup: active RMAN backup or lock file present"
export RMAN_SCRIPT_RESOLUTION_MSG="Wait for active backup to finish or remove stale lock file"
echo "Skipping backup: active RMAN backup or lock file present... exiting"
exit 1
fi
fi

export file_stamp=$(date | sed -e 's/ /_/g')
PID=$$
LOCK_FILE="${RMANBACKUP_MOUNTPOINT}/.RMAN_BACKUP_lock_${PID}_${file_stamp}"
echo -n > "${LOCK_FILE}"
if [ -e "${LOCK_FILE}" ]
then
echo "[INFO] Lock file created: ${LOCK_FILE}"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create backup lock file"
export RMAN_SCRIPT_RESOLUTION_MSG="Check backup mount disk space and permissions"
echo "Error creating lock file: ${LOCK_FILE}"
echo "[ERROR] Backup will now stop"
exit 1
fi


echo "Starting with RMAN backup"
RMANBACKUP_MOUNTPOINT_FULL=$RMANBACKUP_MOUNTPOINT/$SID

export RMAN_SCRIPT_STAGE="Request RMAN Snapshot for Full Backup"
res_rmanbackup=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/${SID}/full/rmanbackup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to request RMAN snapshot"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify backup mount configuration"
echo "Request to start Phoenix Backup failed with response: $res_rmanbackup... exiting"
rm "${LOCK_FILE}"
exit 1
fi

echo "Response RMAN Backup: ${res_rmanbackup}"

SNAPSHOT_NAME=$(echo "$res_rmanbackup" | /usr/xpg4/bin/awk -F "snap_name" '{print $2}' | cut -d '"' -f3)
if [ -z "$SNAPSHOT_NAME" ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to get snapshot name"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify backup mount configuration"
echo "Failed to get Snapshot name... exiting with response: $res_rmanbackup"
rm "${LOCK_FILE}"
exit 1
fi

echo "Snapshot to be created ${SNAPSHOT_NAME}"

export RMAN_SCRIPT_STAGE="Run RMAN Backup"
RMAN_LOGFILE=$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'
echo "RMAN Logfile: ${RMAN_LOGFILE}"
rman log=${RMAN_LOGFILE} 2> /dev/null << EOF

connect target /
set echo on;

configure backup optimization on;
configure controlfile autobackup on;
configure device type disk parallelism $PARALLELISM BACKUP TYPE TO COPY;
configure datafile backup copies for device type disk to 1;
configure archivelog backup copies for device type disk to 1;
configure channel device type disk format '$RMANBACKUP_MOUNTPOINT_FULL/full/datafile_%U.bkp';
configure controlfile autobackup format for device type disk to '$RMANBACKUP_MOUNTPOINT_FULL/full/full_controlfile_%d_%F';

run
{
sql 'alter system archive log current';
backup incremental level 1 for recover of copy with tag 'phoenix_oracle_backup' database;
recover copy of database with tag 'phoenix_oracle_backup';
sql 'alter system archive log current';
backup as backupset format '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/%d_%h_%e_%s_%t.arc' archivelog all not backed up;
#Force is to ignore I/O errors
delete noprompt obsolete device type disk;
delete force NOPROMPT expired copy;
delete force NOPROMPT expired backup;

crosscheck backup;
crosscheck copy;
}

configure backup optimization clear;
configure controlfile autobackup clear;

exit

EOF

RMAN_EXIT_STATUS=$?
if [ $RMAN_EXIT_STATUS -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="RMAN backup failed (exit_code: ${RMAN_EXIT_STATUS})"
export RMAN_SCRIPT_RESOLUTION_MSG="Check RMAN logs and fix the issue"
echo ""
echo "RMAN backup failed (exit_code: ${RMAN_EXIT_STATUS})... exiting"
rm "${LOCK_FILE}"
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

echo "RMAN log location: $LOG_FILE_DIR/rman_full_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log"

export RMAN_SCRIPT_STAGE="Upload RMAN Logs"
echo "Notifying Phoenix to upload RMAN Logs"

rman_uploadlog_res=$(curl -X POST -H "Content-Type: multipart/form-data" -F "file=@$LOG_FILE_DIR/rman_full_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log" -F mountpoint=$RMANBACKUP_MOUNTPOINT -F platform=linux http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/uploadlog 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to send RMAN Logs failed..."
echo "Response from Phoenix Backup Store: "$rman_uploadlog_res
fi

rm "${LOCK_FILE}"
if [ -e "${LOCK_FILE}" ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=$(date | sed -e 's/ /_/g')
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi

export RMAN_SCRIPT_STAGE="End Backup"
echo "Notifying Phoenix to end backup"
final_res=$(curl -X PUT http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)

if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to end Phoenix Backup with response: $final_res"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify export service is reachable and check its logs"
echo "Request to end Phoenix Backup failed with response: $final_res... exiting"
rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

ERROR_CODE=$(echo "$final_res" | /usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to end Phoenix Backup (error_code: ${ERROR_CODE})"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify export service is reachable and check its logs"
echo "Response from Phoenix Backup Store: "$final_res
echo "Request to end Phoenix Backup failed... exiting"
exit 1
fi
echo "$final_res"

echo "Exiting with successful status"
}

# Main
full_backup

Use this script for Enterprise Workloads agent version 7.0.2-985623 or earlier.

#!/bin/bash

if [ "$#" -ne 2 ]; then
echo ""
echo "Usage: $0 <backup_store_IP> <backup_mount_name>"
echo ""
echo " <backup_store_IP> : IP address of the Phoenix Backup Store"
echo " <backup_mount_name> : Name of the backup mount configured in Phoenix, e.g. mount1"
exit 1
fi

BACKUP_STORE_IP=$1
BACKUP_MOUNT=$2

PARALLELISM=1

if [[ -z "${ORACLE_HOME}" ]];
then
echo "Environment variable ORACLE_HOME not set... exiting"
exit 1
fi

if [[ -z "${ORACLE_SID}" ]];
then
echo "Environment variable ORACLE_SID not set... exiting"
exit 1
fi

SID=${ORACLE_SID}

echo "Validating backup request"
validate_resp=$(curl -X GET http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/1.2/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to validate phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$validate_resp
exit 1
fi

VALIDATE_ERROR_CODE=$(echo $validate_resp|/usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $VALIDATE_ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Request to validate Phoenix backup failed... exiting"
exit 1
fi

# Sample output format
# {"error_code":0,"error_msg":"","result":{"is_reached_max_snapshots":false,"mount_name":"m2"}}
IS_REACHED_MAX_SNAPSHOTS=$(echo $validate_resp|/usr/xpg4/bin/awk -F "is_reached_max_snapshots" '{print $2}'|cut -d ',' -f1 |cut -d ':' -f2)
if [ $IS_REACHED_MAX_SNAPSHOTS == "false" ];
then
echo "Validation for phoenix backup succeeded"
else
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Validation for phoenix backup failed... exiting"
exit 1
fi

echo "Notifying Phoenix to start backup - Phoenix Backup Store=$BACKUP_STORE_IP mount name=$BACKUP_MOUNT"

res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res
exit 1
fi

# Sample output format
# {"error_code":4295622665,"error_msg":"Backup mount does not exist on Export Service.","result":{"mount_name":"mount4","mount_path":""}}
ERROR_CODE=$(echo $res|/usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)

if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$res
echo "Request to start Phoenix backup failed... exiting"
exit 1
fi

REMOTE_MOUNTPOINT=$BACKUP_STORE_IP:$(echo $res|/usr/xpg4/bin/awk -F "mount_path" '{print $2}'|cut -d '"' -f3)
RMANBACKUP_MOUNTPOINT=$(grep "^$REMOTE_MOUNTPOINT" /etc/vfstab| sed 's/\s\+/ /g' |cut -d ' ' -f3)


if [ -z "$RMANBACKUP_MOUNTPOINT" ];
then
echo "Entry for Phoenix Backup Store mount not found in /etc/vfstab... exiting"
exit 1
fi

ACTUAL_MOUNTPOINT=$(mount|grep -w "$REMOTE_MOUNTPOINT"| cut -d" " -f1 |head -1|sed 's/\s\+/ /g' 2>/dev/null)


if [ -z "$ACTUAL_MOUNTPOINT" ];
then
mount $RMANBACKUP_MOUNTPOINT 2> /dev/null
if [ $? -ne 0 ];
then
echo "Unable to mount $RMANBACKUP_MOUNTPOINT... exiting"
exit 1
fi
else
RMANBACKUP_MOUNTPOINT=$ACTUAL_MOUNTPOINT
fi

export PATH=$ORACLE_HOME/bin:$PATH
full_backup () {

#Creating full backup directory
echo "Creating Dir $RMANBACKUP_MOUNTPOINT/$SID'/full'"

if [ ! -e $RMANBACKUP_MOUNTPOINT/$SID'/full' ]
then
mkdir -p $RMANBACKUP_MOUNTPOINT/$SID'/full'
if [ $? -eq 0 ];
then
echo "Created directory for full backup $RMANBACKUP_MOUNTPOINT/$SID/full"
else
echo "Oracle user does not have permission for $RMANBACKUP_MOUNTPOINT directory... exiting"
exit 1
fi
elif [ ! -d $RMANBACKUP_MOUNTPOINT/${SID}'/full' ];
then
echo "$RMANBACKUP_MOUNTPOINT is not a directory... exiting"
exit 1
fi

#Creating Archivelog Directory

if [ ! -e $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs' ]
then
mkdir -p $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs'
if [ $? -eq 0 ];
then
echo "Created directory for archivelogs backup $RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
else
echo "Oracle user does not have permission for $RMANBACKUP_MOUNTPOINT directory... exiting"
exit 1
fi

elif [ ! -d $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs' ];
then
echo "$RMANBACKUP_MOUNTPOINT is not a directory... exiting"
exit 1
fi

LOG_FILE_DIR=$RMANBACKUP_MOUNTPOINT/'_workspace/RMAN_Logs'
echo "Creating Log File Dir: =$RMANBACKUP_MOUNTPOINT'/_workspace/RMAN_Logs'"

if [ ! -e $LOG_FILE_DIR ]
then
mkdir -p $LOG_FILE_DIR
if [ $? -eq 0 ];
then
echo "Created log directory for oracle backup $LOG_FILE_DIR"
else
echo "Oracle user does not have permission for $LOG_FILE_DIR directory... exiting"
exit 1
fi
fi



echo -n >$LOG_FILE_DIR'/rman_full_backup_${ORACLE_SID}.log'
touch $RMANBACKUP_MOUNTPOINT/_workspace/
if [ $? -ne 0 ];
then
echo "$RMANBACKUP_MOUNTPOINT directory is not writable.. exiting"
exit 1
fi

#Checking if any .lock file is present and deleting the same if the PID is NOT running.

is_lock_file_present=`find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_FULL_lock_*"|wc -l `
if [[ ${is_lock_file_present} -ne 0 ]]
then
for _lock_file in `find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_FULL_lock_*" | xargs `
do
_pid=`echo ${_lock_file}|cut -d"_" -f4`
is_pid_proc_running=`ps -ef|grep ${_pid}|grep -v grep | wc -l`
if [[ ${is_pid_proc_running} -ne 0 ]]
then
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is active."
echo "[ERROR] One Full backup is already in progress with process ${_pid}. Exiting current backup"
exit 1

else
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is NOT active"
echo "Deleting ${_lock_file}"
rm ${_lock_file}
if [ -e ${_lock_file} ]
then
echo "ERROR deleting file ${_lock_file}"
fi
fi
done
fi

# Creating a .lock file to represnt current active full/diff backup.

export file_stamp=`date | sed -e 's/ /_/g'`
PID=`echo $$`
LOCK_FILE=`echo ${RMANBACKUP_MOUNTPOINT}/.RMAN_FULL_lock_${PID}_${file_stamp}`
echo -n > ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[INFO] Lock file created: ${LOCK_FILE}"
else
echo "Error creating lock file: ${LOCK_FILE}"
echo "[ERROR] Backup will now stop"
exit -3
fi


echo "Starting with RMAN backup"
RMANBACKUP_MOUNTPOINT_FULL=$RMANBACKUP_MOUNTPOINT/$SID

#Calling Start RMAN Backup
res_rmanbackup=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/${SID}/full/rmanbackup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res_rmanbackup
exit 1
fi

echo "Response RMAN Backup: ${res_rmanbackup}"

SNAPSHOT_NAME=`echo $res_rmanbackup|/usr/xpg4/bin/awk -F "snap_name" '{print $2}'|cut -d '"' -f3`
if [ -z "$SNAPSHOT_NAME" ];
then
echo "Failed to get Snapshot name. Exiting. Please check Export Service Logs in PBS"
exit 1
fi

echo "Snapshot to be created ${SNAPSHOT_NAME}"

echo -n >$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'

RMAN_LOGFILE=$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'
echo "RMAN Logfile: ${RMAN_LOGFILE}"
rman log=$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log' 2> /dev/null << EOF

connect target /
set echo on;

configure backup optimization on;
configure controlfile autobackup on;
configure device type disk parallelism $PARALLELISM BACKUP TYPE TO COPY;
configure datafile backup copies for device type disk to 1;
configure archivelog backup copies for device type disk to 1;
configure channel device type disk format '$RMANBACKUP_MOUNTPOINT_FULL/full/datafile_%U.bkp';
configure controlfile autobackup format for device type disk to '$RMANBACKUP_MOUNTPOINT_FULL/full/full_controlfile_%d_%F';

run
{
sql 'alter system archive log current';
backup incremental level 1 for recover of copy with tag 'phoenix_oracle_backup' database;
recover copy of database with tag 'phoenix_oracle_backup';
sql 'alter system archive log current';
backup as backupset format '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/%d_%h_%e_%s_%t.arc' archivelog all not backed up;
#Force is to ignore I/O errors
delete noprompt obsolete device type disk;
delete force NOPROMPT expired copy;
delete force NOPROMPT expired backup;

crosscheck backup;
crosscheck copy;
}

configure backup optimization clear;
configure controlfile autobackup clear;

exit

EOF

RMAN_EXIT_STATUS=$?
if [ $RMAN_EXIT_STATUS -ne 0 ];
then
echo ""
echo "rman failed with status $RMAN_EXIT_STATUS.. exiting"
rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

echo ""

echo "Notifying Phoenix to upload RMAN Logs"

rman_uploadlog_res=$(curl -X POST -H "Content-Type: multipart/form-data" -F "file=@$LOG_FILE_DIR/rman_full_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log" -F mountpoint=$RMANBACKUP_MOUNTPOINT -F platform=linux http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/uploadlog 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to send RMAN Logs failed..."
echo "Response from Phoenix Backup Store: "$rman_uploadlog_res
fi


rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi

echo "Notifying Phoenix to end backup"
final_res=$(curl -X PUT http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)

if [ $? -ne 0 ];
then
echo "Request to end phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$final_res

rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

ERROR_CODE=$(echo $final_res|/usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$final_res
echo "Request to start Phoenix backup failed... exiting"
fi
echo $final_res

echo "Exiting with successful status"
}

# Main
full_backup

oracle_rman_archivelog_backup_Solaris.sh

Use this script for Enterprise Workloads agent version 7.0.2-1003652 or later.

#!/bin/bash

if [ "$#" -ne 2 ]; then
echo ""
echo "Usage: $0 <backup_store_IP> <backup_mount_name>"
echo ""
echo " <backup_store_IP> : IP address of the Phoenix Backup Store"
echo " <backup_mount_name> : Name of the backup mount configured in Phoenix, e.g. mount1"
exit 1
fi

BACKUP_STORE_IP=$1
BACKUP_MOUNT=$2

PARALLELISM=1

if [[ -z "${ORACLE_HOME}" ]];
then
echo "Environment variable ORACLE_HOME not set... exiting"
exit 1
fi

if [[ -z "${ORACLE_SID}" ]];
then
echo "Environment variable ORACLE_SID not set... exiting"
exit 1
fi

SID=${ORACLE_SID}

# --- ENHANCED FAILURE NOTIFICATION TRAP ---
export RMAN_SCRIPT_STAGE="Initialization"
export RMAN_SCRIPT_ERROR_MSG="Unexpected termination during initialization"
export RMAN_SCRIPT_RESOLUTION_MSG="Check export service logs or contact Druva Support"

rman_script_failure_notify() {
local ec="${1:-1}"

# Only fire the alert if the exit code is strictly greater than 0
[ "$ec" -eq 0 ] && return 0

local stage="${RMAN_SCRIPT_STAGE}"
local sid="${ORACLE_SID}"
local err_msg="${RMAN_SCRIPT_ERROR_MSG}"
local resolution_msg="${RMAN_SCRIPT_RESOLUTION_MSG}"

# Escape internal double quotes and newlines to prevent JSON payload corruption
local stage_escaped="${stage//\"/\\\"}"
local sid_escaped="${sid//\"/\\\"}"
local err_msg_escaped="${err_msg//\"/\\\"}"
err_msg_escaped="${err_msg_escaped//$'\n'/ }" # Replace newlines with spaces
local resolution_msg_escaped="${resolution_msg//\"/\\\"}"
resolution_msg_escaped="${resolution_msg_escaped//$'\n'/ }" # Replace newlines with spaces

# Construct JSON payload natively using printf
local body
body=$(printf '{"exit_code":%d,"failure_stage":"%s","db_sid":"%s","error_msg":"%s","resolution_msg":"%s"}' \
"$ec" "$stage_escaped" "$sid_escaped" "$err_msg_escaped" "$resolution_msg_escaped")

# Network-hardened API call with a 30-second maximum timeout ceiling
curl -sS --max-time 30 -X POST "http://${BACKUP_STORE_IP}:9090/druva-phoenix/v1/mounts/${BACKUP_MOUNT}/rmanbackup/failure-alert" \
-H "Content-Type: application/json" \
-d "$body" >/dev/null 2>&1 || true
}

# Register trap to catch any exit and pass the true exit code
trap 'rman_script_failure_notify $?' EXIT
# ------------------------------------------

export RMAN_SCRIPT_STAGE="Validate Backup Request"
echo "Validating backup request"

validate_resp=$(curl -X GET http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/1.2/backup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Backup validation request failed with response: $validate_resp"
echo "Backup validation request failed with response: $validate_resp... exiting"
exit 1
fi

VALIDATE_ERROR_CODE=$(echo "$validate_resp" | /usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$VALIDATE_ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Backup validation failed (error_code: ${VALIDATE_ERROR_CODE})"
echo "Backup validation request failed... exiting"
exit 1
fi

# Sample output format
# {"error_code":0,"error_msg":"","result":{"is_reached_max_snapshots":false,"mount_name":"m2"}}
IS_REACHED_MAX_SNAPSHOTS=$(echo "$validate_resp" | /usr/xpg4/bin/awk -F "is_reached_max_snapshots" '{print $2}' | cut -d ',' -f1 | cut -d ':' -f2)
if [ "$IS_REACHED_MAX_SNAPSHOTS" = "false" ];
then
echo "Validation for phoenix backup succeeded"
else
export RMAN_SCRIPT_ERROR_MSG="Backup mount reached max snapshot limit"
export RMAN_SCRIPT_RESOLUTION_MSG="Increase max snapshots limit or wait for pending uploads"
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Validation for phoenix backup failed... exiting"
exit 1
fi

export RMAN_SCRIPT_STAGE="Start Phoenix Backup"
echo "Notifying Phoenix to start backup - Phoenix Backup Store=$BACKUP_STORE_IP mount name=$BACKUP_MOUNT"

res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to start Phoenix Backup session"
echo "Request to start Phoenix Backup failed with response: $res... exiting"
exit 1
fi

# Sample output format
# {"error_code":4295622665,"error_msg":"Backup mount does not exist on Export Service.","result":{"mount_name":"mount4","mount_path":""}}
ERROR_CODE=$(echo "$res" | /usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Phoenix Backup init failed (error_code: ${ERROR_CODE})"
echo "Request to start Phoenix Backup failed with response: $res... exiting"
exit 1
fi

export RMAN_SCRIPT_STAGE="Mount Phoenix Backup Store"
REMOTE_MOUNTPOINT=$BACKUP_STORE_IP:$(echo "$res" | /usr/xpg4/bin/awk -F "mount_path" '{print $2}' | cut -d '"' -f3)
RMANBACKUP_MOUNTPOINT=$(grep "^$REMOTE_MOUNTPOINT" /etc/vfstab | sed 's/\s\+/ /g' | cut -d ' ' -f3)

if [ -z "$RMANBACKUP_MOUNTPOINT" ];
then
export RMAN_SCRIPT_ERROR_MSG="Mount entry missing from /etc/vfstab"
export RMAN_SCRIPT_RESOLUTION_MSG="Add mount entry to /etc/vfstab"
echo "Entry for Phoenix Backup Store mount not found in /etc/vfstab... exiting"
exit 1
fi

ACTUAL_MOUNTPOINT=$(mount | grep -w "$REMOTE_MOUNTPOINT" | cut -d" " -f1 | head -1 | sed 's/\s\+/ /g' 2> /dev/null)
if [ -z "$ACTUAL_MOUNTPOINT" ];
then
mount "$RMANBACKUP_MOUNTPOINT" 2> /dev/null
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to mount backup store"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify mount entry in /etc/vfstab"
echo "Unable to mount $RMANBACKUP_MOUNTPOINT... exiting"
exit 1
fi
else
RMANBACKUP_MOUNTPOINT=$ACTUAL_MOUNTPOINT
fi

export PATH=$ORACLE_HOME/bin:$PATH
arch_backup () {

export RMAN_SCRIPT_STAGE="Create Archivelogs Backup Directory"
if [ ! -e "$RMANBACKUP_MOUNTPOINT/$SID/archivelogs" ]
then
mkdir -p "$RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
if [ $? -eq 0 ];
then
echo "Created directory for archivelogs backup $RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create archivelogs directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "Oracle user does not have permission for $RMANBACKUP_MOUNTPOINT/$SID directory... exiting"
exit 1
fi
elif [ ! -d "$RMANBACKUP_MOUNTPOINT/$SID/archivelogs" ];
then
export RMAN_SCRIPT_ERROR_MSG="Path conflict: archivelogs path is a file, expected directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Remove conflicting file and retry"
echo "$RMANBACKUP_MOUNTPOINT/$SID is not a directory... exiting"
exit 1
fi

LOG_FILE_DIR=$RMANBACKUP_MOUNTPOINT/'_workspace/RMAN_Logs'
echo "Creating Log File Dir: =$RMANBACKUP_MOUNTPOINT'/_workspace/RMAN_Logs'"

if [ ! -e "$LOG_FILE_DIR" ]
then
mkdir -p "$LOG_FILE_DIR"
if [ $? -eq 0 ];
then
echo "Created log directory for oracle backup $LOG_FILE_DIR"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create RMAN log directory"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "Oracle user does not have permission for $LOG_FILE_DIR directory... exiting"
exit 1
fi
fi

echo -n > "$LOG_FILE_DIR/archivelogs_backup.log"
touch "$RMANBACKUP_MOUNTPOINT/_workspace/" 2>/dev/null
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to write to workspace folder"
export RMAN_SCRIPT_RESOLUTION_MSG="Check directory permissions and writability"
echo "$RMANBACKUP_MOUNTPOINT directory is not writable.. exiting"
exit 1
fi

#Checking if any .lock file is present and deleting the same if the PID is NOT running.
echo "Checking for backup lock file"
export RMAN_SCRIPT_STAGE="Check for Backup Lock File"
export BKP_CONTINUE=0
is_lock_file_present=$(find "${RMANBACKUP_MOUNTPOINT}" -type f -name ".RMAN_FULL_lock_*" | wc -l)
if [[ ${is_lock_file_present} -ne 0 ]]
then
for _lock_file in $(find "${RMANBACKUP_MOUNTPOINT}" -type f -name ".RMAN_FULL_lock_*" | xargs)
do
_pid=$(echo "${_lock_file}" | cut -d"_" -f4)
is_pid_proc_running=$(ps -ef | grep "${_pid}" | grep -v grep | wc -l)
if [[ ${is_pid_proc_running} -ne 0 ]]
then
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is active"
export BKP_CONTINUE=1
else
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is NOT active"
echo "Deleting ${_lock_file}"
rm "${_lock_file}"
if [ -e "${_lock_file}" ]
then
echo "ERROR deleting file ${_lock_file}"
echo "Exiting Log backup"
export BKP_CONTINUE=1
fi
fi
done

if [[ ${BKP_CONTINUE} -eq 1 ]]
then
export RMAN_SCRIPT_ERROR_MSG="Skipping backup: active RMAN backup or lock file present"
export RMAN_SCRIPT_RESOLUTION_MSG="Wait for active backup to finish or remove stale lock file"
echo "Skipping backup: active RMAN backup or lock file present... exiting"
exit 1
fi
fi

export file_stamp=$(date | sed -e 's/ /_/g')
PID=$$
LOCK_FILE="${RMANBACKUP_MOUNTPOINT}/.RMAN_BACKUP_lock_${PID}_${file_stamp}"
echo -n > "${LOCK_FILE}"
if [ -e "${LOCK_FILE}" ]
then
echo "[INFO] Lock file created: ${LOCK_FILE}"
else
export RMAN_SCRIPT_ERROR_MSG="Failed to create backup lock file"
export RMAN_SCRIPT_RESOLUTION_MSG="Check backup mount disk space and permissions"
echo "Error creating lock file: ${LOCK_FILE}"
echo "[ERROR] Backup will now stop"
exit 1
fi

echo "Starting with RMAN backup"
RMANBACKUP_MOUNTPOINT_FULL=$RMANBACKUP_MOUNTPOINT/$SID

export RMAN_SCRIPT_STAGE="Request RMAN Snapshot for Archivelog Backup"
res_rmanbackup=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/${SID}/archivelog/rmanbackup 2> /dev/null)
if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to request RMAN snapshot"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify backup mount configuration"
echo "Request to start Phoenix Backup failed with response: $res_rmanbackup... exiting"
exit 1
fi

echo "Response RMAN Backup: ${res_rmanbackup}"

SNAPSHOT_NAME=$(echo "$res_rmanbackup" | /usr/xpg4/bin/awk -F "snap_name" '{print $2}' | cut -d '"' -f3)
if [ -z "$SNAPSHOT_NAME" ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to get snapshot name"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify backup mount configuration"
echo "Failed to get Snapshot name... exiting with response: $res_rmanbackup"
exit 1
fi

echo "Snapshot to be created ${SNAPSHOT_NAME}"

export RMAN_SCRIPT_STAGE="Run RMAN Backup"
RMAN_LOGFILE=$LOG_FILE_DIR'/rman_archivelog_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'
echo -n > "$RMAN_LOGFILE"
echo "RMAN Logfile: ${RMAN_LOGFILE}"

rman log="$RMAN_LOGFILE" 2> /dev/null << EOF
connect target /
set echo on;

configure backup optimization on;
configure controlfile autobackup on;
configure device type disk parallelism ${PARALLELISM} BACKUP TYPE TO COPY;
configure datafile backup copies for device type disk to 1;
configure archivelog backup copies for device type disk to 1;
configure controlfile autobackup format for device type disk to '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/arch_controlfile_%d_%F.bkp';

run
{
sql 'alter system archive log current';
backup as backupset format '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/%d_%h_%e_%s_%t.arc' archivelog all not backed up;

#Force is to ignore I/O errors
delete noprompt obsolete device type disk;
delete force NOPROMPT expired copy;
delete force NOPROMPT expired backup;

crosscheck backup;
crosscheck copy;
}

configure backup optimization clear;
configure controlfile autobackup clear;

exit

EOF

RMAN_EXIT_STATUS=$?
if [ $RMAN_EXIT_STATUS -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="RMAN backup failed (exit_code: ${RMAN_EXIT_STATUS})"
export RMAN_SCRIPT_RESOLUTION_MSG="Check RMAN logs and fix the issue"
echo ""
echo "rman failed with status $RMAN_EXIT_STATUS.. exiting"
rm "${LOCK_FILE}"
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

export RMAN_SCRIPT_STAGE="Upload RMAN Logs"
echo "Notifying Phoenix to upload RMAN Logs"

rman_uploadlog_res=$(curl -X POST -H "Content-Type: multipart/form-data" -F "file=@$LOG_FILE_DIR/rman_archivelog_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log" -F mountpoint=$RMANBACKUP_MOUNTPOINT -F platform=linux http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/uploadlog 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to send RMAN Logs failed..."
echo "Response from Phoenix Backup Store: "$rman_uploadlog_res
fi

export RMAN_SCRIPT_STAGE="End Backup"
echo "Notifying Phoenix to end backup"
final_res=$(curl -X PUT http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)

if [ $? -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to end Phoenix Backup with response: $final_res"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify export service is reachable and check its logs"
echo "Request to end Phoenix Backup failed with response: $final_res... exiting"
rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

ERROR_CODE=$(echo "$final_res" | /usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2 | cut -d ',' -f1)
if [ "$ERROR_CODE" -ne 0 ];
then
export RMAN_SCRIPT_ERROR_MSG="Failed to end Phoenix Backup (error_code: ${ERROR_CODE})"
export RMAN_SCRIPT_RESOLUTION_MSG="Verify export service is reachable and check its logs"
echo "Response from Phoenix Backup Store: "$final_res
echo "Request to start Phoenix backup failed... exiting"
exit 1
fi
echo "$final_res"

echo "Exiting with successful status"
}

# Main
arch_backup

Use this script for Enterprise Workloads agent version 7.0.2-985623 or earlier.

#!/bin/bash

if [ "$#" -ne 2 ]; then
echo ""
echo "Usage: $0 <backup_store_IP> <backup_mount_name>"
echo ""
echo " <backup_store_IP> : IP address of the Phoenix Backup Store"
echo " <backup_mount_name> : Name of the backup mount configured in Phoenix, e.g. mount1"
exit 1
fi

BACKUP_STORE_IP=$1
BACKUP_MOUNT=$2

PARALLELISM=1

if [[ -z "${ORACLE_HOME}" ]];
then
echo "Environment variable ORACLE_HOME not set... exiting"
exit 1
fi

if [[ -z "${ORACLE_SID}" ]];
then
echo "Environment variable ORACLE_SID not set... exiting"
exit 1
fi

SID=${ORACLE_SID}

echo "Validating backup request"
validate_resp=$(curl -X GET http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/1.2/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to validate phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$validate_resp
exit 1
fi

VALIDATE_ERROR_CODE=$(echo $validate_resp|/usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $VALIDATE_ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Request to validate Phoenix backup failed... exiting"
exit 1
fi

# Sample output format
# {"error_code":0,"error_msg":"","result":{"is_reached_max_snapshots":false,"mount_name":"m2"}}
IS_REACHED_MAX_SNAPSHOTS=$(echo $validate_resp|/usr/xpg4/bin/awk -F "is_reached_max_snapshots" '{print $2}'|cut -d ',' -f1 |cut -d ':' -f2)
if [ $IS_REACHED_MAX_SNAPSHOTS == "false" ];
then
echo "Validation for phoenix backup succeeded"
else
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Validation for phoenix backup failed... exiting"
exit 1
fi

echo "Notifying Phoenix to start backup - Phoenix Backup Store=$BACKUP_STORE_IP mount name=$BACKUP_MOUNT"

res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res
exit 1
fi

# Sample output format
# {"error_code":4295622665,"error_msg":"Backup mount does not exist on Export Service.","result":{"mount_name":"mount4","mount_path":""}}
ERROR_CODE=$(echo $res|/usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)

if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$res
echo "Request to start Phoenix backup failed... exiting"
exit 1
fi

REMOTE_MOUNTPOINT=$BACKUP_STORE_IP:$(echo $res|/usr/xpg4/bin/awk -F "mount_path" '{print $2}'|cut -d '"' -f3)
RMANBACKUP_MOUNTPOINT=$(grep "^$REMOTE_MOUNTPOINT" /etc/vfstab| sed 's/\s\+/ /g' |cut -d ' ' -f3)

if [ -z "$RMANBACKUP_MOUNTPOINT" ];
then
echo "Entry for Phoenix Backup Store mount not found in /etc/vfstab... exiting"
exit 1
fi

ACTUAL_MOUNTPOINT=$(mount|grep -w "$REMOTE_MOUNTPOINT"| cut -d" " -f1 |head -1|sed 's/\s\+/ /g' 2>/dev/null)

if [ -z "$ACTUAL_MOUNTPOINT" ];
then
mount $RMANBACKUP_MOUNTPOINT 2> /dev/null
if [ $? -ne 0 ];
then
echo "Unable to mount $RMANBACKUP_MOUNTPOINT... exiting"
exit 1
fi
else
RMANBACKUP_MOUNTPOINT=$ACTUAL_MOUNTPOINT
fi

export PATH=$ORACLE_HOME/bin:$PATH
arch_backup () {

if [ ! -e $RMANBACKUP_MOUNTPOINT/$SID'/archivelogs' ]
then
mkdir -p $RMANBACKUP_MOUNTPOINT/$SID'/archivelogs'
if [ $? -eq 0 ];
then
echo "Created directory for archivelogs backup $RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
else
echo "Oracle user does not have permission for $RMANBACKUP_MOUNTPOINT/$SID directory... exiting"
exit 1
fi
elif [ ! -d $RMANBACKUP_MOUNTPOINT/$SID'/archivelogs' ];
then
echo "$RMANBACKUP_MOUNTPOINT/$SID is not a directory... exiting"
fi

LOG_FILE_DIR=$RMANBACKUP_MOUNTPOINT/'_workspace/RMAN_Logs'
echo "Creating Log File Dir: =$RMANBACKUP_MOUNTPOINT'/_workspace/RMAN_Logs'"

if [ ! -e $LOG_FILE_DIR ]
then
mkdir -p $LOG_FILE_DIR
if [ $? -eq 0 ];
then
echo "Created log directory for oracle backup $LOG_FILE_DIR"
else
echo "Oracle user does not have permission for $LOG_FILE_DIR directory... exiting"
exit 1
fi
fi

echo -n >$LOG_FILE_DIR'/archivelogs_backup_${ORACLE_SID}.log'
touch $RMANBACKUP_MOUNTPOINT/_workspace/
if [ $? -ne 0 ];
then
echo "$RMANBACKUP_MOUNTPOINT directory is not writable.. exiting"
exit 1
fi


# Checking if any of the Full/Diff backup is currently running and PID is active.
# In this case, we will fail/skip the current Log backup.
# Next trigger (external) of this script will retry log backup.

#LOCK_FILE=`echo ${RMANBACKUP_MOUNTPOINT}/.RMAN_FULL_lock_${PID}_${file_stamp}`

is_lock_file_present=`find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_FULL_lock_*"|wc -l `
export BKP_CONTINUE=0
if [[ ${is_lock_file_present} -ne 0 ]]
then
for _lock_file in `find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_FULL_lock_*" | xargs `
do
_pid=`echo ${_lock_file}|cut -d"_" -f4`
is_pid_proc_running=`ps -ef|grep ${_pid}|grep -v grep | wc -l`
if [[ ${is_pid_proc_running} -ne 0 ]]
then
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is active"
export BKP_CONTINUE=1
else
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is NOT active"
echo "Deleting ${_lock_file}"
rm ${_lock_file}
if [ -e ${_lock_file} ]
then
echo "ERROR deleting file ${_lock_file}"
echo "Exiting Log backup"
export BKP_CONTINUE=1
fi
fi
done

if [[ ${BKP_CONTINUE} -eq 1 ]]
then
echo "[WARNING] There is full backup running or the lock file for Full/diff backup is present"
echo "[ERROR] Exiting the current Log backup"
exit 5
fi
fi

echo "Starting with RMAN backup"
RMANBACKUP_MOUNTPOINT_FULL=$RMANBACKUP_MOUNTPOINT/$SID

#Calling Start RMAN Backup
res_rmanbackup=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/${SID}/archivelog/rmanbackup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res_rmanbackup
exit 1
fi

echo "Response RMAN Backup: ${res_rmanbackup}"

SNAPSHOT_NAME=`echo $res_rmanbackup|/usr/xpg4/bin/awk -F "snap_name" '{print $2}'|cut -d '"' -f3`
if [ -z "$SNAPSHOT_NAME" ];
then
echo "Failed to get Snapshot name. Exiting. Please check Export Service Logs in PBS"
exit 1
fi

echo "Snapshot to be created ${SNAPSHOT_NAME}"

echo -n >$LOG_FILE_DIR'/rman_archivelog_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'

RMAN_LOGFILE=$LOG_FILE_DIR'/rman_archivelog_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'
echo "RMAN Logfile: ${RMAN_LOGFILE}"

rman log=$LOG_FILE_DIR'/rman_archivelog_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log' 2> /dev/null << EOF

connect target /
set echo on;

configure backup optimization on;
configure controlfile autobackup on;
configure device type disk parallelism ${PARALLELISM} BACKUP TYPE TO COPY;
configure datafile backup copies for device type disk to 1;
configure archivelog backup copies for device type disk to 1;
configure controlfile autobackup format for device type disk to '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/arch_controlfile_%d_%F.bkp';

run
{
sql 'alter system archive log current';
backup as backupset format '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/%d_%h_%e_%s_%t.arc' archivelog all not backed up;

#Force is to ignore I/O errors
delete noprompt obsolete device type disk;
delete force NOPROMPT expired copy;
delete force NOPROMPT expired backup;

crosscheck backup;
crosscheck copy;
}

configure backup optimization clear;
configure controlfile autobackup clear;

exit

EOF

RMAN_EXIT_STATUS=$?
if [ $RMAN_EXIT_STATUS -ne 0 ];
then
echo ""
echo "rman failed with status $RMAN_EXIT_STATUS.. exiting"
exit 1
fi

echo ""

echo "Notifying Phoenix to upload RMAN Logs"

rman_uploadlog_res=$(curl -X POST -H "Content-Type: multipart/form-data" -F "file=@$LOG_FILE_DIR/rman_archivelog_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log" -F mountpoint=$RMANBACKUP_MOUNTPOINT -F platform=linux http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/uploadlog 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to send RMAN Logs failed..."
echo "Response from Phoenix Backup Store: "$rman_uploadlog_res
fi

echo "Notifying Phoenix to end backup"
final_res=$(curl -X PUT http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)

if [ $? -ne 0 ];
then
echo "Request to end phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$final_res
exit 1
fi
ERROR_CODE=$(echo $final_res|/usr/xpg4/bin/awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$final_res
echo "Request to start Phoenix backup failed... exiting"
fi
echo $final_res

echo "Exiting with successful status"
}

# Main
arch_backup

oracle_rman_data_full_merge_weekly_backup.sh

Click here to view script

#!/bin/bash

if [ "$#" -ne 2 ]; then
echo ""
echo "Usage: $0 <backup_store_IP> <backup_mount_name>"
echo ""
echo " <backup_store_IP> : IP address of the Phoenix Backup Store"
echo " <backup_mount_name> : Name of the backup mount configured in Phoenix, e.g. mount1"

exit 1
fi

BACKUP_STORE_IP=$1
BACKUP_MOUNT=$2

PARALLELISM=1

if [[ -z "${ORACLE_HOME}" ]];
then
echo "Environment variable ORACLE_HOME not set... exiting"
exit 1
fi

if [[ -z "${ORACLE_SID}" ]];
then
echo "Environment variable ORACLE_SID not set... exiting"
exit 1
fi
SID=${ORACLE_SID}

echo "Validating backup request"
validate_resp=$(curl -X GET http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/1.2/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to validate phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$validate_resp
exit 1
fi

VALIDATE_ERROR_CODE=$(echo $validate_resp|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $VALIDATE_ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Request to validate Phoenix backup failed... exiting"
exit 1
fi

# Sample output format
# {"error_code":0,"error_msg":"","result":{"is_reached_max_snapshots":false,"mount_name":"m2"}}
IS_REACHED_MAX_SNAPSHOTS=$(echo $validate_resp|awk -F "is_reached_max_snapshots" '{print $2}'|cut -d ',' -f1 |cut -d ':' -f2)
if [ $IS_REACHED_MAX_SNAPSHOTS == "false" ];
then
echo "Validation for phoenix backup succeeded"
else
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Validation for phoenix backup failed... exiting"
exit 1
fi

echo "Notifying Phoenix to start backup - Phoenix Backup Store=$BACKUP_STORE_IP mount name=$BACKUP_MOUNT"

#res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/$SID/full/backup 2> /dev/null)
res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res
exit 1
fi

# Sample output format
# {"error_code":4295622665,"error_msg":"Backup mount does not exist on Export Service.","result":{"mount_name":"mount4","mount_path":""}}
ERROR_CODE=$(echo $res|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)

if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$res
echo "Request to start Phoenix backup failed... exiting"
exit 1
fi


REMOTE_MOUNTPOINT=$BACKUP_STORE_IP:$(echo $res|awk -F "mount_path" '{print $2}'|cut -d '"' -f3)
RMANBACKUP_MOUNTPOINT=$(grep "^$REMOTE_MOUNTPOINT" /etc/fstab| sed 's/\s\+/ /g' |cut -d ' ' -f2)

if [ -z "$RMANBACKUP_MOUNTPOINT" ];
then
echo "Entry for Phoenix Backup Store mount not found in /etc/fstab... exiting"
exit 1
fi

ACTUAL_MOUNTPOINT=$(mount|grep "^$REMOTE_MOUNTPOINT"|sed 's/\s\+/ /g' |cut -d " " -f3 2> /dev/null)
if [ -z "$ACTUAL_MOUNTPOINT" ];
then
mount $RMANBACKUP_MOUNTPOINT 2> /dev/null
if [ $? -ne 0 ];
then
echo "Unable to mount $RMANBACKUP_MOUNTPOINT... exiting"
exit 1
fi
else
RMANBACKUP_MOUNTPOINT=$ACTUAL_MOUNTPOINT
fi

export PATH=$ORACLE_HOME/bin:$PATH
full_backup () {

echo "Creating Dir $RMANBACKUP_MOUNTPOINT/$SID'/full'"

if [ ! -e $RMANBACKUP_MOUNTPOINT/$SID'/full' ]
then
mkdir -p $RMANBACKUP_MOUNTPOINT/$SID'/full'
if [ $? -eq 0 ];
then
echo "Created directory for full backup $RMANBACKUP_MOUNTPOINT/$SID/full"
else
echo "Oracle user does not have permission for $RMANBACKUP_MOUNTPOINT directory... exiting"
exit 1
fi
elif [ ! -d $RMANBACKUP_MOUNTPOINT/${SID}'/full' ];
then
echo "$RMANBACKUP_MOUNTPOINT is not a directory... exiting"
exit 1
fi

#Creating Archivelog Directory

if [ ! -e $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs' ]
then
mkdir -p $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs'
if [ $? -eq 0 ];
then
echo "Created directory for archivelogs backup $RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
else
echo "Oracle user does not have permission for $RMANBACKUP_MOUNTPOINT directory... exiting"
exit 1
fi

elif [ ! -d $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs' ];
then
echo "$RMANBACKUP_MOUNTPOINT is not a directory... exiting"
exit 1
fi

LOG_FILE_DIR=$RMANBACKUP_MOUNTPOINT/'_workspace/RMAN_Logs'
echo "Creating Log File Dir: =$RMANBACKUP_MOUNTPOINT'/_workspace/RMAN_Logs'"

if [ ! -e $LOG_FILE_DIR ]
then
mkdir -p $LOG_FILE_DIR
if [ $? -eq 0 ];
then
echo "Created log directory for oracle backup $LOG_FILE_DIR"
else
echo "Oracle user does not have permission for $LOG_FILE_DIR directory... exiting"
exit 1
fi
fi

RMANBACKUP_MOUNTPOINT_FULL=$RMANBACKUP_MOUNTPOINT/$SID

#echo -n >$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}'.log'
touch $RMANBACKUP_MOUNTPOINT/_workspace/
if [ $? -ne 0 ];
then
echo "$RMANBACKUP_MOUNTPOINT directory is not writable.. exiting"
exit 1
fi

#Checking if any .lock file is present and deleting the same if the PID is NOT running.

is_lock_file_present=`find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_FULL_lock_*"|wc -l `
if [[ ${is_lock_file_present} -ne 0 ]]
then
for _lock_file in `find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_FULL_lock_*" | xargs `
do
_pid=`echo ${_lock_file}|cut -d"_" -f4`
is_pid_proc_running=`ps -ef|grep ${_pid}|grep -v grep | wc -l`
if [[ ${is_pid_proc_running} -ne 0 ]]
then
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is active"
else
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is NOT active"
echo "Deleting ${_lock_file}"
rm ${_lock_file}
if [ -e ${_lock_file} ]
then
echo "ERROR deleting file ${_lock_file}"
fi
fi
done
fi

# Creating a .lock file to represnt current active full/diff backup.

export file_stamp=`date | sed -e 's/ /_/g'`
PID=`echo $$`
LOCK_FILE=`echo ${RMANBACKUP_MOUNTPOINT}/.RMAN_FULL_lock_${PID}_${file_stamp}`
echo -n > ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[INFO] Lock file created: ${LOCK_FILE}"
else
echo "Error creating lock file: ${LOCK_FILE}"
echo "[ERROR] Backup will now stop"
exit -3
fi


echo "Starting with RMAN backup"

#Calling Start RMAN Backup
res_rmanbackup=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/${SID}/full/rmanbackup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res_rmanbackup
exit 1
fi

echo "Response RMAN Backup: ${res_rmanbackup}"

SNAPSHOT_NAME=`echo $res_rmanbackup|awk -F "snap_name" '{print $2}'|cut -d '"' -f3`
if [ -z "$SNAPSHOT_NAME" ];
then
echo "Failed to get Snapshot name. Exiting. Please check Export Service Logs in PBS"
exit 1
fi

echo "Snapshot to be created ${SNAPSHOT_NAME}"

echo -n >$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'

RMAN_LOGFILE=$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'
echo "RMAN Logfile: ${RMAN_LOGFILE}"
rman log=$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log' 2> /dev/null << EOF


connect target /
set echo on;

configure backup optimization on;
configure controlfile autobackup on;
configure device type disk parallelism $PARALLELISM BACKUP TYPE TO COPY;
configure datafile backup copies for device type disk to 1;
configure archivelog backup copies for device type disk to 1;
configure channel device type disk format '${RMANBACKUP_MOUNTPOINT_FULL}/full/datafile_%U.bkp';
configure controlfile autobackup format for device type disk to '${RMANBACKUP_MOUNTPOINT_FULL}/full/full_controlfile_%d_%F.bkp';

run
{

sql 'alter system archive log current';
recover copy of database with tag 'phoenix_oracle_backup';
backup incremental level 1 for recover of copy with tag 'phoenix_oracle_backup' database;
sql 'alter system archive log current';
backup as backupset format '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/%d_%h_%e_%s_%t.arc' archivelog all not backed up;

#Force is to ignore I/O errors
delete noprompt obsolete device type disk;
delete force NOPROMPT expired copy;
delete force NOPROMPT expired backup;

crosscheck backup;
crosscheck copy;
}

configure backup optimization clear;
configure controlfile autobackup clear;

exit

EOF

RMAN_EXIT_STATUS=$?
if [ $RMAN_EXIT_STATUS -ne 0 ];
then
echo ""
echo "rman failed with status $RMAN_EXIT_STATUS.. exiting"
rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi


echo "RMAN log location: $LOG_FILE_DIR/rman_full_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log"

echo "Notifying Phoenix to upload RMAN Logs"

rman_uploadlog_res=$(curl -X POST -H "Content-Type: multipart/form-data" -F "file=@$LOG_FILE_DIR/rman_full_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log" -F mountpoint=$RMANBACKUP_MOUNTPOINT -F platform=linux http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/uploadlog 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to send RMAN Logs failed..."
echo "Response from Phoenix Backup Store: "$rman_uploadlog_res
fi



rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi

echo "Notifying Phoenix to end backup"
final_res=$(curl -X PUT http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)

if [ $? -ne 0 ];
then
echo "Request to end phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$final_res

rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

ERROR_CODE=$(echo $final_res|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$final_res
echo "Request to End Phoenix backup failed... exiting"
fi
echo $final_res

echo "Exiting with successful status"
}

# Main
full_backup

oracle_rman_data_incremental_daily_backup.sh

Click here to view script

#!/bin/bash

if [ "$#" -ne 2 ]; then
echo ""
echo "Usage: $0 <backup_store_IP> <backup_mount_name>"
echo ""
echo " <backup_store_IP> : IP address of the Phoenix Backup Store"
echo " <backup_mount_name> : Name of the backup mount configured in Phoenix, e.g. mount1"

exit 1
fi

BACKUP_STORE_IP=$1
BACKUP_MOUNT=$2

PARALLELISM=1

if [[ -z "${ORACLE_HOME}" ]];
then
echo "Environment variable ORACLE_HOME not set... exiting"
exit 1
fi

if [[ -z "${ORACLE_SID}" ]];
then
echo "Environment variable ORACLE_SID not set... exiting"
exit 1
fi
SID=${ORACLE_SID}

echo "Validating backup request"
validate_resp=$(curl -X GET http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/1.2/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to validate phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$validate_resp
exit 1
fi

VALIDATE_ERROR_CODE=$(echo $validate_resp|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $VALIDATE_ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Request to validate Phoenix backup failed... exiting"
exit 1
fi

# Sample output format
# {"error_code":0,"error_msg":"","result":{"is_reached_max_snapshots":false,"mount_name":"m2"}}
IS_REACHED_MAX_SNAPSHOTS=$(echo $validate_resp|awk -F "is_reached_max_snapshots" '{print $2}'|cut -d ',' -f1 |cut -d ':' -f2)
if [ $IS_REACHED_MAX_SNAPSHOTS == "false" ];
then
echo "Validation for phoenix backup succeeded"
else
echo "Response from Phoenix Backup Store: "$validate_resp
echo "Validation for phoenix backup failed... exiting"
exit 1
fi

echo "Notifying Phoenix to start backup - Phoenix Backup Store=$BACKUP_STORE_IP mount name=$BACKUP_MOUNT"

#res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/$SID/full/backup 2> /dev/null)
res=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res
exit 1
fi

# Sample output format
# {"error_code":4295622665,"error_msg":"Backup mount does not exist on Export Service.","result":{"mount_name":"mount4","mount_path":""}}
ERROR_CODE=$(echo $res|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)

if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$res
echo "Request to start Phoenix backup failed... exiting"
exit 1
fi


REMOTE_MOUNTPOINT=$BACKUP_STORE_IP:$(echo $res|awk -F "mount_path" '{print $2}'|cut -d '"' -f3)
RMANBACKUP_MOUNTPOINT=$(grep "^$REMOTE_MOUNTPOINT" /etc/fstab| sed 's/\s\+/ /g' |cut -d ' ' -f2)

if [ -z "$RMANBACKUP_MOUNTPOINT" ];
then
echo "Entry for Phoenix Backup Store mount not found in /etc/fstab... exiting"
exit 1
fi

ACTUAL_MOUNTPOINT=$(mount|grep "^$REMOTE_MOUNTPOINT"|sed 's/\s\+/ /g' |cut -d " " -f3 2> /dev/null)
if [ -z "$ACTUAL_MOUNTPOINT" ];
then
mount $RMANBACKUP_MOUNTPOINT 2> /dev/null
if [ $? -ne 0 ];
then
echo "Unable to mount $RMANBACKUP_MOUNTPOINT... exiting"
exit 1
fi
else
RMANBACKUP_MOUNTPOINT=$ACTUAL_MOUNTPOINT
fi

export PATH=$ORACLE_HOME/bin:$PATH
full_backup () {

echo "Creating Dir $RMANBACKUP_MOUNTPOINT/$SID'/full'"

if [ ! -e $RMANBACKUP_MOUNTPOINT/$SID'/full' ]
then
mkdir -p $RMANBACKUP_MOUNTPOINT/$SID'/full'
if [ $? -eq 0 ];
then
echo "Created directory for full backup $RMANBACKUP_MOUNTPOINT/$SID/full"
else
echo "Oracle user does not have permission for $RMANBACKUP_MOUNTPOINT directory... exiting"
exit 1
fi
elif [ ! -d $RMANBACKUP_MOUNTPOINT/${SID}'/full' ];
then
echo "$RMANBACKUP_MOUNTPOINT is not a directory... exiting"
exit 1
fi

#Creating Archivelog Directory

if [ ! -e $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs' ]
then
mkdir -p $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs'
if [ $? -eq 0 ];
then
echo "Created directory for archivelogs backup $RMANBACKUP_MOUNTPOINT/$SID/archivelogs"
else
echo "Oracle user does not have permission for $RMANBACKUP_MOUNTPOINT directory... exiting"
exit 1
fi

elif [ ! -d $RMANBACKUP_MOUNTPOINT/${SID}'/archivelogs' ];
then
echo "$RMANBACKUP_MOUNTPOINT is not a directory... exiting"
exit 1
fi

LOG_FILE_DIR=$RMANBACKUP_MOUNTPOINT/'_workspace/RMAN_Logs'
echo "Creating Log File Dir: =$RMANBACKUP_MOUNTPOINT'/_workspace/RMAN_Logs'"

if [ ! -e $LOG_FILE_DIR ]
then
mkdir -p $LOG_FILE_DIR
if [ $? -eq 0 ];
then
echo "Created log directory for oracle backup $LOG_FILE_DIR"
else
echo "Oracle user does not have permission for $LOG_FILE_DIR directory... exiting"
exit 1
fi
fi

RMANBACKUP_MOUNTPOINT_FULL=$RMANBACKUP_MOUNTPOINT/$SID

#echo -n >$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}'.log'
touch $RMANBACKUP_MOUNTPOINT/_workspace/
if [ $? -ne 0 ];
then
echo "$RMANBACKUP_MOUNTPOINT directory is not writable.. exiting"
exit 1
fi

#Checking if any .lock file is present and deleting the same if the PID is NOT running.

is_lock_file_present=`find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_FULL_lock_*"|wc -l `
if [[ ${is_lock_file_present} -ne 0 ]]
then
for _lock_file in `find ${RMANBACKUP_MOUNTPOINT} -type f -name ".RMAN_FULL_lock_*" | xargs `
do
_pid=`echo ${_lock_file}|cut -d"_" -f4`
is_pid_proc_running=`ps -ef|grep ${_pid}|grep -v grep | wc -l`
if [[ ${is_pid_proc_running} -ne 0 ]]
then
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is active"
else
echo "[INFO] Full backup Lock File: ${_lock_file} is present and PID is NOT active"
echo "Deleting ${_lock_file}"
rm ${_lock_file}
if [ -e ${_lock_file} ]
then
echo "ERROR deleting file ${_lock_file}"
fi
fi
done
fi

# Creating a .lock file to represnt current active full/diff backup.

export file_stamp=`date | sed -e 's/ /_/g'`
PID=`echo $$`
LOCK_FILE=`echo ${RMANBACKUP_MOUNTPOINT}/.RMAN_FULL_lock_${PID}_${file_stamp}`
echo -n > ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[INFO] Lock file created: ${LOCK_FILE}"
else
echo "Error creating lock file: ${LOCK_FILE}"
echo "[ERROR] Backup will now stop"
exit -3
fi


echo "Starting with RMAN backup"

#Calling Start RMAN Backup
res_rmanbackup=$(curl -X POST http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/${SID}/full/rmanbackup 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to start phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$res_rmanbackup
exit 1
fi

echo "Response RMAN Backup: ${res_rmanbackup}"

SNAPSHOT_NAME=`echo $res_rmanbackup|awk -F "snap_name" '{print $2}'|cut -d '"' -f3`
if [ -z "$SNAPSHOT_NAME" ];
then
echo "Failed to get Snapshot name. Exiting. Please check Export Service Logs in PBS"
exit 1
fi

echo "Snapshot to be created ${SNAPSHOT_NAME}"

echo -n >$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'

RMAN_LOGFILE=$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log'
echo "RMAN Logfile: ${RMAN_LOGFILE}"
rman log=$LOG_FILE_DIR'/rman_full_backup_'${SNAPSHOT_NAME}_${ORACLE_SID}'.log' 2> /dev/null << EOF


connect target /
set echo on;

configure backup optimization on;
configure controlfile autobackup on;
configure device type disk parallelism $PARALLELISM BACKUP TYPE TO COPY;
configure datafile backup copies for device type disk to 1;
configure archivelog backup copies for device type disk to 1;
configure channel device type disk format '${RMANBACKUP_MOUNTPOINT_FULL}/full/datafile_%U.bkp';
configure controlfile autobackup format for device type disk to '${RMANBACKUP_MOUNTPOINT_FULL}/full/full_controlfile_%d_%F.bkp';

run
{

sql 'alter system archive log current';
backup incremental level 1 for recover of copy with tag 'phoenix_oracle_backup' database;
sql 'alter system archive log current';
backup as backupset format '${RMANBACKUP_MOUNTPOINT_FULL}/archivelogs/%d_%h_%e_%s_%t.arc' archivelog all not backed up;

#Force is to ignore I/O errors
delete noprompt obsolete device type disk;
delete force NOPROMPT expired copy;
delete force NOPROMPT expired backup;

crosscheck backup;
crosscheck copy;
}

configure backup optimization clear;
configure controlfile autobackup clear;

exit

EOF

RMAN_EXIT_STATUS=$?
if [ $RMAN_EXIT_STATUS -ne 0 ];
then
echo ""
echo "rman failed with status $RMAN_EXIT_STATUS.. exiting"
rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi


echo "RMAN log location: $LOG_FILE_DIR/rman_full_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log"

echo "Notifying Phoenix to upload RMAN Logs"

rman_uploadlog_res=$(curl -X POST -H "Content-Type: multipart/form-data" -F "file=@$LOG_FILE_DIR/rman_full_backup_${SNAPSHOT_NAME}_${ORACLE_SID}.log" -F mountpoint=$RMANBACKUP_MOUNTPOINT -F platform=linux http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/uploadlog 2> /dev/null)
if [ $? -ne 0 ];
then
echo "Request to send RMAN Logs failed..."
echo "Response from Phoenix Backup Store: "$rman_uploadlog_res
fi



rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi

echo "Notifying Phoenix to end backup"
final_res=$(curl -X PUT http://$BACKUP_STORE_IP:9090/druva-phoenix/v1/mounts/$BACKUP_MOUNT/backup 2> /dev/null)

if [ $? -ne 0 ];
then
echo "Request to end phoenix backup failed... exiting"
echo "Response from Phoenix Backup Store: "$final_res

rm ${LOCK_FILE}
if [ -e ${LOCK_FILE} ]
then
echo "[ERROR] Could NOT delete Lock file: ${LOCK_FILE}"
else
dt=`date | sed -e 's/ /_/g'`
echo "[INFO] Lock file deleted: ${LOCK_FILE} at ${dt} "
fi
exit 1
fi

ERROR_CODE=$(echo $final_res|awk -F "error_code" '{print $2}' | cut -d ':' -f2|cut -d ',' -f1)
if [ $ERROR_CODE -ne 0 ];
then
echo "Response from Phoenix Backup Store: "$final_res
echo "Request to End Phoenix backup failed... exiting"
fi
echo $final_res

echo "Exiting with successful status"
}

# Main
full_backup

Did this answer your question?