Shell-Script

根據變數的輸出執行塊

  • February 23, 2018

下面是我起草的腳本,它將根據它將從中獲得的 SID 工作

ps -ef | grep pmon

一旦 SID 被 grepped,它將傳遞 SID 以設置必要的參數,並且它還會從條目dbenv()中刪除 DB_VERSION 。/etc/oratab

根據版本,如果是 12 或 11,那麼腳本應該執行一個塊,或者如果版本是 10 或 9,它應該執行一個塊。

12 或 11 的警報日誌在TRACE_FILE’ 值下,10 或 9 不會有任何輸出TRACE_FILE,因此 10 和 9 應根據BDUMPs 值清除警報日誌。

所以我起草了下面的腳本,它工作正常,我覺得腳本有很多重複,我為 DB_VERSION 應用了邏輯。

關於如何增強此腳本的任何想法

#############################################################################################################################################################
#!/bin/bash
#############################################################################################################################################################

TODAY=`date +%Y-%m-%d`
DATE=`date +%Y%b%d`
YESTERDAY=`date -d '-1 day' +%b%Y`
YDAY=`date -d '-1 day' +%Y%b%d`
HOST=`hostname`
LOG_LOCATION="/home/oracle/utility_script/dba_maint/logs"

mkdir -p ${LOG_LOCATION}

LOG_FILE="${LOG_LOCATION}/oracle_files_cleanup_${DATE}.log"

rm ${LOG_FILE} 2>/dev/null

dbenv ()
{
       ORACLE_HOME=`cat /etc/oratab | grep ^$ORACLE_SID | cut -d":" -f2`; export ORACLE_HOME
       PATH=$ORACLE_HOME/bin:$PATH ; export PATH
       LD_LIBRARY_PATH=$ORACLE_HOME/lib ; export LD_LIBRARY_PATH
       DB_VERSION=`cat /etc/oratab | grep "^$ORACLE_SID" | cut -d":" -f2 | rev | cut -d"/" -f2| rev | cut -d"." -f1`; export DB_VERSION
}


dbcheck()
{
       sqlplus / as sysdba << EOF &>${LOG_LOCATION}/dbcheck.out
       exit
EOF
}

sql_plus()
{
       sqlplus -s / as sysdba << EOF &>/dev/null
       SET NEWPAGE NONE;
       set lines 200 pages 300;
       set feedback off;
       set heading off;
       spool ${LOG_LOCATION}/$1.log
       $2
       exit
EOF
}

for SID in `ps -eaf | grep pmon | grep -v grep | awk '{print $8}' | sort | cut -d"_" -f3`
do
       ORACLE_SID=${SID} ; export ORACLE_SID
       dbenv ${ORACLE_SID}                                                     #-- Passing the ORACLE_SID to dbenv function to source the database.
       if [ ${DB_VERSION} -eq 11 -o ${DB_VERSION} -eq 12 ]
       then
               dbcheck
               DB_CHECK=`cat ${LOG_LOCATION}/dbcheck.out | egrep "ORA|SP2|idle"`
               LOWER_SID=`echo ${ORACLE_SID} | tr '[A-Z]' '[a-z]'`

#-- Queries to fetch the proper log location from database

               ADUMP="select DISPLAY_VALUE from v\$parameter where name='audit_file_dest';"
               BDUMP="select DISPLAY_VALUE from v\$parameter where name='background_dump_dest';"
               CDUMP="select DISPLAY_VALUE from v\$parameter where name='core_dump_dest';"
               UDUMP="select DISPLAY_VALUE from v\$parameter where name='user_dump_dest';"
               TRACE_FILE="select DISPLAY_VALUE from v\$parameter where name='diagnostic_dest';"

#-- Calls the sql_plus function with the parameters as the logname and SQL query

               sql_plus "adump_${ORACLE_SID}" "${ADUMP}"
               sql_plus "bdump_${ORACLE_SID}" "${BDUMP}"
               sql_plus "cdump_${ORACLE_SID}" "${CDUMP}"
               sql_plus "udump_${ORACLE_SID}" "${UDUMP}"
               sql_plus "trace_${ORACLE_SID}" "${TRACE_FILE}"

