oracle_19c_ru_ojvm_upgrade.sh一键升级脚本分享

news/2025/9/28 22:44:34/文章来源:https://www.cnblogs.com/kerrycode/p/19117774

oracle_19c_ru_ojvm_upgrade.sh一键升级脚本分享

2025-09-28 22:43  潇湘隐者  阅读(0)  评论(0)    收藏  举报

oracle_19c_ru_ojvm_upgrade.sh脚本的初始版本来源于IT邦德的分享,使用原脚本时发现有一些bug,在我的环境中脚本根本跑不通,于是个人在这个脚本的基础上进行了大量的改进与优化,到当前版本可以说算是完全重构了。 我用这个脚本进行了大量的测试验证(测试环境和UAT环境Oraccle 19c数据库实例打补丁),对于Oracle 19c来说基本上是没有什么问题. 使用此脚本打补丁相当丝滑与惬意。也确实让效率飞升,可以腾出很多时间做其他事情。
脚本的一些思路与想法,可以从下面代码略知一二,如果有不足,也敬请指教。当然,这个脚本暂时没有在其他数据库版本经过测试验证。难免会一些Bug,个人后续也会不断地完善、扩充这个脚本。关于这个脚本的一些注意事项,详情请见下面:

注意事项:

  1. 此脚本只在Linux(REHL)平台上测试了Oracle 19c数据库, 虽然经过大量验证,不保证其它平台环境也能运行,可能存在Bug,使用前请进行测试验证,作者不保证脚本没有任何bug
  2. 使用前,根据实际情况修改相关变量.
  3. REQUIRED_OPATCH_VERSION变量需要指定的opatch版本根据官方文档资料指定
  4. 脚本目前还只适用于单实例
  5. Oracle 19c早期版本需要先回滚OJVM补丁,然后安装新的补丁,从Oracle Database 19.17.0开始,官方发布了 RU + OJVM Combination Patch(组合补丁)。在该组合补丁中,OJVM 补丁已被整合进 RU 安装映像,不再需要先回滚旧的 OJVM 补丁. 脚本里面没有考虑早期版本升级需要先回滚OJVM补丁情况. 如有需要,请自行完善.
  6. 多实例环境,又分相同数据库版本和不同数据库版本,这里脚本暂未实现这个功能, 属实太复杂的场景会让脚本变得无比复杂,代码量继续飙增.这个脚本代码行数破千了如果。是相同数据库版本的多实例,只保留一个实例和监听服务,其它关闭,然后跑完脚本,最后在启动其它实例,只需跑datapatch脚本
  7. prepare_run_sql只是特殊环境需要授权,应该很多人的数据库环境根本不需要这样的授权,可以注释删除。
