シェル-RACコールドバックアップ
対応バージョン
Oracle Database 10.2 - 11.2
2015-06-01記事公開
よく使用する便利ツールの公開です。
※ カスタマイズなどのご要望がございましたら、お見積りいたしますので、弊社までお問い合わせください。
シェル概要
RAC環境にて指定したデータベースのコールドバックアップを取得します。
シングルインスタンス環境では動作しません。
テスト環境
OS: Oracle Linux 6
Database: Oracle Database 11cR2 Real Application Cluseter
Database: Oracle Database 11cR2 Real Application Cluseter
使用方法
rootユーザにて以下のように実行します。(rootユーザ又はsudoにて実行)
1 |
$ rac_backup_rmancold.sh [引数1:バックアップ対象DB] |
実行例
1 2 3 |
# su - # chmod 755 /tmp/rac_backup_rmancold.sh # /tmp/rac_backup_rmancold.sh orcl |
シェル内容
以下に rac_backup_rmancold.sh シェルの内容を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
#!/bin/bash # Copyright 2015 SIX SQUARE JAPAN.co.,ltd. All Rights Reserved. # 本著作物は例を示したサンプルであり、資料の内容を利用した場合について、 # 弊社が一切の責任を負うものではありません。 # Version: # Ver 1.0 - 2015/06/01 - 新規作成 # Description: # 引数に与えられたOracle RAC データベースのコールドバックアップを取得する。 # データベースの起動・停止を行う。 # 実行はrootユーザまたはsudoにて実行を行う。 # Usage: # parameter1: バックアップ対象DBの DB_NAME ############################################################################### # SYSDBA権限のグループをもつOSユーザ SYSDBA_OSUSER=oracle # レポートファイルの出力先定義 BACKUP_DIRECOTRY=/mnt/dbbackup/oraclerman # バックアップ世代数(手動管理) BACKUP_RETENTION=1 # RMAN実行チャネルの数(パラレル度) NUM_PARALLEL=16 ORACLE_BASE="" ORACLE_HOME="" NORMAL_CODE=0 ERROR_CODE=1 # バックアップオプション [ON/OFF] BACKUP_SET_OPTION_COMPRESS=ON BACKUP_SET_OPTION_ENCRYPTION=ON # SYSDBA_OSUSER に設定したユーザの.bash_profile読み込み L_ORACLE_BASH_PROFILE=`eval ls -1 ~${SYSDBA_OSUSER}/.bash_profile` if [ -f ${L_ORACLE_BASH_PROFILE} ]; then source ${L_ORACLE_BASH_PROFILE} fi export LANG=C export NLS_LANG=American_America.AL32UTF8 # ORACLE_BASEが空の場合、.bash_profileから取得 if [ -z "${ORACLE_BASE}" ]; then ORACLE_BASE=`grep "ORACLE_BASE=" ${L_ORACLE_BASH_PROFILE} | grep -v "^[ ]*#" \ | cut -d'=' -f2- | sed -e 's@#.*$@@'` # ORACLE_BASEが取得できない場合は必須でないためそのまま実行 if [ -z "${ORACLE_BASE}" ]; then echo "`date '+%Y/%m/%d %H:%M:%S'` Warning: ORACLE_BASE is NULL" fi fi # ORACLE_HOMEが空の場合、.bash_profileから取得 if [ -z "${ORACLE_HOME}" ]; then ORACLE_HOME=`grep "ORACLE_HOME=" ${L_ORACLE_BASH_PROFILE} | grep -v "^[ ]*#" \ | cut -d'=' -f2- | sed -e 's@#.*$@@'` if [ -z "${ORACLE_HOME}" ]; then # ORACLE_HOMEが取得できない場合は異常終了 echo "ORACLE_HOME of environment variable Not found." exit ${ERROR_CODE} fi fi export ORACLE_BASE ORACLE_HOME PATH=${ORACLE_HOME}/bin:${PATH}:/usr/bin:/usr/sbin:/bin:/sbin export PATH echo "`date '+%Y/%m/%d %H:%M:%S'` Started shell[`basename $0`]" # ユーザの確認 case "${USER}" in "root" ) echo "`date '+%Y/%m/%d %H:%M:%S'` User is ${USER}. [Pass]" ;; * ) echo "`date '+%Y/%m/%d %H:%M:%S'` User is ${USER}. Switch user to [root]." exit ${ERROR_CODE} ;; esac # 引数の数のチェック if [ $# -ne 1 ]; then echo "Usage: $0 [Backup DB Name]" echo " ex: $0 orcl" exit ${ERROR_CODE} fi # 第一引数に指定された値をバックアップ対象のDBとして設定 BKDB=$1 # RMANファイルのバックアップディレクトリ設定 L_BACKUP_DIRECOTRY_RMANFILE=${BACKUP_DIRECOTRY}/${BKDB}_cold # Gridが動作しているORACLE_HOMEを特定 GRID_OCSSDBIN=`ps -ef | awk '{print $8}' | grep "/ocssd.bin$" | head -1` export PATH=`dirname ${GRID_OCSSDBIN}`:${PATH} # シェル実行ノードのデータベースのステータスを取得 L_DB_STATUS=`srvctl status database -d ${BKDB} | grep " `uname -n | cut -d'.' -f1`$"` if [ "${L_DB_STATUS}" = "" ]; then # シェル実行ノードで稼働しているインスタンスが取得できなかった場合 echo "`date '+%Y/%m/%d %H:%M:%S'` Instance was not exists. [${BKDB} on `uname -n | cut -d'.' -f1`]" exit ${ERROR_CODE} fi # インスタンス名を取得 L_TGT_INSTANCE=`echo "${L_DB_STATUS}" | awk '{print $2}'` # 古いバックアップの削除 if [ -d ${L_BACKUP_DIRECOTRY_RMANFILE} ]; then # バックアップディレクトリ付与番号最大値の取得 L_NUM_DIRECTORY_MAX=`expr ${BACKUP_RETENTION} - 1` for L_NUM_DIRECTORY in `ls -1d ${L_BACKUP_DIRECOTRY_RMANFILE}.[0-9]* 2>/dev/null \ | sed -e "s@${L_BACKUP_DIRECOTRY_RMANFILE}.@@" | sort -r` do # 取得したディレクトリ番号の数値チェック echo "${L_NUM_DIRECTORY}" | grep -q "[0-9]*[0-9]" if [ $? -ne 0 ]; then # 取得したディレクトリ番号が数値以外の場合 echo "[${L_NUM_DIRECTORY}] is not numeric data." else # 決められたフォーマットのものはローテーションを行う if [ ${L_NUM_DIRECTORY} -ge ${L_NUM_DIRECTORY_MAX} ]; then # 取得したディレクトリ番号が世代最大値より大きいか等しい場合 echo "`date '+%Y/%m/%d %H:%M:%S'` Remove [${L_BACKUP_DIRECOTRY_RMANFILE}.${L_NUM_DIRECTORY}]" rm -rf ${L_BACKUP_DIRECOTRY_RMANFILE}.${L_NUM_DIRECTORY} else # 取得したディレクトリ番号が世代最大値より小さい場合 L_NUM_DIRECTORY_MOVE=`expr ${L_NUM_DIRECTORY} + 1` echo -n "`date '+%Y/%m/%d %H:%M:%S'` Move [${L_BACKUP_DIRECOTRY_RMANFILE}.${L_NUM_DIRECTORY}] to" echo " [${L_BACKUP_DIRECOTRY_RMANFILE}.${L_NUM_DIRECTORY_MOVE}]" mv -f ${L_BACKUP_DIRECOTRY_RMANFILE}.${L_NUM_DIRECTORY} ${L_BACKUP_DIRECOTRY_RMANFILE}.${L_NUM_DIRECTORY_MOVE} fi # ローテーション対象のディレクトリが残存していた場合 if [ -d ${L_BACKUP_DIRECOTRY_RMANFILE}.${L_NUM_DIRECTORY} ]; then echo "`date '+%Y/%m/%d %H:%M:%S'` Remove directory failed. [${L_BACKUP_DIRECOTRY_RMANFILE}.${L_NUM_DIRECTORY}]" exit ${ERROR_CODE} fi fi done # 前回バックアップの処理 if [ ${L_NUM_DIRECTORY_MAX} -ge 1 ]; then # 最大ローテーション番号が1より大きい場合(二世代以上)は、前回バックアップを .1 に変更 echo "`date '+%Y/%m/%d %H:%M:%S'` Move [${L_BACKUP_DIRECOTRY_RMANFILE}] to [${L_BACKUP_DIRECOTRY_RMANFILE}.1]" mv -f ${L_BACKUP_DIRECOTRY_RMANFILE} ${L_BACKUP_DIRECOTRY_RMANFILE}.1 else # 1世代保存の場合、前回のバックアップを削除 echo "`date '+%Y/%m/%d %H:%M:%S'` Remove [${L_BACKUP_DIRECOTRY_RMANFILE}]" rm -rf ${L_BACKUP_DIRECOTRY_RMANFILE} fi # ローテーション処理のチェック if [ -d ${L_BACKUP_DIRECOTRY_RMANFILE} ]; then echo "`date '+%Y/%m/%d %H:%M:%S'` Remove directory failed. [${L_BACKUP_DIRECOTRY_RMANFILE}]" exit ${ERROR_CODE} fi fi # データベースをマウントモードへ変更 echo "`date '+%Y/%m/%d %H:%M:%S'` Stop database [${BKDB}]" L_DB_STATUS=`su - ${SYSDBA_OSUSER} -c "export ORACLE_HOME=${ORACLE_HOME}; ${ORACLE_HOME}/bin/srvctl stop database -d ${BKDB}"` echo "`date '+%Y/%m/%d %H:%M:%S'` Mount database [${BKDB}]" L_DB_STATUS=`su - ${SYSDBA_OSUSER} -c "export ORACLE_HOME=${ORACLE_HOME}; \ ${ORACLE_HOME}/bin/srvctl start instance -d ${BKDB} -i ${L_TGT_INSTANCE} -o mount"` # データベースのオープン状態を取得 L_MNTSTATUS=`su - ${SYSDBA_OSUSER} -c "export LANG=C; export NLS_LANG=American_America.AL32UTF8; \ export ORACLE_HOME=${ORACLE_HOME}; export ORACLE_SID=${L_TGT_INSTANCE}; \ ${ORACLE_HOME}/bin/sqlplus -s -L / as sysdba << SQL_EOF whenever sqlerror exit 2 whenever oserror exit 2 set pages 0 line 1200 trim on trims on feed off heading off timing off verify off select OPEN_MODE from v\\\\\\\$database; exit SQL_EOF"` echo "`date '+%Y/%m/%d %H:%M:%S'` The status of database:${BKDB} is [${L_MNTSTATUS}]" # データベースのオープン状態がコールドバックアップの前提であるマウントモードになっていることの確認 if [ "${L_MNTSTATUS}" != "MOUNTED" ]; then echo "`date '+%Y/%m/%d %H:%M:%S'` Status of database[${BKDB}] is not MOUNTED. Change status was failed." exit ${ERROR_CODE} fi # バックアップディレクトリの作成 mkdir -m777 ${L_BACKUP_DIRECOTRY_RMANFILE} if [ ! -d ${L_BACKUP_DIRECOTRY_RMANFILE} ]; then echo "`date '+%Y/%m/%d %H:%M:%S'` mkdir failed.[${L_BACKUP_DIRECOTRY_RMANFILE}]" exit ${ERROR_CODE} fi # 指定されたパラレル度に応じて、チャネル宣言の生成 for L_NUM_CH in `seq 1 ${NUM_PARALLEL}` do L_ALLOCATE_CHANNEL=" ALLOCATE CHANNEL ch${L_NUM_CH} DEVICE TYPE DISK FORMAT '${L_BACKUP_DIRECOTRY_RMANFILE}/DATA_%d_DBID%I_%U';" L_ALLOCATE_CHANNELS=`printf "%s\n%s" "${L_ALLOCATE_CHANNELS}" "${L_ALLOCATE_CHANNEL}"` done # 圧縮オプションがONの場合は圧縮処理を付与 if [ "${BACKUP_SET_OPTION_COMPRESS}" == "ON" ]; then L_BACKUP_SET_OPTION=`printf "%s\n%s" "${L_BACKUP_SET_OPTION}" "SET COMPRESSION ALGORITHM 'LOW';"` L_BACKUP_FTYPE="AS COMPRESSED BACKUPSET" else L_BACKUP_FTYPE="AS BACKUPSET" fi # 暗号化オプションがONの場合は暗号化処理を付与 if [ "${BACKUP_SET_OPTION_ENCRYPTION}" == "ON" ]; then L_BACKUP_SET_OPTION=`printf "%s\n%s" "${L_BACKUP_SET_OPTION}" "SET ENCRYPTION ALGORITHM 'AES128' ON;"` fi # RMAN コマンドファイル生成 L_RMANCMDFILE=${L_BACKUP_DIRECOTRY_RMANFILE}/rman_`date '+%Y%m%d%H%M%S'`.cmd echo "CROSSCHECK BACKUP;" >> ${L_RMANCMDFILE} echo "DELETE NOPROMPT EXPIRED BACKUP;" >> ${L_RMANCMDFILE} echo "${L_BACKUP_SET_OPTION}" >> ${L_RMANCMDFILE} echo "run {" >> ${L_RMANCMDFILE} echo " ${L_ALLOCATE_CHANNELS}" >> ${L_RMANCMDFILE} echo " backup ${L_BACKUP_FTYPE} database SECTION SIZE 50G;" >> ${L_RMANCMDFILE} echo "}" >> ${L_RMANCMDFILE} echo -n "backup AS BACKUPSET DEVICE TYPE DISK FORMAT " >> ${L_RMANCMDFILE} echo "'${L_BACKUP_DIRECOTRY_RMANFILE}/SPFL_%d_DBID%I_%U' spfile;" >> ${L_RMANCMDFILE} echo -n "backup AS BACKUPSET DEVICE TYPE DISK FORMAT " >> ${L_RMANCMDFILE} echo "'${L_BACKUP_DIRECOTRY_RMANFILE}/CTRL_%d_DBID%I_%U' current controlfile;" >> ${L_RMANCMDFILE} echo "exit" >> ${L_RMANCMDFILE} chmod 666 ${L_RMANCMDFILE} # RMAN コマンドファイルの作成確認 if [ ! -f "${L_RMANCMDFILE}" ]; then echo "`date '+%Y/%m/%d %H:%M:%S'` Create rman command file failed.[${L_RMANCMDFILE}]" exit ${ERROR_CODE} fi # RMAN コールドバックアップの実行 su - ${SYSDBA_OSUSER} -c "export NLS_DATE_FORMAT='YYYY/MM/DD HH24:MI:SS'; export ORACLE_HOME=${ORACLE_HOME}; \ export ORACLE_SID=${L_TGT_INSTANCE}; \ ${ORACLE_HOME}/bin/rman target / nocatalog @'${L_RMANCMDFILE}'" \ | tee -a ${L_BACKUP_DIRECOTRY_RMANFILE}/rman_`date '+%Y%m%d%H%M%S'`.log echo "`date '+%Y/%m/%d %H:%M:%S'` Ended backup database[${BKDB}]" # バックアップ後データベースの再起動 echo "`date '+%Y/%m/%d %H:%M:%S'` Stop database [${BKDB}]" L_DB_STATUS=`su - ${SYSDBA_OSUSER} -c "export ORACLE_HOME=${ORACLE_HOME}; ${ORACLE_HOME}/bin/srvctl stop database -d ${BKDB}"` echo "`date '+%Y/%m/%d %H:%M:%S'` Start database [${BKDB}]" L_DB_STATUS=`su - ${SYSDBA_OSUSER} -c "export ORACLE_HOME=${ORACLE_HOME}; ${ORACLE_HOME}/bin/srvctl start database -d ${BKDB}"` # データベース再起動後のステータス確認 srvctl status database -d ${BKDB} 2>&1 | grep -qv "is running on node" L_DBSTATUS=$? if [ ${L_DBSTATUS} -ne 1 ]; then echo "`date '+%Y/%m/%d %H:%M:%S'` Status of database was wrong.[${BKDB}]" srvctl status database -d ${BKDB} exit ${ERROR_CODE} fi exit ${NORMAL_CODE} |