#-- Remove any empty lines after the log location

               ADUMP_LOC=`cat ${LOG_LOCATION}/adump_${ORACLE_SID}.log | sed 's/[[:blank:]]*$//'`
               BDUMP_LOC=`cat ${LOG_LOCATION}/bdump_${ORACLE_SID}.log | sed 's/[[:blank:]]*$//'`
               CDUMP_LOC=`cat ${LOG_LOCATION}/cdump_${ORACLE_SID}.log | sed 's/[[:blank:]]*$//'`
               UDUMP_LOC=`cat ${LOG_LOCATION}/udump_${ORACLE_SID}.log | sed 's/[[:blank:]]*$//'`
               TRACE_LOC=`cat ${LOG_LOCATION}/trace_${ORACLE_SID}.log | sed 's/[[:blank:]]*$//'`

#-- If the Database is not in idle state or without any errors, start housekeeping

               if [ -z "${DB_CHECK}" ]
               then
                       echo -e "\t\t\t\t HOUSEKEEPING for database : ${ORACLE_SID}" >>${LOG_FILE}
                       echo -e "\t\t\t\t ============ === ======== = =============" >>${LOG_FILE}

#-- Cleans .aud files older than 60 days in ADUMP location

                       if [ ! -z "${ADUMP_LOC}" ]
                       then
                                       echo -e "\t\t\tAdump cleanup" >> ${LOG_FILE}
                       fi

#-- Cleans .trm or .trc files older than 60 days in BDUMP location

                       if [ ! -z "${BDUMP_LOC}" ]
                       then
                                       echo -e "\n\n\t\t\tBdump cleanup" >> ${LOG_FILE}
                       fi

#-- Cleans .trm or .trc files older than 60 days in CDUMP location

                       if [ ! -z "${CDUMP_LOC}" ]
                       then
                                       echo -e "\n\t\t\tCdump cleanup" >> ${LOG_FILE}
                       fi

#-- Cleans .trm or .trc files older than 60 days in UDUMP location

                       if [ ! -z "${UDUMP_LOC}" ]
                       then
                                       echo -e "\n\t\t\tUdump cleanup" >> ${LOG_FILE}
                       fi

#-- Rotates the Database alert log on 01st of every month.

                       if [ `date +%d` -eq 01 ]
                       then
                               if [ ! -z "${TRACE_LOC}" ]
                               then
                                       echo -e "\n\t\t\tALERT LOG ROTATION" >> ${LOG_FILE}
                               fi
                       fi

#-- Rotates the Listener log on 01st of every month.

                       if [ `date +%d` -eq 01 ]
                                       if [ ! -z "${TRACE_LOC}" ]
                                       then
                                                       echo -e "\n\t\t\tLISTENER LOG ROTATION" >> ${LOG_FILE}
                                       fi
                       fi
               else
                       echo -e "ERROR : Please fix the below error in database - ${ORACLE_SID} on host - ${HOST} \n ${DB_CHECK}" >> ${LOG_LOCATION}/house_keeping_fail_${ORACLE_SID}_${DATE}.log
               fi
       elif [ ${DB_VERSION} -eq 10 -o ${DB_VERSION} -eq 9 ]
       then
               dbcheck
               DB_CHECK=`cat ${LOG_LOCATION}/dbcheck.out | egrep "ORA|SP2|idle"`

#-- Queries to fetch the proper log location from database

               ADUMP="select DISPLAY_VALUE from v\$parameter where name='audit_file_dest';"
               BDUMP="select DISPLAY_VALUE from v\$parameter where name='background_dump_dest';"
               CDUMP="select DISPLAY_VALUE from v\$parameter where name='core_dump_dest';"
               UDUMP="select DISPLAY_VALUE from v\$parameter where name='user_dump_dest';"

#-- Calls the sql_plus function with the parameters as the logname and SQL query

               sql_plus "adump_${ORACLE_SID}" "${ADUMP}"
               sql_plus "bdump_${ORACLE_SID}" "${BDUMP}"
               sql_plus "cdump_${ORACLE_SID}" "${CDUMP}"
               sql_plus "udump_${ORACLE_SID}" "${UDUMP}"

#-- Remove any empty lines after the log location

               ADUMP_LOC=`cat ${LOG_LOCATION}/adump_${ORACLE_SID}.log | sed 's/[[:blank:]]*$//'`
               BDUMP_LOC=`cat ${LOG_LOCATION}/bdump_${ORACLE_SID}.log | sed 's/[[:blank:]]*$//'`
               CDUMP_LOC=`cat ${LOG_LOCATION}/cdump_${ORACLE_SID}.log | sed 's/[[:blank:]]*$//'`
               UDUMP_LOC=`cat ${LOG_LOCATION}/udump_${ORACLE_SID}.log | sed 's/[[:blank:]]*$//'`

