A clean, reproducible setup: write nightly RMAN backups to the Fast Recovery Area (FRA), then sync them to /backup/rman
, scheduled via DBMS_SCHEDULER. Includes copy‑paste scripts, scheduler jobs, and troubleshooting.
/backup/rman
for a second on‑disk copy.# Directories & ownerships (adjust as needed)
sudo mkdir -p /u03/fra /backup/rman /u01/app/oracle/admin/log /u01/app/oracle/admin/backup
sudo chown -R oracle:oinstall /u03/fra /backup/rman /u01/app/oracle/admin
sudo chmod 750 /backup/rman
-- As SYSDBA in SQL*Plus
SHOW PARAMETER db_recovery_file_dest;
SHOW PARAMETER db_recovery_file_dest_size;
Clear hardcoded FORMATs so backups land in the FRA; set sane retention and controls.
sudo -iu oracle bash -lc "cat > /u01/app/oracle/admin/backup/rman_config.rman <<'RMAN'
CONFIGURE CHANNEL DEVICE TYPE DISK CLEAR;
CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;
CONFIGURE CONTROLFILE AUTOBACKUP ON;
CONFIGURE ARCHIVELOG DELETION POLICY TO BACKED UP 1 TIMES TO DEVICE TYPE DISK;
CONFIGURE BACKUP OPTIMIZATION ON;
SHOW ALL;
RMAN
rman target / cmdfile=/u01/app/oracle/admin/backup/rman_config.rman \
log=/u01/app/oracle/admin/log/rman_config_$(date +%F).log"
rman_backup.sh
)sudo -iu oracle bash -lc "cat > /u01/app/oracle/admin/backup/rman_backup.sh <<'BASH'
#!/bin/bash
set -euo pipefail
export ORACLE_SID=${ORACLE_SID:-ORCL}
export ORACLE_HOME=/u01/app/oracle/product/19c/dbhome_1
export LD_LIBRARY_PATH=$ORACLE_HOME/lib
export PATH=$ORACLE_HOME/bin:/bin:/usr/bin:$PATH
LOG_DIR=/u01/app/oracle/admin/log
mkdir -p "$LOG_DIR"
STAMP=$(date +%F_%H%M%S)
LOG="$LOG_DIR/rman_backup_$STAMP.log"
FRA=/u03/fra
[[ -d "$FRA" ]] || { echo "FATAL: FRA $FRA missing" | tee -a "$LOG"; exit 1; }
DOW=$(date +%u) # 1=Mon ... 7=Sun
if [[ "$DOW" == "7" ]]; then
LEVEL_CMD="INCREMENTAL LEVEL 0"
TAG="WEEKLY_L0"
else
LEVEL_CMD="INCREMENTAL LEVEL 1 CUMULATIVE"
TAG="DAILY_L1C"
fi
echo "ENV: SID=$ORACLE_SID HOME=$ORACLE_HOME PATH=$PATH" >>"$LOG"
"$ORACLE_HOME/bin/rman" target / log="$LOG" <<RMAN
RUN {
BACKUP AS BACKUPSET $LEVEL_CMD DATABASE TAG '$TAG';
BACKUP AS BACKUPSET ARCHIVELOG ALL NOT BACKED UP TAG 'ARCH_SYNC';
DELETE NOPROMPT OBSOLETE;
}
LIST BACKUP SUMMARY;
RMAN
echo "Backup complete ($TAG). Log: $LOG"
BASH
chmod +x /u01/app/oracle/admin/backup/rman_backup.sh"
rman_fra_sync.sh
)Uses a cmdfile and TO DESTINATION '/backup/rman'
.
sudo -iu oracle bash -lc "cat > /u01/app/oracle/admin/backup/rman_fra_sync.sh <<'BASH'
#!/bin/bash
set -euo pipefail
export ORACLE_SID=${ORACLE_SID:-ORCL}
export ORACLE_HOME=/u01/app/oracle/product/19c/dbhome_1
export LD_LIBRARY_PATH=$ORACLE_HOME/lib
export PATH=$ORACLE_HOME/bin:/bin:/usr/bin:$PATH
LOG_DIR=/u01/app/oracle/admin/log
mkdir -p "$LOG_DIR"
STAMP=$(date +%F_%H%M%S)
LOG="$LOG_DIR/rman_fra_sync_$STAMP.log"
DEST=/backup/rman
mkdir -p "$DEST"
CMDFILE=/u01/app/oracle/admin/backup/.rman_fra_sync.rcv
cat > "$CMDFILE" <<'RCV'
RUN {
ALLOCATE CHANNEL ch1 DEVICE TYPE DISK FORMAT '/backup/rman/%d_%T_%U.bkp';
ALLOCATE CHANNEL ch2 DEVICE TYPE DISK FORMAT '/backup/rman/%d_%T_%U.bkp';
BACKUP RECOVERY AREA TO DESTINATION '/backup/rman' TAG 'FRA_SYNC';
RELEASE CHANNEL ch1;
RELEASE CHANNEL ch2;
}
LIST BACKUP SUMMARY;
RCV
echo "ENV: SID=$ORACLE_SID HOME=$ORACLE_HOME PATH=$PATH DEST=$DEST" >>"$LOG"
"$ORACLE_HOME/bin/rman" target / cmdfile="$CMDFILE" log="$LOG"
echo "FRA sync complete. Log: $LOG"
BASH
chmod +x /u01/app/oracle/admin/backup/rman_fra_sync.sh"
sudo -iu oracle bash -lc "cat > /u01/app/oracle/admin/backup/rman_jobs.sql <<'SQL'
BEGIN
FOR j IN (SELECT job_name FROM dba_scheduler_jobs
WHERE job_name IN ('RMAN_BACKUP_NIGHTLY','RMAN_FRA_SYNC_NIGHTLY')) LOOP
DBMS_SCHEDULER.DROP_JOB(j.job_name, force => TRUE);
END LOOP;
END;
/
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'RMAN_BACKUP_NIGHTLY',
job_type => 'EXECUTABLE',
job_action => '/u01/app/oracle/admin/backup/rman_backup.sh',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY;BYHOUR=2;BYMINUTE=0;BYSECOND=0',
enabled => TRUE,
auto_drop => FALSE,
comments => 'Nightly RMAN backup to FRA (/u03/fra). L0 Sun, L1-cum Mon–Sat.'
);
END;
/
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'RMAN_FRA_SYNC_NIGHTLY',
job_type => 'EXECUTABLE',
job_action => '/u01/app/oracle/admin/backup/rman_fra_sync.sh',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY;BYHOUR=3;BYMINUTE=0;BYSECOND=0',
enabled => TRUE,
auto_drop => FALSE,
comments => 'Copy FRA contents to /backup/rman'
);
END;
/
SET LINES 200
COL job_name FORMAT A24
COL state FORMAT A12
SELECT job_name, state,
TO_CHAR(next_run_date,'YYYY-MM-DD HH24:MI:SS TZH:TZM') AS next_run
FROM dba_scheduler_jobs
WHERE job_name IN ('RMAN_BACKUP_NIGHTLY','RMAN_FRA_SYNC_NIGHTLY')
ORDER BY job_name;
SQL
sqlplus / as sysdba @/u01/app/oracle/admin/backup/rman_jobs.sql"
sudo -iu oracle sqlplus -s / as sysdba <<'SQL'
BEGIN
DBMS_SCHEDULER.RUN_JOB('RMAN_BACKUP_NIGHTLY', use_current_session => FALSE);
DBMS_SCHEDULER.RUN_JOB('RMAN_FRA_SYNC_NIGHTLY', use_current_session => FALSE);
END;
/
SQL
# Append to ~oracle/.bashrc to tail newest logs
cat >> ~oracle/.bashrc <<'SH'
tail_rman_sync () {
local LOG
LOG=$(find /u01/app/oracle/admin/log -maxdepth 1 -type f -name "rman_fra_sync_*.log" \
-printf "%T@ %p\n" | sort -nr | awk 'NR==1{print $2}')
if [ -n "$LOG" ]; then
echo ">>> $LOG"
/bin/tail -n 60 "$LOG"
else
echo "No sync log yet."
fi
}
tail_rman_backup () {
local LOG
LOG=$(find /u01/app/oracle/admin/log -maxdepth 1 -type f -name "rman_backup_*.log" \
-printf "%T@ %p\n" | sort -nr | awk 'NR==1{print $2}')
if [ -n "$LOG" ]; then
echo ">>> $LOG"
/bin/tail -n 60 "$LOG"
else
echo "No backup log yet."
fi
}
SH
# Reload and use
sudo -iu oracle bash -lc 'source ~/.bashrc; tail_rman_backup; tail_rman_sync'
-- Newest pieces (from the controlfile)
set lines 200 pages 100
col handle format a100
select completion_time, status, handle
from v$backup_piece
order by completion_time desc fetch first 20 rows only;
-- Scheduler run details
set lines 200
col job_name format a24
col status format a10
col additional_info format a120
select job_name, status, actual_start_date, run_duration, additional_info
from dba_scheduler_job_run_details
where job_name in ('RMAN_BACKUP_NIGHTLY','RMAN_FRA_SYNC_NIGHTLY')
order by actual_start_date desc fetch first 10 rows only;
BACKUP RECOVERY AREA
: add TO DESTINATION '/backup/rman'
.RMAN<lang>.msb not found
): wrong/empty ORACLE_HOME
. Hard‑set ORACLE_HOME
and call RMAN by full path.mkdir
, tail
, etc.): ensure PATH includes /bin:/usr/bin
in scripts.oracle
without credentials.set lines 180 pages 100
col name format a40
select name, space_limit/1024/1024/1024 as fra_gb,
space_used/1024/1024/1024 as used_gb,
space_reclaimable/1024/1024/1024 as reclaimable_gb
from v$recovery_file_dest;
select object_type, count(*) cnt
from v$flash_recovery_area_usage
group by object_type
order by 1;
Wrap‑up: Nightly RMAN backups to FRA (weekly L0, daily L1‑cum) + a secondary copy under /backup/rman
, all owned by DBMS_SCHEDULER with simple log helpers. Ship it. 🚀