#!/bin/bash#########################################################################################
#                                                                                       #
# Oracle 19c RU + OJVM 一键升级脚本,此脚本初始版本来源于IT邦德,使用原脚本时发现有一些bug#
# 于是个人在其基础上进行了大量的调整与改进,这个脚本基本上可以算是完全重构了。          #
#########################################################################################
#                                                                                       #
# ScriptName            :    oracle_19c_ru_ojvm_upgrade.sh                              #
# Author                :    潇湘隐者                                                   #
# CerateDate            :    2025-08-21                                                 #
# Email                 :    kerry2008code@qq.com                                       #
#***************************************************************************************#
# 变量配置                                                                              #
#---------------------------------------------------------------------------------------#
# CONNECT_INFO        连接数据库的方式,默认为系统认证模式(如需适用账号密码访问,调整即可 #
# ORACLE_SID          ORACLE_SID                                                        #
# ORACLE_HOME         ORACLE主目录                                                      #
# PATCH_DIR           Oracle的补丁文件存放路径                                          #
# OPATCH_PATCH        Oracle的opatch补丁文件名                                          #
# REQUIRED_OPATCH_VERSION 要求的最低opatch版本                                          #
# RU_PATCH            RU补丁文件名                                                      #
# OJVM_PATCH          OJVM补丁名                                                        #
#---------------------------------------------------------------------------------------#
# 参数说明                                                                              #
#---------------------------------------------------------------------------------------#
#     此脚本无须使用参数                                                                #
#---------------------------------------------------------------------------------------#
#  Usage:                                                                               #
#          sh oracle_19c_ru_ojvm_upgrade.sh                                             #
#      或  ./oracle_19c_ru_ojvm_upgrade.sh                                              #
#***************************************************************************************#
# 注意事项:                                                                             #
#    1. 此脚本只在Linux(REHL)平台上测试了Oracle 19c数据库, 虽然经过大量验证,不保证其它  #
#       平台环境也能运行,可能存在Bug,使用前请进行测试验证,作者不保证脚本没有任何bug     #
#    2. 使用前,根据实际情况修改相关变量.                                                #
#    3. REQUIRED_OPATCH_VERSION变量需要指定的opatch版本根据官方文档资料指定             #
#    4. 脚本目前还只适用于单实例                                                        #
#    5. Oracle 19c早期版本需要先回滚OJVM补丁,然后安装新的补丁,从Oracle Database 19.17.0 #
#       开始,官方发布了 RU + OJVM Combination Patch(组合补丁)。在该组合补丁中,OJVM 补丁#
#       已被整合进 RU 安装映像,不再需要先回滚旧的 OJVM 补丁. 脚本里面没有考虑早期版本升#
#       级需要先回滚OJVM补丁情况. 如有需要,请自行完善.                                  #
#    6. 多实例环境,又分相同数据库版本和不同数据库版本,这里脚本暂未实现这个功能,         #
#       属实太复杂的场景会让脚本变得无比复杂,代码量继续飙增.这个脚本代码行数破千了      #
#       如果是相同数据库版本的多实例,只保留一个实例和监听服务,其它关闭,然后跑完脚本,最后#
#       在启动其它实例,只需跑datapatch脚本                                              #
#***************************************************************************************#
# Version        Modified Date            Description                                   #
#***************************************************************************************#
# V.0.0          2025-08-19              IT邦德的原始脚本                               #
# V.1.0          2025-08-21              修改/创建此脚本                                #
# V.1.1          2025-08-25              增加逻辑判断,fix掉几个bug                      #
# V.1.2          2025-08-29              关闭/启动数据库实例,关闭/启动监听功能封装成函数#
#                                        独立出来,方便简单调用                          #
# V.1.3          2025-09-01              打补丁前检查各个PDB失效对象信息,打完补丁后执行 #
#                                        重编译无效对象                                 #
# V.1.4          2025-09-02              打完补丁,检查补丁安装信息                      #
# V.1.5          2025-09-03              完善部分功能与(19c非租户环境)执行检查无        #
#                                        效对象出错的Bug                                #
########################################################################################## =============== 安全控制 ===============
# 严格错误处理
#set -euo pipefail  
#trap "echo 'ERROR: 脚本异常退出,请检查日志!'; exit 1" ERR# =============== 配置区(根据实际修改)===============
# ORACLE_SID
export ORACLE_SID="gsp"
# ORACLE_HOME目录
export ORACLE_HOME="/opt/oracle19c/product/19.3.0/db_1"
# 数据库的连接方式,请根据实际情况调整
readonly CONNECT_INFO="conn / as sysdba"
# 数据库补丁存放的路径
readonly PATCH_DIR="/data/soft"
# OPATCH补丁文件名
readonly OPATCH_PATCH="p6880880_190000_Linux-x86-64.zip"
# 要求的最低opatch版本
readonly REQUIRED_OPATCH_VERSION="12.2.0.1.46"
# RU补丁文件名
readonly RU_PATCH="p37960098_190000_Linux-x86-64.zip"
# OJVM补丁文件名
readonly OJVM_PATCH="p37847857_190000_Linux-x86-64.zip"# 下面变量基本无须修改
ROLLBACK_FILE="${PATCH_DIR}/rollback_${ORACLE_SID}_$(date +%Y%m%d).sql"
LOG_DATE=$(date +%Y%m%d%H%M)
readonly SUCCESS=0
readonly FAILURE=1
LOG_FILE="${PATCH_DIR}/patch_${ORACLE_SID}_${LOG_DATE}.log"
# Log输出方式:log或cmd或all
LOG_OUT_TYPE=all
LSNR_NAME=""
DB_VERSION="19"
IS_MULTI_DB=""
OS_TYPE=""
PDB_LIST=""# 记录脚本的日志信息输出
log_info(){#判断参数个数if [ $# -eq 1 ];thenlocal log_msg=$1case $LOG_OUT_TYPE incmd)echo -e "[info]: $(date '+%Y%m%d %H:%M:%S')> ${log_msg}";;log)echo -e "[info]: $(date '+%Y%m%d %H:%M:%S')> ${log_msg}" >> "$LOG_FILE";;all)# log_info暂时不会发送邮件echo -e "[info]: $(date '+%Y%m%d %H:%M:%S')> ${log_msg}"echo -e "[info]: $(date '+%Y%m%d %H:%M:%S')> ${log_msg}" >> "$LOG_FILE";;*)esacelif [ $# -eq 2 ];thenlocal log_msg=$1case $2 incmd)echo -e "[info]: $(date '+%Y%m%d %H:%M:%S')> ${log_msg}";;log)echo -e "[info]: $(date '+%Y%m%d %H:%M:%S')> ${log_msg}" >> "$LOG_FILE";;all)echo -e "[info]: $(date '+%Y%m%d %H:%M:%S')> ${log_msg}"echo -e "[info]: $(date '+%Y%m%d %H:%M:%S')> ${log_msg}" >> "$LOG_FILE";;*)esacelseecho -e "[error]: $(date '+%Y%m%d %H:%M:%S')> the number of parameters is incorrect!"fi
}# 记录脚本的错误信息输出
log_error(){#判断参数个数if [ $# -eq 1 ];thenlocal log_msg=$1case $LOG_OUT_TYPE incmd)echo  -e  "[error]:$(date '+%Y%m%d %H:%M:%S')> ${log_msg}";;log)echo  -e  "[error]:$(date '+%Y%m%d %H:%M:%S')> ${log_msg}" >> "$LOG_FILE";;all)echo -e "[error]:$(date '+%Y%m%d %H:%M:%S')> ${log_msg}"echo -e "[error]:$(date '+%Y%m%d %H:%M:%S')> ${log_msg}" >> "$LOG_FILE";;*)esacelif [ $# -eq 2 ];thenlocal log_msg=$1case $2 incmd)echo  -e  "[error]:$(date '+%Y%m%d %H:%M:%S')> ${log_msg}";;log)echo  -e  "[error]:$(date '+%Y%m%d %H:%M:%S')> ${log_msg}" >> "$LOG_FILE";;all)echo -e "[error]:$(date '+%Y%m%d %H:%M:%S')> ${log_msg}"echo -e "[error]:$(date '+%Y%m%d %H:%M:%S')> ${log_msg}" >> "$LOG_FILE";;*)esacelseecho -e "[error]: $(date '+%Y%m%d %H:%M:%S')> the number of parameters is incorrect!"fi
}precheck() {log_info "precheck开始预检..."# 1. 检查操作系统OS_TYPE=$(uname -a | awk ' { print $1} ')log_info "当前操作系统为: "${OS_TYPE}" "if [ "$OS_TYPE" == "Linux" ];then log_info "当前操作系统为 ${OS_TYPE},检查通过"elselog_info "当前脚本没有在Linux之外平台测试过,请谨慎使用!"fi # 2. 运行脚本的当前用户检查/确认if [ "$(whoami)" != "oracle" ]; thenlog_error "必须使用oracle用户执行此脚本!"exit ${FAILURE}elselog_info "账号检查正常,当前账号为$(whoami)"fi# 3. Oracle补丁文件检查是否齐全if [[ ! -f ${PATCH_DIR}/${RU_PATCH} || ! -f ${PATCH_DIR}/${OJVM_PATCH} || ! -f ${PATCH_DIR}/${OPATCH_PATCH} ]]; thenlog_error "Oracle相关补丁文件缺失!,请检查补丁包文件是否齐全"exit ${FAILURE}elselog_info "Oracle安装升级的补丁文件齐全,如下所示:"ls -lrt ${PATCH_DIR}/${RU_PATCH}ls -lrt ${PATCH_DIR}/${OJVM_PATCH}ls -lrt ${PATCH_DIR}/${OPATCH_PATCH}fi# 4. 数据库监听服务检查确认local curr_lsn_numcurr_lsn_num=$(ps -e -o args | grep tnslsnr | grep -v grep |wc -l)if [ "${curr_lsn_num}" -eq 0 ];thenlog_info "当前环境不存在监听服务或监听服务已经关闭了"read -r  -p "请输入正确的监听服务名"  listener_nameLSNR_NAME=$(listener_name) elif [ "${curr_lsn_num}" -eq 1 ]thenLSNR_NAME=$(ps -e -o args | grep tnslsnr | grep -v grep | awk '{print $2}' | tr "[:upper:]" "[:lower:]")log_info "当前监听名称为: ${LSNR_NAME}"elif [ "${curr_lsn_num}" -gt 1 ];thenlog_info "当前环境有多个监听服务,请指定监听服务名: "read -r  -p "请输入正确的监听服务名: "  listener_nameLSNR_NAME=$(listener_name) fi # 5. 数据库实例的状态检查确认local curr_db_statuscurr_db_status=$(check_db_status)if [ "$curr_db_status" != "OPEN" ]; thenlog_error "数据库已处于关闭状态,数据库必须处于OPEN状态"exit  ${FAILURE}elseIS_MULTI_DB=$(check_db_multitenant)log_info "数据库状态为: ${curr_db_status} "fi# 5. OPatch版本检查log_info "Opatch的版本信息如下所示:"$ORACLE_HOME/OPatch/opatch version # 6. 数据库版本信息log_info "数据库的版本信息如下所示:"sqlplus -S /nolog <<EOFwhenever sqlerror exit sql.sqlcode${CONNECT_INFO}set linesize 120select banner_full from v\$version;exit;
EOF# 7. 检查失效对象信息log_info "数据库的失效对象检查."check_invalid_obj# 8. 是否继续补丁升级read -r -n1 -p "Do you want to continue installing patches? please choose the [Y/N]?" answercase $answer inY | y)log_info "precheck预检结束";;N | n)log_info "You have chosen to exit the patch installation."exit ${FAILURE};;*)log_error "your choice is wrong!"exit ${FAILURE};;esac
}check_db_version(){local curr_db_status
curr_db_status=$(check_db_status)if [ "${curr_db_status}" == "DOWN" ];
thenlog_error "the oracle instance is down, please check it"
elsedb_version_sql=$(
sqlplus -S /nolog  <<EOF |awk -F= "/^a=/ {print \$2}" 
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF
${CONNECT_INFO}
SELECT 'a='||REGEXP_SUBSTR(VERSION, '^\d+') FROM V\$INSTANCE;
EXIT
EOF)if [[ -n "${db_version_sql}"  && "${db_version_sql}" -gt 9 ]];thenDB_VERSION=${db_version_sql}elselog_error "获取Oracle数据库版本出错,请检查脚本与日志!"fi 
fi
}# 检查数据库当前状态
check_db_status() {local status=""local db_inst_num="0"db_inst_num=$(ps -ef | grep ora_pmon_${ORACLE_SID} | grep -v grep | wc -l)if [ "${db_inst_num}" -eq 0 ]; thenecho "DOWN"elsestatus=$(sqlplus -S /nolog <<EOF  | awk -F= "/^a=/ {print \$2}" set head off pagesize 0 feedback off linesize 400whenever sqlerror exit 1${CONNECT_INFO}select 'a='||status from v\$instance;exit
EOF)echo "${status}" fireturn "${SUCCESS}"
}# 检查数据库是否多租户环境
check_db_multitenant() {check_db_versionif [ "${DB_VERSION}" -ge 12 ];then IS_PDB_EXIST=$(sqlplus  -S /nolog <<EOF${CONNECT_INFO}SET HEADING OFF WHENEVER SQLERROR EXIT SQL.SQLCODESELECT COUNT(*) VALUE FROM CDB_PDBS;EXIT
EOF)if [ "$IS_PDB_EXIST" -ge 1 ];thenecho "Y"elseecho "N"fielseecho "N"fi
}# 停止监听服务
stop_listener() {if [ "$OS_TYPE" == "Linux" ] ; 
then #LSNR_NAME=`ps -ef | grep tns | grep $ORACLE_HOME | grep -v grep | awk '{ print $9 }'`LSNR_NAME=$(ps -e -o args | grep tnslsnr | grep -v grep | head -1 | awk '{print $2}' | tr "[:upper:]" "[:lower:]")
elif [ "$OS_TYPE" == "AIX" ] ; 
then#LSNR_NAME=`ps -ef | grep tns | grep $ORACLE_HOME | grep -v grep | awk '{ print $10 }'`LSNR_NAME=$(ps -ef | grep tnslsnr | grep -v grep | awk '{print $10 }')
elif [ "OS_TYPE" == "HP-UX"] ; 
thenLSNR_NAME=$(ps -ef | grep tnslsnr | grep -v grep | awk '{print $10 }')
filocal curr_lsn_num
curr_lsn_num=$(ps -ef | grep tnslsnr | grep -v grep |wc -l)if [ "$curr_lsn_num" -eq 0 ];
thenlog_info "当前环境数据库监听服务已经停止或不存在, 请检查确认!"exit ${FAILURE}
elif [ "$curr_lsn_num" -eq 1 ];
thenlsnrctl stop "$LSNR_NAME"
elif [ "$curr_lsn_num" -gt 1 ];
thenread -r -n1 -p "Do you like shutting down all listening services? please choose the [Y/N]?" answercase $answer inY | y)for lsnr_name_item in ${LSNR_NAME};dolsnrctl stop "$lsnr_name_item"done;;N | n)read -r  -p "Please specify the listener service to be stopped." curr_lsnr_namelsnrctl stop "$curr_lsnr_name";;*)log_error "your choice was wrong!"exit ${FAILURE};;esac
fi
}# 启动监听服务
start_listener() {local curr_lsn_numlocal curr_lsnr_nameif [ -z "${LSNR_NAME}" ]; thenlog_error ""${LSNR_NAME}" is null, please check it"read -r  -p "Please specify the listener service to be stopped." curr_lsnr_namelsnrctl start "$curr_lsnr_name"if [ $? -eq 0 ]; thenlog_info  "Oracle监听服务${LSNR_NAME}启动成功"elselog_error "Oracle监听服务${LSNR_NAME}启动失败"exit ${FAILURE}fielsecurr_lsn_num=$(ps -ef | grep tnslsnr | grep "${LSNR_NAME}" | grep -v grep |wc -l)if [ "$curr_lsn_num" -eq 0 ];thenlsnrctl start  "${LSNR_NAME}"if [ $? -eq 0 ]; thenlog_info  "Oracle监听服务${LSNR_NAME}启动成功"elselog_error "Oracle监听服务${LSNR_NAME}启动失败"exit ${FAILURE}fielselog_info "the listener ${LSNR_NAME} is started now"fifi
}shutdown_oracle() {local curr_db_statuscurr_db_status=$(check_db_status)# 此处只适用于Linux,HP-UX环境会报错,如需适用于HP-UX的话,其用下面注释代码#local curr_lsn_num=$(ps -ef | grep tnslsnr | grep -v grep |wc -l)local curr_lsn_numcurr_lsn_num=$(ps -e -o args | grep tnslsnr | grep -v grep |wc -l)if [ "${curr_lsn_num}" -gt 1 ];thenlog_info "当前环境中有多个监听,请新开一个窗口进行检查,并手工关闭这些监听服务."read -r -n1 -p "数据库监听服务已经关闭了吗,请输入(Y或N)"  answercase $answer inY | y)log_info "数据库监听服务已经关闭!";;N | n)log_info "You have chosen to exit the patch installation."exit ${FAILURE};;*)log_error "your choice is wrong!"exit ${FAILURE};;esacelif [ "${curr_lsn_num}" -eq 1 ];thenLSNR_NAME=$(ps -e -o args | grep tnslsnr | grep -v grep | awk '{print $2}' | tr "[:upper:]" "[:lower:]")log_info "Listener Name: ${LSNR_NAME}"lsnrctl stop "${LSNR_NAME}"if [ $? -eq 0 ];thenlog_info "stop the Listener  ${LSNR_NAME} successed."elselog_error "stop the listener ${LSNR_NAME} failed ,please check the log"exit ${FAILURE}fielselog_info "the Listener ${LSNR_NAME} is stopped status. it does not need to stop it!"fiif [ "${curr_db_status}" == "DOWN" ]; thenlog_info "数据库已处于关闭状态,无需关闭数据库实例!"return  ${SUCCESS}else sqlplus -S /nolog <<EOFwhenever sqlerror exit sql.sqlcode${CONNECT_INFO}shutdown immediate;exit;
EOFif [ $? -eq 0 ];thenlog_info  "Oracle instance shutdown done.\n"elselog_error "Oracle instance shutdown failed.\n"exit ${FAILURE}fiINSTANCE_STATUS=$(check_db_status)if [  "$INSTANCE_STATUS" == "DOWN" ];thenlog_info "Oracle instance is shutdown now"elselog_error "the oracle instance status is ${INSTANCE_STATUS}, pleas check it "exit $FAILUREfifi
}start_oracle() {start_listenercurr_db_status=$(check_db_status)if [ "$curr_db_status" == "DOWN" ]; thenif [ "${IS_MULTI_DB}" == "Y" ];thensqlplus -S /nolog <<EOF
whenever sqlerror exit sql.sqlcode
${CONNECT_INFO}  
startup;
alter pluggable database all open;
alter pluggable database all save state;  
exit;
EOFif [ $? -eq 0 ]; thenlog_info  "Oracle数据库实例启动成功"elselog_error "Oracle数据库实例启动失败"exit ${FAILURE}fielsesqlplus -S /nolog <<EOF
whenever sqlerror exit sql.sqlcode
${CONNECT_INFO}  
startup;
exit;
EOFif [ $? -eq 0 ]; thenlog_info  "Oracle数据库实例${ORACLE_SID}启动成功"elselog_error "Oracle数据库实例${ORACLE_SID}启动失败"exit ${FAILURE}fifificurr_db_status=$(check_db_status)if [ "${curr_db_status}" != "OPEN" ]thenlog_error "Oracle数据库实例${ORACLE_SID}启动失败.\n"exit ${FAILURE}elselog_info "Oracle数据库实例${ORACLE_SID}启动成功\n"   fi
}# 返回PDB数据库列表
get_pdb_list() {PDB_LIST=$(sqlplus -S /nolog <<EOF
${CONNECT_INFO}
set pagesize 0 feedback off verify off heading off echo off
select 'CDB\$ROOT' name from dual union all
select name from v\$pdbs where open_mode = 'READ WRITE';
exit;
EOF
)if [ $? -eq 0 ];
thenreturn ${SUCCESS}
elsereturn ${FAILURE}
fi}
# =============== 备份模块 ===============
create_backup() {log_info ">>> 创建回滚点..."sqlplus -S / as sysdba <<EOF > "$ROLLBACK_FILE"
set serveroutput on
exec dbms_qopatch.get_sqlpatch_status;
exit;
EOFlog_info ">>> 备份重要文件:"$ORACLE_HOME/OPatch/opatch lsinventory -detail > ${PATCH_DIR}/inventory_bak_"$(date +%s)".txt#cp ${ORACLE_HOME}/sqlpatch/sqlpatch_bundle/* ${PATCH_DIR}/sqlpatch_bak_$(date +%s)/
}# 版本比较函数(处理形如x.y.z.a的版本格式)
version_ge() {# 比较版本:如果$1 ≥ $2则返回0(成功),否则返回1[ "$(printf "%s\n%s" "$2" "$1" | sort -V | head -n1)" = "$2" ]
}opatch_upgrade() {local -r patch_file=$1# 定义OPatch路径
local -r OPATCH_CMD="${ORACLE_HOME}/OPatch/opatch"if [ -f "${PATCH_DIR}/${patch_file}" ];
thenunzip -o "${PATCH_DIR}/${patch_file}" -d ${PATCH_DIR}PATCH_NAME=$(unzip -l "${PATCH_DIR}/${patch_file}" | awk '/\/$/ {print $4}' | cut -d'/' -f1 | sort -u)cd "${PATCH_DIR}" || exitif [ -d "${ORACLE_HOME}/OPatch" ];then# 备份旧的OPatch目录mv "${ORACLE_HOME}/OPatch"  "${ORACLE_HOME}/OPatch.${LOG_DATE}"cp -rp "${PATCH_DIR}/${PATCH_NAME}" "${ORACLE_HOME}/OPatch"elselog_error "error, please check it"exit ${FAILURE}fi# 检查opatch可执行文件是否存在if [ ! -x "${OPATCH_CMD}" ]; thenlog_error "错误:OPatch工具不存在或不可执行,路径:${OPATCH_CMD}"exit ${FAILURE}fi# 获取当前OPatch版本log_info "正在检查OPatch版本..."CURRENT_OPATCH_VERSION=$("${OPATCH_CMD}" version | awk '/OPatch Version/ {print $3}')if [ -z "${CURRENT_OPATCH_VERSION}" ]; thenlog_error "错误:无法获取OPatch版本信息"exit ${FAILURE}filog_info "当前OPatch版本:${CURRENT_OPATCH_VERSION}"log_info "要求的最低OPatch版本:${REQUIRED_OPATCH_VERSION}"# 检查版本是否符合要求if version_ge "${CURRENT_OPATCH_VERSION}" "${REQUIRED_OPATCH_VERSION}"; thenlog_info "OPatch版本符合要求"return $SUCCESSelselog_error "OPatch版本不符合要求,请升级至${REQUIRED_OPATCH_VERSION}或更高版本"exit ${FAILURE}fi"${ORACLE_HOME}"/OPatch/opatch version | grep -q "${OPATCH_VER}" || {log_error "错误:OPatch版本不满足要求!"exit ${FAILURE}}
fi}
# =============== 补丁应用模块 ===============
apply_patch() {local patch_file=$1local patch_type=$2log_info "应用${patch_type}补丁:$(basename "${patch_file}")"unzip -o "${PATCH_DIR}/${patch_file}" -d "${PATCH_DIR}"#PATCH_NAME=$(basename $patch_file .zip)PATCH_NAME=$(unzip -l "${PATCH_DIR}/${patch_file}" | awk '/\/$/ {print $4}' | cut -d'/' -f1 | sort -u)cd "${PATCH_DIR}/${PATCH_NAME}" || exit"${ORACLE_HOME}"/OPatch/opatch prereq CheckConflictAgainstOHWithDetail -ph ."${ORACLE_HOME}"/OPatch/opatch apply -silent if [ $? -eq 0 ];thenlog_info "Oracle RU patch  apply success"elselog_error "Oracle RU patch  apply failed ,please check the log "exit ${FAILURE}fi}data_patch() {start_oracle$ORACLE_HOME/OPatch/datapatch -verboseif [ $? -eq 0 ];thenlog_info "Oracle PUS patch success"elselog_error "Oracle PUS patch failed ,please check the log "exit ${FAILURE}fi}prepare_run_sql(){local -r sql_cmd_text="GRANT EXECUTE ON  HTTPURITYPE TO PUBLIC;"if [ "$IS_MULTI_DB" == "N" ];
thensqlplus -S /nolog <<EOF${CONNECT_INFO}whenever sqlerror exit sql.sqlcode${sql_cmd_text}exit;
EOFif [ $? -eq 0 ];thenlog_info "在$pdb_name中执行SQL结束..."elselog_error "在$pdb_name中执行SQL: ${sql_cmd_text} 异常"exit ${FAILURE}fielseif ! get_pdb_list; thenexit ${FAILURE}fi # 检查是否获取到PDB列表if [ -z "$PDB_LIST" ]; thenlog_error "错误: 未能获取到PDB列表,请检查数据库连接"exit ${FAILURE}fi# 在每个PDB中执行SQL语句for pdb_name in  ${PDB_LIST};doif [ -n "$pdb_name" ]; thenlog_info "在$pdb_name中执行SQL开始..."# 执行SQL语句sqlplus -S /nolog <<EOFwhenever sqlerror exit sql.sqlcode${CONNECT_INFO}ALTER SESSION SET CONTAINER="$pdb_name";${sql_cmd_text}exit;
EOFif [ $? -eq 0 ];thenlog_info "在$pdb_name中执行SQL结束..."elselog_error "在$pdb_name中执行SQL: ${sql_cmd_text} 异常"exit ${FAILURE}fifidone
fi}check_invalid_obj() {local sql_cmd_text=""if [ "$IS_MULTI_DB" == "Y" ];
thenif ! get_pdb_list; thenexit ${FAILURE}fi # 检查是否获取到PDB列表if [ -z "$PDB_LIST" ]; thenlog_error "错误: 未能获取到PDB列表,请检查数据库连接"exit ${FAILURE}fi# 在每个PDB中执行SQL语句for pdb_name in  ${PDB_LIST};doif [ -n "$pdb_name" ]; thensql_cmd_text="${CONNECT_INFO}whenever sqlerror exit sql.sqlcodeset serveroutput on;ALTER SESSION SET CONTAINER="$pdb_name";set linesize 720set pagesize 60col object_name for a40col object_type for a15col owner for a10select object_name,object_type,owner,status from dba_objects where status<>'VALID' order by owner,object_name;exit;"log_info "正在 $pdb_name 中执行SQL..."# 执行SQL语句sqlplus -S /nolog <<EOF${sql_cmd_text}
EOFif [ $? -eq 0 ];thenlog_info "$pdb_name 中检查无效对象完成."elselog_error "$pdb_name 中检查无效对象异常."exit $FAILUREfifidone
elsesql_cmd_text="${CONNECT_INFO}whenever sqlerror exit sql.sqlcodeset serveroutput on;set linesize 720set pagesize 60col object_name for a40col object_type for a15col owner for a10select object_name,object_type,owner,status from dba_objects where status<>'VALID' order by owner,object_name;exit;"log_info "正在 $pdb_name 中执行SQL..."# 执行SQL语句sqlplus -S /nolog <<EOF${sql_cmd_text}
EOFif [ $? -eq 0 ];thenlog_info "$pdb_name 中检查无效对象完成."elselog_error "$pdb_name 中检查无效对象异常."exit $FAILUREfifi}recompile_invalid_obj() {local sql_cmd_text=""if [ "$IS_MULTI_DB" == "N" ];
thensql_cmd_text="${CONNECT_INFO}whenever sqlerror exit sql.sqlcodeset serveroutput on;@?/rdbms/admin/utlrp.sqlexit;"# 执行SQL语句sqlplus -S /nolog <<EOF${sql_cmd_text}
EOFif [ $? -eq 0 ];thenlog_info "在$pdb_name 中执行脚本utlrp.sql完成..."elselog_error "在$pdb_name 中执行脚本utlrp.sql出现异常..."exit ${FAILURE}fi
elseif ! get_pdb_list; thenexit ${FAILURE}fi # 检查是否获取到PDB列表if [ -z "$PDB_LIST" ]; thenlog_error "错误: 未能获取到PDB列表,请检查数据库连接"exit ${FAILURE}fi# 在每个PDB中执行SQL语句for pdb_name in  ${PDB_LIST};doif [ -n "$pdb_name" ]; thenlog_info "正在$pdb_name中执行脚本utlrp.sql开始..."sql_cmd_text="${CONNECT_INFO}whenever sqlerror exit sql.sqlcodeset serveroutput on;ALTER SESSION SET CONTAINER="$pdb_name";@?/rdbms/admin/utlrp.sqlexit;"# 执行SQL语句sqlplus -S /nolog <<EOF${sql_cmd_text}
EOFif [ $? -eq 0 ];thenlog_info "在$pdb_name 中执行脚本utlrp.sql完成..."elselog_error "在$pdb_name 中执行脚本utlrp.sql出现异常..."exit ${FAILURE}fifidone
fi
}check_patch_info() {log_info "执行检查补丁信息如下所示:"# 执行SQL语句sqlplus -S /nolog <<EOFwhenever sqlerror exit sql.sqlcode${CONNECT_INFO}ALTER SESSION SET CONTAINER="$pdb_name";set serveroutput on;set linesize 640;set pagesize 40;column action_time for a19column action format a16column version format a26column id for 99column comments format a30column bundle_series format a10select to_char(action_time, 'yyyy-mm-dd hh24:mi:ss') as action_time, action, version, id, comments, bundle_series from sys.registry\$historyorder by action_time;set linesize 640;set serveroutput on;col description for a30;    col action_time for a30 ;   select patch_id, patch_uid,action, status,action_time,description from dba_registry_sqlpatch;set linesize 720col version_full for a19col status for a10;col modified for a20;select version,version_full,status,modifiedfrom dba_registry;exit;
EOFif [ $? -ne 0 ];then log_error "执行检查补丁信息的SQL语句出现错误,请检查确认!"exit ${FAILURE}fi}main() {#执行预检precheck# 特殊授权prepare_run_sql#创建备份create_backup#升级opatchopatch_upgrade $OPATCH_PATCH#关闭数据库实例shutdown_oracle#应用RU补丁apply_patch $RU_PATCH "RU"#应用OJVM补丁apply_patch $OJVM_PATCH "OJVM"#数据库data patchdata_patch# 最终验证log_info ">>> 验证补丁状态:"$ORACLE_HOME/OPatch/opatch lspatches$ORACLE_HOME/OPatch/opatch lsinventory | grep -E "${RU_PATCH%.*}|${OJVM_PATCH%.*}"log_info ">>>>>> 升级成功!请执行健康检查脚本验证数据库状态 <<<<<<"check_invalid_objrecompile_invalid_objcheck_patch_info}# 执行主函数
main | tee -a "${LOG_FILE}"

微信公众号的文章保存时,部分代码经常会出现部分单词间的空格被"自动删除", 所以建议你从下面的原文或
百度网盘链接获取源代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/921228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

域名不变 网站改版如何知道网站开发语言

2019独角兽企业重金招聘Python工程师标准>>> 前景 Python在编程领域的占有率一直处于稳步上升之中&#xff0c;根据最新的数据&#xff0c;Python排名第六。前五名分别是 Java、C、PHP、C 和 VB. 作为一个很年轻的语言&#xff0c;Python的位置已经相当令人振奋了。…

数据类型-列表

列表 (可变类型):info= ["guohan",1,"222","xxx"] 公共功能:1.索引:  info[0]>>>"guohan"2.切片:  info[1;3]>>>[1,"222"]3步长:  …

2025/9/28

2025/9/28今日:1.学习离散数学 2.继续学习算法

网站内容页怎么设计网络优化行业怎么样

一、查看开机自启项1.Centos7自启项查看方式从Centos6的chkconfig改为&#xff1a;systemctl list-unit-files2.用grep过滤查看&#xff0c;比如&#xff1a;查看启动项&#xff1a;systemctl list-unit-files | grep enable查看sshd服务自启动情况&#xff1a;systemctl list-…

智表 ZCELL:纯前端 Excel 导入导出的高效解决方案,让数据处理更轻松

在当今数字化时代,数据处理已成为各行各业日常工作的重要组成部分,而 Excel 作为常用的数据处理工具,其导入导出功能的高效性和便捷性直接影响着工作效率。传统的 Excel 导入导出往往需要依赖后端服务,不仅流程繁琐…

采用IOT-Tree消息流MQTT模块节点实现监测数据推送功能

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

【MySQL 高阶】MySQL 架构与存储引擎全面详解 - 实践

【MySQL 高阶】MySQL 架构与存储引擎全面详解 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&quo…

两学一做网站进不去织梦物流公司网站模板简洁大气

图文&#xff1a;udb311主题&#xff1a;MSSQL内网渗透案例分析发表&#xff1a;黑白前线描述&#xff1a;对于内网渗透技术一直感觉很神秘&#xff0c;手中正巧有一个webshell是内网服务器。借此机会练习下内网入侵渗透技术&#xff01;本文敏感信息以屏蔽&#xff01;密码都以…

ISO 雨晨 26200.6588 Windows 11 企业版 LTSC 25H2 自用 edge 140.0.3485.81 - 教程

ISO 雨晨 26200.6588 Windows 11 企业版 LTSC 25H2 自用 edge 140.0.3485.81 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; fo…

做淘宝美工图片网站常用的行业管理系统

一、概念: ①类似于仓库,空间内存储代码,需要用到时调用②也为防止名字冲突提供了更加可控的机制二、命名空间的定义 定义的基本格式如下:namespace 命名空间名 { //一系列声明与定义 };三、命名空间的注意事项 命名空间定义时最后的分号可有可无只要出现在全局作用域中的…

网站推广营销效果网站制作协议

建议对ionic和AnjularJs有一定了解的人可以用到&#xff0c;很多时候我们要用到选择省份、城市、区县的功能&#xff0c;现在就跟着我来实现这个功能吧&#xff0c;用很少的代码&#xff08;我这里是根据客户的要求&#xff0c;只显示想要显示的部分省份和其相对应的城市、区县…

企业网站设计文档菏泽做网站优化的

近日&#xff0c;江苏省数字经济学会公布了2023年度江苏省数字经济学会科学技术奖获奖名单。本次在全省范围内共评选出科学技术进步奖、科学技术创新奖、优秀成果奖获奖项目共计19项。“聚合数据资产服务API平台”凭借其前沿的创新性和优秀的应用前景成功获得科学技术创新奖二等…

lc1039-多边形三角剖分的最低得分

难度:中等(温天仁是吧,压境界了)题目描述有一个凸的 n 边形,其每个顶点都有一个整数值 将其剖分为 n-2 个三角形 每个三角形的值都是其三个顶点值的乘积 返回剖分后可以得到的最低分示例输入:values = [3,7,4,5]…

Powershell 进阶语(三)

本篇介绍pwsh的管道用法,补充剩下的进阶语法。目录PowerShell 管道管道输出控制管道输出的格式设置Format-ListFormat-TableFormat-Wide管道选择、排序和度量对象排序和分组Sort-ObjectFormat 的 GroupBy分组度量管道…

随机函数

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

集合进阶-collection集合

细节: collection遍历方式1:迭代器 遍历时不可以删除或者添加元素 增强for遍历(用来简化迭代器书写): 直接数组名.for快速生成 lambda表达式遍历:

工装设计方案网站做网站什么都不懂 怎么做

此博客用于记录2020年9月25日每日分享&#xff0c; 大概讲讲团队里的分工合作那些事儿。 关于带宽啊&#xff0c;网速啊之类的一些事儿 日期&#xff1a;2020年9月25日 主题&#xff1a; 团队合作怎么合作&#xff1f;有什么人&#xff1f;一般用什么工具&#xff1f;诸如此类…

完整教程:前端学习-HTML

完整教程:前端学习-HTML2025-09-28 22:13 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; fo…

素数定理的初等证明

可能有错误,欢迎指出x零、基本介绍 此文中 \(\log\) 指代自然对数,记 \(p, q, r\) 为素数,分解 \(n = p_1^{\alpha_1}p_2^{\alpha_2} \cdots p_m^{\alpha_m}\)。 令 \(\displaystyle \pi(x) = \sum [0 \le p \le x]…

sql2008做网站重庆今天的新消息

对于一个 .NET Core开发人员&#xff0c;你可能没有使用过Docker&#xff0c;但是你不可能没有听说过Docker。Docker是Github上最受欢迎的开源项目之一&#xff0c;它号称要成为所有云应用的基石&#xff0c;并把互联网升级到下一代。Docker是dotCloud公司开源的一款产品&#…