#-- If the Database is not in idle state or without any errors, start housekeeping

               if [ -z "${DB_CHECK}" ]
               then
#-- Cleans .aud files older than 60 days in ADUMP location

                       if [ ! -z "${ADUMP_LOC}" ]
                                       echo -e "\t\t\tAdump cleanup" >> ${LOG_FILE}
                       fi

#-- Cleans .trm or .trc files older than 60 days in BDUMP location

                       if [ ! -z "${BDUMP_LOC}" ]
                       then
                                       echo -e "\n\n\t\t\tBdump cleanup" >> ${LOG_FILE}
                       fi

#-- Cleans .trm or .trc files older than 60 days in CDUMP location

                       if [ ! -z "${CDUMP_LOC}" ]
                       then
                                       echo -e "\n\t\t\tCdump cleanup" >> ${LOG_FILE}
                       fi

#-- Cleans .trm or .trc files older than 60 days in UDUMP location

                       if [ ! -z "${UDUMP_LOC}" ]
                       then
                                       echo -e "\n\t\t\tUdump cleanup" >> ${LOG_FILE}
                       fi

#-- Rotates the ${DB_VERSION} version Database alert log on 01st of every month.

                       if [ `date +%d` -eq 01 ]
                       then
                               if [ ! -z "${BDUMP_LOC}" ]
                               then
                                       echo -e "\n\t\t\tALERT LOG ROTATION" >> ${LOG_FILE}
                               fi
                       fi
              else
                      echo -e "ERROR : Please fix the below error in database - ${ORACLE_SID} on host - ${HOST} \n ${DB_CHECK}" >> ${LOG_LOCATION}/house_keeping_fail_${ORACLE_SID}_${DATE}.log
              fi
       fi
done
exit $?
#---------------------------------------------------------------------END-----------------------------------------------------------------------------------#

這個問題可能屬於 https://codereview.stackexchange.com/而不是這裡,但這是我的建議:

  1. 使用$()而不是反引號進行命令替換。
  2. 您(幾乎)永遠不需要grep輸入awk. 例如,而不是:
ps -eaf | grep pmon | grep -v grep | awk '{print $8}'

你可以做:

ps -eaf | awk '/pmon/ && ! /grep/ {print $8}'

grep類似地,管道cut通常最好使用awk. 例如,而不是:

cat /etc/oratab | grep ^$ORACLE_SID | cut -d":" -f2

採用

awk -F: "/^$ORACLE_SID/ {print \$2}" /etc/oratab

(通常你不會在腳本中轉義$of ,因為更常見的是單引號整個腳本。在這種情況下,我們是雙引號腳本,以便我們可以使用 bash 變數,所以我們需要反斜杠轉義以防止外殼用自己的替換它)$2``awk``awk``awk``$ORACLE_SID``awk``awk``$2``$2 3. 你不需要做管道psgrep無論如何awk。你可以這樣做ps h -o cmd -C pmon。或使用pgrep. 4. sed可以自己讀取文件,你不需要管道catsed. 其他標准文本處理工具也grep可以。awk``perl``cut 5. [ -n "$var" ]是一樣的[ ! -z "$var" ]

-z測試空字元串,-n測試非空字元串。 6. 有幾次你沒有雙引號你的變數。當你使用它們時,你應該(幾乎)總是用雙引號引起來。 7. 單引號用於固定的文字字元串。雙引號用於將變數或命令替換插入字元串時。 8. 縮進 8 個字元是多餘的。每個縮進級別使用 2 或 4 個空格。或將編輯器中的製表位設置為 2 或 4 個空格。 9. 對您自己的變數使用小寫或 MixedCase 是一個好習慣,而將 ALLCAPS 變數名留給標準實用程序和常用程序。 10. sqlplus, mysql,等工具psql對於在 sh 或 bash 等中執行腳本數據庫查詢非常方便,但您必須非常小心使用 SQL 命令的任何變數 - 特別是如果變數中的值來自使用者提供的數據,或者其他“不受信任”的來源。如果輸入數據未經驗證和未經處理,很容易破壞腳本。創建 SQL 注入錯誤同樣容易。

對於非平凡的 SQL 查詢,您可能應該學習perlpython使用支持佔位符的數據庫庫的其他語言,以避免在 sql 命令中引用變數時出現任何問題。

引用自:https://unix.stackexchange.com/questions/426051