經過2個多月的努力,該系列博文到這裡已經即將結束,希望該系列的文章能夠給諸位今後的工作帶來些許協助,也希望能有機會與大家在技術上多多交流,互相取長補短,同時也敬請大家能夠繼續關注我在後面給出的關於其他技術主題的系列博文。最後在這裡感謝諸位網友的支援。
言歸正傳,該篇部落格將承接上一篇部落格,進入oracle啟動指令碼的主體邏輯部分。
#1. /etc/oratab指令碼的格式如下:
# MyOrcl1:/opt/oracle/product/OraHome:Y
# MyOrcl2:/opt/oracle/product/OraHome:N
#該檔案的開頭處有很多的注釋說明,都是以#開頭,這些注釋需要在後面的處理中被忽略。在有用部分中,每行表示一個oracle執行個體,在同一行中,包含3個欄位,他們之間用#冒號分隔,第一個欄位為oracle的sid,第二個欄位為oracle執行個體的主目錄,最後一個欄位表示本次啟動是否拉起該執行個體,如果為Y則拉起,N則忽略。
#2. cat以管道的形式,將每行的都輸出給while迴圈,作為其輸入並賦值給LINE變數,如果到了$ORATAB檔案的末尾,while迴圈將退出。
cat $ORATAB | while read LINE; do
#3. 如果當前行以#開頭後面跟隨任一字元,則為注釋說明,直接忽略即可。
#4. 如果合法的資料行,用awk命令進行切分,並提取第一個域欄位,即oracle的sid值,賦值給變數ORACLE_SID。如果該變數為空白,則直接忽略,continue命令將回到迴圈的開頭處。
case $LINE in
\#*) ;;
*)
ORACLE_SID=`echo $LINE | awk -F: '{print $1}' -`
if [ "$ORACLE_SID" = '*' ] ; then
ORACLE_SID=""
continue
fi
#5. 這裡提取$LINE變數的最後一個欄位,其中NF表示awk的輸入行的欄位數量,在本例中NF的值為3,$LINE的第三個域為狀態欄位,只有當該值為Y時才拉起該sid。
if [ "`echo $LINE | awk -F: '{print $NF}' -`" = "Y" ] ; then
#6. 通過cut命令截取ORACLE_SID的第一個字元,如果其值為加號(+),則視其為asm instance。
#7. 這裡的cut命令可以替換為${ORACLE_SID:0:1},0表示從變數$ORACLE_SID的第一個字元開始,取1個字元。
if [ `echo $ORACLE_SID | cut -b 1` = '+' ]; then
INST="ASM instance"
ORACLE_HOME=`echo $LINE | awk -F: '{print $2}' -`
export ORACLE_HOME
LOG=$ORACLE_HOME/startup.log
#8. 通過touch命令建立一個記錄檔,同時賦予讀許可權。
touch $LOG
chmod a+r $LOG
echo "Processing $INST \"$ORACLE_SID\": log file $ORACLE_HOME/startup.log"
#9. 調用啟動asm執行個體的函數,並將標準輸出重新導向到剛剛建立的記錄檔,同時也將標準錯誤輸出也重新導向到該檔案。
startasminst >> $LOG 2>&1
fi
fi
;;
esac
done
#10. 如果執行之上的操作失敗,則直接退出指令碼,退出值為2。
if [ "$?" != "0" ] ; then
exit 2
fi
#11. 該部分將重新遍曆/etc/oratab檔案,並啟動資料庫執行個體。該段邏輯中的shell技巧和上面的邏輯基本相同,這裡僅給出差異部分。
cat $ORATAB | while read LINE; do
case $LINE in
\#*) ;;
*)
ORACLE_SID=`echo $LINE | awk -F: '{print $1}' -`
if [ "$ORACLE_SID" = '*' ] ; then
ORACLE_SID=""
continue
fi
# Proceed only if last field is 'Y'.
if [ "`echo $LINE | awk -F: '{print $NF}' -`" = "Y" ] ; then
#12. 這裡和上面不同是,是判斷ORACLE_SID的第一個字元不為加號(+),這表示該執行個體為正常的資料庫執行個體。
if [ `echo $ORACLE_SID | cut -b 1` != '+' ]; then
INST="Database instance"
ORACLE_HOME=`echo $LINE | awk -F: '{print $2}' -`
export ORACLE_HOME
LOG=$ORACLE_HOME/startup.log
touch $LOG
chmod a+r $LOG
echo "Processing $INST \"$ORACLE_SID\": log file $ORACLE_HOME/startup.log"
startinst >> $LOG 2>&1
fi
fi
;;
esac
done
#13. 該段代碼邏輯的shell應用技巧和之前幾段的基本雷同,這裡我只是給出技巧上的差異部分。
cat $ORATAB | while read LINE;do
case $LINE in
\#*) ;;
*)
ORACLE_SID=`echo $LINE | awk -F: '{print $1}' -`
if [ "$ORACLE_SID" = '*' ] ; then
ORACLE_SID=""
continue
fi
if [ "`echo $LINE | awk -F: '{print $NF}' -`" = "W" ] ; then
W_ORACLE_SID=`echo $LINE | awk -F: '{print $1}' -`
cat $ORATAB | while read LINE; do
case $LINE in
\#*) ;;
*)
ORACLE_SID=`echo $LINE | awk -F: '{print $1}' -`
if [ "$ORACLE_SID" = '*' ] ; then
ORACLE_SID=""
continue
fi
if [ `echo $ORACLE_SID | cut -b 1` = '+' ]; then
INST="ASM instance"
ORACLE_HOME=`echo $LINE | awk -F: '{print $2}' -`
if [ -x $ORACLE_HOME/bin/srvctl ] ; then
COUNT=0
NODE=`olsnodes -l`
#14. 執行下面的命令,並將其結果用grep命令過濾,只保留包含$ORACLE_SID is running的行,這裡$ORACLE_SID將完成變數替換。
RNODE=`srvctl status asm -n $NODE | grep "$ORACLE_SID is running"`
RC=$?
#15. 如果執行失敗,將繼續執行。
while [ "$RC" != "0" ]; do
#16. COUNT=$((COUNT+1))是另外一種進行數值型變數計算的表示方式。
COUNT=$((COUNT+1))
#17. -eq表示等於$COUNT等於5。
if [ $COUNT -eq 5 ] ; then
$LOGMSG "Error: Timed out waiting on CRS to start ASM instance $ORACLE_SID"
exit $COUNT
fi
$LOGMSG "Waiting for Oracle CRS service to start ASM instance $ORACLE_SID"
$LOGMSG "Wait $COUNT."
sleep 60
RNODE=`srvctl status asm -n $NODE | grep "$ORACLE_SID is running"`
RC=$?
done
else
$LOGMSG "Error: \"${W_ORACLE_SID}\" has dependency on ASM instance \"${ORACLE_SID}\""
$LOGMSG "Error: Need $ORACLE_HOME/bin/srvctl to check this dependency"
fi
fi
;;
esac
done # innner while
fi
;;
esac
done # outer while
#18. 在該段代碼邏輯中,主要是用於處理/etc/oratab檔案中最後一個欄位的值為W的情況,它表示所有的asm執行個體均已啟動完畢,進入等待狀態,此時將只能啟動資料庫執行個體。從Shell的應用技巧視角看,該段邏輯和之前的shell技巧沒有太多差別,這裡就不再一一給出注釋說明了。
cat $ORATAB | while read LINE; do
case $LINE in
\#*) ;;
*)
ORACLE_SID=`echo $LINE | awk -F: '{print $1}' -`
if [ "$ORACLE_SID" = '*' ] ; then
ORACLE_SID=""
continue
fi
if [ "`echo $LINE | awk -F: '{print $NF}' -`" = "W" ] ; then
INST="Database instance"
if [ `echo $ORACLE_SID | cut -b 1` = '+' ]; then
$LOGMSG "Error: ${INST} \"${ORACLE_SID}\" NOT started"
$LOGMSG "Error: incorrect usage: 'W' not allowed for ASM instances"
continue
fi
ORACLE_HOME=`echo $LINE | awk -F: '{print $2}' -`
export ORACLE_HOME
LOG=$ORACLE_HOME/startup.log
touch $LOG
chmod a+r $LOG
echo "Processing $INST \"$ORACLE_SID\": log file $ORACLE_HOME/startup.log"
startinst >> $LOG 2>&1
fi
;;
esac
done
最後需要說明的是,有興趣的讀者可以繼續自行研究$ORACLE_HOME/bin目錄下的另外一個Shell指令碼(dbshut),該指令碼主要用於關閉Oracle資料庫伺服器,其代碼結構和Shell技巧與該指令碼(dbstart)極為相似。