下面是我起草的脚本,它将根据从中获取的 SID 来工作
ps -ef | grep pmon
一旦 SID 被 grep 出来,它就会将 SID 传递给dbenv()
设置必要的参数,并且还会从条目中删除 DB_VERSION /etc/oratab
。
根据版本,如果版本为 12 或 11,则脚本应执行一个块,或者如果版本为 10 或 9,则应执行一个块。
TRACE_FILE
12 或 11 有s 值下的警报日志,10 或 9 不会有 的任何输出TRACE_FILE
,因此 10 和 9 应根据BDUMP
s 值清除警报日志。
所以我起草了下面的脚本,它工作得很好,我觉得该脚本有很多重复,其中我应用了 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-----------------------------------------------------------------------------------#
答案1
这个问题可能属于 https://codereview.stackexchange.com/而不是在这里,但这是我的建议:
使用
$()
而不是反引号进行命令替换。你(几乎)永远不需要通过管道输入
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 变量,所以我们需要反斜杠转义是为了防止 shell 将其替换为自己的)$2
awk
awk
awk
$ORACLE_SID
awk
awk
$2
$2
你不需要做管道
ps
进入grep
或awk
无论如何。你也可以这样做ps h -o cmd -C pmon
。或者使用pgrep
.sed
可以自己读取文件,不需要通过管道传输cat
到sed
.grep
和awk
和perl
以及cut
所有其他标准文本处理工具也可以。[ -n "$var" ]
是相同的[ ! -z "$var" ]
。-z
测试空字符串,-n
测试非空字符串。在某些情况下,您没有对变量进行双引号。当你使用变量时,你应该(几乎)总是用双引号引起来。
单引号用于固定的文字字符串。当您想要将变量或命令替换插入字符串时,可以使用双引号。
缩进 8 个字符过多。每个缩进级别使用 2 或 4 个空格。或者将编辑器中的制表位设置为 2 或 4 个空格。
使用小写或混合大小写作为自己的变量是一个好习惯,为标准实用程序和通用程序保留全部大写的变量名称。
sqlplus
、mysql
、等工具psql
对于在 sh 或 bash 等中执行脚本化数据库查询非常方便,但是您必须非常小心与 SQL 命令一起使用的任何变量 - 特别是如果变量中的值来自用户提供的数据,或者其他“不可信”来源。如果输入数据未经验证且未经清理,则很容易破坏脚本。创建 SQL 注入错误同样容易。对于重要的 SQL 查询,您可能应该学习
perl
或python
或其他带有支持占位符的数据库库的语言,以避免在 sql 命令中引用变量时出现任何问题。