分享一个oracle全版本的RAC部署脚本

!/bin/bash

=============================================================================

oracle_deploy.sh v2.1

Oracle 一键部署:single(单实例/文件系统)| standalone(单实例+GI+ASM)| rac

版本:11G / 12C(12.1) / 12.2 / 18C / 19C / 21C / 23AI

-----------------------------------------------------------------------------

说明:

1. 版本差异集中在 load_profile(),安装主流程与版本解耦;

2. 参数支持任意顺序、-k=v 与 -k v 两种写法,并按模式校验必填项;

3. OS 初始化脚本幂等,单机与 RAC 共用同一份;

4. 响应文件统一由函数生成;

5. 安装等待改为精确匹配+超时,避免死循环。

=============================================================================

set -o pipefail
SOFT_DIR=${SOFT_DIR:-/soft}

ORA_BASE=/u01/app/oracle

GRID_BASE=/u01/app/grid

INVENTORY=/u01/app/oraInventory

ASM_DISK_DIR=/dev/oracleasm/disks
DB_TYPE=""; OP="install"; HA=""; VER=""

PUBLIC_IP=""; NODE_NAME=""; ROOT_PWD=""; DB_PWD=""; DB_SID=""

USE_CDB="false"; PDB_NAME=""; DB_CHARSET=""; DB_NCHARSET=""; YUM_SRC=""

PUB1=""; PUB2=""; VIP1=""; VIP2=""; PRIV1=""; PRIV2=""; SCAN_IP=""

PUB_IF=""; PRIV_IF=""; OCR_REDU=""; OCR_DISKS=""; DATA_REDU=""; DATA_DISKS=""

DB_ZIP_OVERRIDE=""; GRID_ZIP_OVERRIDE=""
ORA_NUMBER=""; ORA_NUMBER_S=""; ORACLE_HOME=""; GRID_HOME=""

DB_ZIP=""; GRID_ZIP=""; DB_MEDIA_MODE=""; GRID_MEDIA_MODE=""

AU_SIZE=""; SUPPORTS_CDB=0; CDB_REQUIRED=0

RSP_DB_SCHEMA=""; RSP_GRID_SCHEMA=""; RSP_DBCA_SCHEMA=""

MIN_MEM_SINGLE=""; MIN_MEM_RAC=""; IGNORE_FLAG=""; YUM_CMD=""
PROG=(basename "0")

LOG_FILE={LOG_FILE:-/tmp/oracle_deploy_(date +%Y%m%d_%H%M%S).log}

START_TIME=$(date +%s)
log(){

local msg

msg="(date '+%F %T') "
printf '%s\n' "msg" printf '%s\\n' "msg" >>"LOG_FILE" 2\>/dev/null \|\| true } die(){ log "ERROR:
"; exit 1; }

run_as(){ local u=1; shift; su - "u" -c "(printf '%q ' "@")"; }

cidr24(){ echo "1" \| awk -F. '{print 1"."2"."3".0"}'; }
cleanup(){

local rc=$?

if (( rc != 0 )); then

log "脚本异常退出 (rc=rc),日志: LOG_FILE"

else

log "脚本执行完成,耗时 (( (date +%s) - START_TIME ))s,日志: $LOG_FILE"

fi

}

trap cleanup EXIT

-----------------------------------------------------------------------------

帮助

-----------------------------------------------------------------------------

usage(){

cat <<EOF

Usage: {PROG} -dt=oracle -op=install -ht= -v= \[options\] {PROG} -h | --help | -help | help
-ht single 单实例(文件系统)

standalone 单实例 + Grid Infrastructure + ASM(原 ha)

rac 两节点 RAC
-v 11G | 12C | 12.2 | 18C | 19C | 21C | 23AI

11G / 12C 使用解压式安装介质,12.2 及以上使用 image 方式
通用参数:

-i <public_ip> 主机 IP

-n
主机名前缀(自动追加 db / db1、db2)
-dp oracle/grid 系统用户口令,SYS/SYSTEM 等口令
-o <oracle_sid> 数据库 SID
-cdb <true|false> 是否 CDB(11G 忽略;21C/23AI 强制 TRUE)
-pdbname PDB 名称(CDB 时默认 pdb)
-cs 字符集,如 ZHS16GBK / AL32UTF8
-ncs 国家字符集,如 AL16UTF16 / UTF8
-yum </dev/cdrom|xxx.iso> 本地 yum 源
RAC / standalone 专用:

-rp <root_password> 节点 root 口令(用于配置互信,RAC 必填)

-pu1/-pu2
node1/node2 公网 IP
-vi1/-vi2 node1/node2 VIP(兼容旧写法 -vip1/-vip2)
-pr1/-pr2 node1/node2 私网 IP
-si <scan_ip> SCAN IP
-puf -prf 公网/私网网卡名
-or <HIGH|NORMAL|EXTERNAL> OCR 冗余
-od </dev/sdb,...> OCR 磁盘
-dr <HIGH|NORMAL|EXTERNAL> 数据盘冗余
-dd </dev/sde,...> 数据磁盘
可选覆盖:

-dbzip "a.zip b.zip" 覆盖默认数据库安装介质文件名

-gridzip "g.zip" 覆盖默认 Grid 安装介质文件名
日志:

可通过环境变量 LOG_FILE 覆盖日志路径,默认 /tmp/oracle_deploy_<时间戳>.log
示例(19C 单实例):

./${PROG} -dt=oracle -op=install -ht=single -v=19C \

-i=192.168.220.100 -n=orcl -dp=Enmo_1234 -o=orcl \

-cdb=false -pdbname=pdb -cs=ZHS16GBK -ncs=AL16UTF16 -yum=/dev/cdrom
示例(19C RAC):

./${PROG} -dt=oracle -op=install -ht=rac -v=19C \

-i=192.168.220.100 -n=enmo -rp=123456 -dp=Enmo_1234 -o=orcl \

-cdb=true -pdbname=pdb -cs=ZHS16GBK -ncs=AL16UTF16 -yum=/dev/cdrom \

-pu1=192.168.220.100 -pu2=192.168.220.102 \

-vi1=192.168.220.103 -vi2=192.168.220.104 \

-pr1=192.168.220.100 -pr2=192.168.220.102 -si=192.168.220.240 \

-puf=eth0 -prf=eth1 -or=EXTERNAL -od=/dev/sdb,/dev/sdc \

-dr=EXTERNAL -dd=/dev/sde,/dev/sdf

EOF

}

-----------------------------------------------------------------------------

参数解析

-----------------------------------------------------------------------------

is_known_opt(){

case $1 in

-dt|--db-type|-op|--operation|-ht|--ha-type|-v|--version|-i|--ip|-n|--name|

-rp|-dp|-o|-cdb|-pdbname|-cs|-ncs|-yum|-pu1|-pu2|-vi1|-vi2|-vip1|-vip2|

-pr1|-pr2|-si|-scan|-puf|-prf|-or|-od|-dr|-dd|-dbzip|-gridzip|-h|--help|-help)

return 0 ;;

*) return 1 ;;

esac

}
set_param(){

local k=1 v=2

case $k in

-dt|--db-type) DB_TYPE=$v ;;

-op|--operation) OP=$v ;;

-ht|--ha-type) HA=$v ;;

-v|--version) VER=$v ;;

-i|--ip) PUBLIC_IP=$v ;;

-n|--name) NODE_NAME=$v ;;

-rp) ROOT_PWD=$v ;;

-dp) DB_PWD=$v ;;

-o) DB_SID=$v ;;

-cdb) USE_CDB=$v ;;

-pdbname) PDB_NAME=$v ;;

-cs) DB_CHARSET=$v ;;

-ncs) DB_NCHARSET=$v ;;

-yum) YUM_SRC=$v ;;

-pu1) PUB1=$v ;;

-pu2) PUB2=$v ;;

-vi1|-vip1) VIP1=$v ;;

-vi2|-vip2) VIP2=$v ;;

-pr1) PRIV1=$v ;;

-pr2) PRIV2=$v ;;

-si|-scan) SCAN_IP=$v ;;

-puf) PUB_IF=$v ;;

-prf) PRIV_IF=$v ;;

-or) OCR_REDU=$v ;;

-od) OCR_DISKS=$v ;;

-dr) DATA_REDU=$v ;;

-dd) DATA_DISKS=$v ;;

-dbzip) DB_ZIP_OVERRIDE=$v ;;

-gridzip) GRID_ZIP_OVERRIDE=$v ;;

*) die "未知参数: $k" ;;

esac

}
parse_args(){

(( $# == 0 )) && { usage; exit 1; }

while (( $# )); do

case $1 in

-h|--help|-help|help) usage; exit 0 ;;

--) shift; break ;;

-= )

set_param "{1%%=*}" "{1#* =}"; shift ;;

-*)

(( # \>= 2 )) \|\| die "参数 1 缺少取值"

is_known_opt "2" \&\& die "参数 1 缺少取值(下一个是参数 $2)"

set_param "1" "2"; shift 2 ;;

) die "无法识别的参数: 1" ;; esac done (( # == 0 )) || die "存在无法解析的尾部参数: $ "

}

-----------------------------------------------------------------------------

参数规范化与校验

-----------------------------------------------------------------------------

normalize_inputs(){

DB_TYPE={DB_TYPE,,}; OP={OP,,}; HA={HA,,}; VER=
\[ -n $DB_TYPE ] || { usage; die "必须指定 -dt=oracle"; }

\[ $DB_TYPE == oracle ] || die "本版本仅支持 -dt=oracle"

\[ $OP == install ] || die "当前仅支持 -op=install"
case $HA in

single) ;;

standalone|ha) HA=standalone ;;

rac) ;;

*) die "-ht 仅支持 single / standalone / rac" ;;

esac

}
load_profile(){

case $VER in

11G|11.2|11.2.0|112)

VER=11G

ORA_NUMBER=11.2.0; ORA_NUMBER_S=11.2

RSP_DB_SCHEMA=v11_2_0; RSP_GRID_SCHEMA=v11_2_0; RSP_DBCA_SCHEMA=11.2.0

DB_MEDIA_MODE=extract; GRID_MEDIA_MODE=extract

DB_ZIP="p13390677_112040_Linux-x86-64_1of7.zip p13390677_112040_Linux-x86-64_2of7.zip"

GRID_ZIP="p13390677_112040_Linux-x86-64_3of7.zip"

AU_SIZE=1; SUPPORTS_CDB=0; CDB_REQUIRED=0

MIN_MEM_SINGLE=2048; MIN_MEM_RAC=2560

IGNORE_FLAG="-ignoreSysPrereqs -ignorePrereq" ;;

12C|12.1|121)

VER=12C

ORA_NUMBER=12.1.0; ORA_NUMBER_S=12.1

RSP_DB_SCHEMA=v12_1_0; RSP_GRID_SCHEMA=v12_1_0; RSP_DBCA_SCHEMA=12.1.0

DB_MEDIA_MODE=extract; GRID_MEDIA_MODE=extract

DB_ZIP="linuxamd64_12102_database_1of2.zip linuxamd64_12102_database_2of2.zip"

GRID_ZIP="linuxamd64_12102_grid_1of2.zip linuxamd64_12102_grid_2of2.zip"

AU_SIZE=4; SUPPORTS_CDB=1; CDB_REQUIRED=0

MIN_MEM_SINGLE=2048; MIN_MEM_RAC=4096

IGNORE_FLAG="-ignoreSysPrereqs -ignorePrereq" ;;

12.2|122)

VER=12.2

ORA_NUMBER=12.2.0; ORA_NUMBER_S=12.2

RSP_DB_SCHEMA=v12_2_0; RSP_GRID_SCHEMA=v12_2_0; RSP_DBCA_SCHEMA=12.2.0

DB_MEDIA_MODE=image; GRID_MEDIA_MODE=image

DB_ZIP=LINUX.X64_122010_db_home.zip; GRID_ZIP=LINUX.X64_122010_grid_home.zip

AU_SIZE=4; SUPPORTS_CDB=1; CDB_REQUIRED=0

MIN_MEM_SINGLE=2048; MIN_MEM_RAC=4096

IGNORE_FLAG="-ignorePrereqFailure" ;;

18C|18.0|18)

VER=18C

ORA_NUMBER=18.0.0; ORA_NUMBER_S=18.0

RSP_DB_SCHEMA=v18.0.0; RSP_GRID_SCHEMA=v18.0.0; RSP_DBCA_SCHEMA=18.0.0

DB_MEDIA_MODE=image; GRID_MEDIA_MODE=image

DB_ZIP=LINUX.X64_180000_db_home.zip; GRID_ZIP=LINUX.X64_180000_grid_home.zip

AU_SIZE=4; SUPPORTS_CDB=1; CDB_REQUIRED=0

MIN_MEM_SINGLE=2048; MIN_MEM_RAC=8192

IGNORE_FLAG="-ignorePrereqFailure" ;;

19C|19.0|19)

VER=19C

ORA_NUMBER=19.3.0; ORA_NUMBER_S=19.0

RSP_DB_SCHEMA=v19.0.0; RSP_GRID_SCHEMA=v19.0.0; RSP_DBCA_SCHEMA=19.0.0

DB_MEDIA_MODE=image; GRID_MEDIA_MODE=image

DB_ZIP=LINUX.X64_193000_db_home.zip; GRID_ZIP=LINUX.X64_193000_grid_home.zip

AU_SIZE=4; SUPPORTS_CDB=1; CDB_REQUIRED=0

MIN_MEM_SINGLE=2048; MIN_MEM_RAC=8192

IGNORE_FLAG="-ignorePrereqFailure" ;;

21C|21.0|21)

VER=21C

ORA_NUMBER=21.3.0; ORA_NUMBER_S=21.0

RSP_DB_SCHEMA=v21.0.0; RSP_GRID_SCHEMA=v21.0.0; RSP_DBCA_SCHEMA=21.0.0

DB_MEDIA_MODE=image; GRID_MEDIA_MODE=image

DB_ZIP=LINUX.X64_213000_db_home.zip; GRID_ZIP=LINUX.X64_213000_grid_home.zip

AU_SIZE=4; SUPPORTS_CDB=1; CDB_REQUIRED=1

MIN_MEM_SINGLE=2048; MIN_MEM_RAC=8192

IGNORE_FLAG="-ignorePrereqFailure" ;;

23AI|23C|23.0|23)

VER=23AI

ORA_NUMBER=23.0.0; ORA_NUMBER_S=23.0

RSP_DB_SCHEMA=v23.0.0; RSP_GRID_SCHEMA=v23.0.0; RSP_DBCA_SCHEMA=23.0.0

DB_MEDIA_MODE=image; GRID_MEDIA_MODE=image

DB_ZIP=LINUX.X64_230000_db_home.zip; GRID_ZIP=LINUX.X64_230000_grid_home.zip

AU_SIZE=4; SUPPORTS_CDB=1; CDB_REQUIRED=1

MIN_MEM_SINGLE=2048; MIN_MEM_RAC=8192

IGNORE_FLAG="-ignorePrereqFailure" ;;

*) die "不支持的版本: $VER(支持 11G/12C/12.2/18C/19C/21C/23AI)" ;;

esac
\[ -n $DB_ZIP_OVERRIDE ] && DB_ZIP=$DB_ZIP_OVERRIDE

\[ -n $GRID_ZIP_OVERRIDE ] && GRID_ZIP=GRID_ZIP_OVERRIDE ORACLE_HOME={ORA_BASE}/product/${ORA_NUMBER}/dbhome_1

GRID_HOME=/u01/app/${ORA_NUMBER}/grid

}
require()
validate_params(){

require "-i" "$PUBLIC_IP"

require "-n" "$NODE_NAME"

require "-dp" "$DB_PWD"

require "-o" "$DB_SID"

require "-cs" "$DB_CHARSET"

require "-ncs" "$DB_NCHARSET"

require "-yum" "YUM_SRC" \[\[ DB_SID =~ [[1]](#[1])A-Za-z0-9_#${0,7} \]\] \|\| die "SID 非法: DB_SID"

\[ $NODE_NAME =\~ ^[\[2](#[2])^A-Za-z0-9-* \]\] \|\| die "主机名前缀非法: NODE_NAME"
if \[ $HA != single ]; then

require "-or" "OCR_REDU"; require "-od" "OCR_DISKS"

require "-dr" "DATA_REDU"; require "-dd" "DATA_DISKS"

fi
if \[ $HA == rac ]; then

require "-rp" "$ROOT_PWD"

require "-pu1" "PUB1"; require "-pu2" "PUB2"

require "-vi1" "VIP1"; require "-vi2" "VIP2"

require "-pr1" "PRIV1"; require "-pr2" "PRIV2"

require "-si" "$SCAN_IP"

require "-puf" "PUB_IF"; require "-prf" "PRIV_IF"

\[ $NODE_NAME == \*\[0-9 ]] && log "WARN: -n 末尾含数字,RAC 主机名将拼接为 {NODE_NAME}db1/{NODE_NAME}db2"

fi
if (( SUPPORTS_CDB == 0 )); then

\[ ${USE_CDB,,} == true ] && log "WARN: $VER 不支持 CDB,已强制 -cdb=false"

USE_CDB=FALSE; PDB_NAME=""

else

case ${USE_CDB,,} in

true|yes|1) USE_CDB=TRUE ;;

*) USE_CDB=FALSE ;;

esac

(( CDB_REQUIRED == 1 )) && USE_CDB=TRUE

if \[ $USE_CDB == TRUE ]; then

PDB_NAME=${PDB_NAME:-pdb}

else

PDB_NAME=""

fi

fi

}
resolve_yum_cmd(){

case $YUM_SRC in

/dev/cdrom) YUM_CMD="mount /dev/cdrom /mnt" ;;

*.iso) \[ -f $YUM_SRC ] || die "yum 镜像不存在: $YUM_SRC"

YUM_CMD="mount -o loop $YUM_SRC /mnt" ;;

*) die "-yum 仅支持 /dev/cdrom 或本地 iso 文件" ;;

esac

}

-----------------------------------------------------------------------------

预检查

-----------------------------------------------------------------------------

os_major(){

if \[ -r /etc/redhat-release ]; then

grep -oE '0-9+' /etc/redhat-release | head -1

elif \[ -r /etc/os-release ]; then

( . /etc/os-release; echo "${VERSION_ID%%.*}" )

else

echo 0

fi

}
precheck(){

log "===== 环境预检查 ====="

\[ $EUID -eq 0 ] || die "请以 root 运行"

\[ $NODE_NAME =\~ \^localhost ] && die "hostname 非法: $NODE_NAME"

\[ $PUBLIC_IP == 127.0.0.1 ] && die "IP 非法: PUBLIC_IP" local major; major=(os_major)

case $major in

7|8|9) log "OS major version: $major" ;;

*) die "仅支持 RHEL/OEL 7/8/9,当前: $major" ;;

esac

\[ $VER == 23AI \&\& $major -lt 8 ] && log "WARN: 23AI 建议部署在 OL8/OL9 上"
local mem_mb; mem_mb=(awk '/MemTotal/{printf "%d", 2/1024}' /proc/meminfo)

local need=$MIN_MEM_SINGLE

\[ $HA == rac ] && need=$MIN_MEM_RAC

(( mem_mb >= need )) || die "内存不足: 需要 {need}MB,当前 {mem_mb}MB"
if id oracle >/dev/null 2>&1; then die "oracle 用户已存在,疑似已安装"; fi

\[ -d $ORA_BASE ] && die "ORA_BASE 已存在,疑似已安装" local tz; tz=(timedatectl 2>/dev/null | awk -F': ' '/Time zone/{print 2}' \| awk '{print 1}')

\[ -n $tz \&\& $tz != Asia/Shanghai ] && die "时区为 $tz,请先设置为 Asia/Shanghai"
mountpoint -q /mnt 2>/dev/null && umount /mnt >/dev/null 2>&1 || true

eval "YUM_CMD" \>/dev/null 2\>\&1 \|\| die "无法挂载 yum 源: YUM_CMD"

umount /mnt >/dev/null 2>&1 || true
local f

for f in $DB_ZIP; do

\[ -f ${SOFT_DIR}/$f ] || die "缺少数据库介质: {SOFT_DIR}/f"

done

if \[ $HA != single ]; then

for f in $GRID_ZIP; do

\[ -f ${SOFT_DIR}/$f ] || die "缺少 Grid 介质: {SOFT_DIR}/f"

done

fi

log "预检查通过"

}

-----------------------------------------------------------------------------

OS 初始化脚本(生成一次,单机/RAC 共用,幂等)

-----------------------------------------------------------------------------

gen_setos(){

cat > "${SOFT_DIR}/setos.sh" <<'EOS'

!/bin/bash

generated by oracle_deploy.sh -- 幂等 OS 初始化

set -u

say(){ echo "setos $*"; }

: "${ROLE:=primary}"

: "${NODE_SUFFIX:=1}"

1. hosts

if \[ "${HA}" == "rac" ]; then

sed -i '/^# >>> oradb hosts/,/^# <<< oradb hosts/d' /etc/hosts

cat >> /etc/hosts <<EOF

>>> oradb hosts

{PUB1} {NODE_NAME}db1

{PUB2} {NODE_NAME}db2

{VIP1} {NODE_NAME}db1-vip

{VIP2} {NODE_NAME}db2-vip

{PRIV1} {NODE_NAME}db1-priv

{PRIV2} {NODE_NAME}db2-priv

{SCAN_IP} {NODE_NAME}db-scan

<<< oradb hosts

EOF

else

grep -qE "^{PUBLIC_IP}\[\[:space:\]\]+{NODE_NAME}db(\[:space:]|$)" /etc/hosts

|| echo -e "{PUBLIC_IP}\\t{NODE_NAME}db" >> /etc/hosts

fi

if \[ "${HA}" == "rac" ]; then

hostnamectl set-hostname "{NODE_NAME}db{NODE_SUFFIX}"

else

hostnamectl set-hostname "${NODE_NAME}db"

fi

2. yum

mountpoint -q /mnt 2>/dev/null && umount /mnt >/dev/null 2>&1 || true

eval "{YUM_CMD}" \>/dev/null 2\>\&1 \|\| { echo "ERROR: 挂载 yum 源失败: {YUM_CMD}"; exit 1; }

mkdir -p /etc/yum.repos.d/bak

for r in /etc/yum.repos.d/*.repo; do \[ -e "${r}" ] && mv -f "${r}" /etc/yum.repos.d/bak/ 2>/dev/null; done

cat > /etc/yum.repos.d/oradb.repo <<EOF

oradb

name=oradb local

baseurl=file:///mnt

enabled=1

gpgcheck=0

EOF

yum clean all >/dev/null 2>&1

yum makecache >/dev/null 2>&1 ||
OS_MAJOR=$(grep -oE '0-9+' /etc/redhat-release 2>/dev/null | head -1)

if \[ ${OS_MAJOR:-7} -ge 8 ]; then

PKGS="gcc gcc-c++ make binutils elfutils-libelf elfutils-libelf-devel glibc-devel

libaio libaio-devel libstdc++ libstdc++-devel ksh sysstat unixODBC unixODBC-devel libnsl

libXext libX11 libXau libXi libXtst libXrender xorg-x11-utils device-mapper-multipath

unzip zip net-tools lrzsz vim dstat bc tree nfs-utils expect psmisc

policycoreutils-python-utils smartmontools"

else

PKGS="gcc gcc-c++ make compat-gcc-34 compat-libstdc++-33 elfutils-libelf

elfutils-libelf-devel glibc-headers libaio libaio-devel libgcc libstdc++ libstdc++-devel

ksh sysstat unixODBC unixODBC-devel compat-libcap1 libXp libXi libXtst xorg-x11-utils

device-mapper-multipath unzip zip smartmontools net-tools lrzsz vim dstat libnsl

policycoreutils-python bc tree nfs-utils expect psmisc"

fi

for p in ${PKGS}; do

rpm -q "{p}" \>/dev/null 2\>\&1 \|\| yum install -y "{p}" >/dev/null 2>&1

|| say "WARN: 软件包未安装: ${p}"

done

umount /mnt >/dev/null 2>&1 || true

3. 关闭无关服务 / SELinux

systemctl stop firewalld >/dev/null 2>&1 || true

systemctl disable firewalld >/dev/null 2>&1 || true

sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

setenforce 0 >/dev/null 2>&1 || true

for s in tuned ktune postfix avahi-daemon avahi-dnsconfd atd bluetooth wpa_supplicant

accounts-daemon ModemManager rtkit-daemon rpcbind rngd upower rhsmcertd mcelog colord

gdm libstoragemgmt ksmtuned brltty cups irqbalance; do

systemctl stop "${s}" >/dev/null 2>&1 || true

systemctl disable "${s}" >/dev/null 2>&1 || true

done

4. sysctl

sed -i '/^# >>> oradb oracle sysctl/,/^# <<< oradb oracle sysctl/d' /etc/sysctl.conf

mem_kb=(awk '/MemTotal/{print 2}' /proc/meminfo)

huge_pages=(awk -v m="{mem_kb}" 'BEGIN{printf "%d", (m*0.75)/2048}')

(( huge_pages < 256 )) && huge_pages=256

cat >> /etc/sysctl.conf <<EOF

>>> oradb oracle sysctl

kernel.shmall = ${mem_kb}

kernel.shmmax = $(( mem_kb * 1024 ))

kernel.shmmni = 4096

kernel.sem = 250 32000 100 128

fs.file-max = 6815744

fs.aio-max-nr = 1048576

net.ipv4.ip_local_port_range = 9000 65500

net.core.rmem_default = 262144

net.core.rmem_max = 4194304

net.core.wmem_default = 262144

net.core.wmem_max = 1048576

net.ipv4.ipfrag_high_thresh = 4194304

net.ipv4.ipfrag_low_thresh = 3145728

vm.min_free_kbytes = 512000

vm.vfs_cache_pressure = 200

vm.swappiness = 20

vm.nr_hugepages = ${huge_pages}

<<< oradb oracle sysctl

EOF

sysctl -p >/dev/null 2>&1 || sysctl --system >/dev/null 2>&1 || true

5. limits

sed -i '/^# >>> oradb limits/,/^# <<< oradb limits/d' /etc/security/limits.conf

{

echo "# >>> oradb limits"

for u in oracle grid; do

\[ ${u} == grid \&\& ${HA} == single ] && continue

cat <<EOF

${u} soft nproc 16384

${u} hard nproc 16384

${u} soft nofile 10240

${u} hard nofile 65536

${u} soft stack 10240

${u} hard stack 32768

${u} soft memlock unlimited

${u} hard memlock unlimited

${u} soft core unlimited

${u} hard core unlimited

EOF

done

echo "# <<< oradb limits"

} >> /etc/security/limits.conf

grep -q 'pam_limits.so' /etc/pam.d/login || echo 'session required pam_limits.so' >> /etc/pam.d/login

6. 用户与组

chattr -i /etc/passwd /etc/group /etc/gshadow >/dev/null 2>&1 || true

add_group(){

local g=1 gid=2

getent group "$g" >/dev/null && return 0

if getent group "gid" \>/dev/null; then groupadd "g"; else groupadd -g "gid" "g"; fi

}

add_user(){

local u=1 uid=2 grps=$3

id "$u" >/dev/null 2>&1 && return 0

if getent passwd "$uid" >/dev/null; then

useradd -g oinstall -G "grps" -m "u"

else

useradd -u "uid" -g oinstall -G "grps" -m "$u"

fi

}

add_group oinstall 54321

add_group dba 54322

if \[ "${HA}" != "single" ]; then

add_group oper 54323

add_group asmadmin 54324

add_group asmoper 54325

add_group asmdba 54326

add_group backupdba 54327

add_group dgdba 54328

add_group kmdba 54329

add_group racdba 54330

add_user oracle 54321 "dba,oper,asmdba,backupdba,dgdba,kmdba,racdba"

add_user grid 54322 "dba,asmadmin,asmdba,asmoper"

else

add_user oracle 54321 "dba"

fi

echo "${DB_PWD}" | passwd --stdin oracle >/dev/null 2>&1

\[ "${HA}" != "single" ] && echo "${DB_PWD}" | passwd --stdin grid >/dev/null 2>&1

7. 关闭透明大页

chmod +x /etc/rc.d/rc.local >/dev/null 2>&1 || true

for f in /sys/kernel/mm/transparent_hugepage/enabled /sys/kernel/mm/redhat_transparent_hugepage/enabled; do

\[ -f "${f}" ] && echo never > "${f}" || true

done

grep -q 'transparent_hugepage' /etc/rc.d/rc.local 2>/dev/null || cat >> /etc/rc.d/rc.local <<'EOF'

if test -f /sys/kernel/mm/transparent_hugepage/enabled; then

echo never > /sys/kernel/mm/transparent_hugepage/enabled

fi

EOF

8. 目录

mkdir -p /u01/app /soft

if \[ "${HA}" == "single" ]; then

mkdir -p "${ORA_BASE}" /oradata

chown -R oracle:oinstall /u01 /oradata "${SOFT_DIR}"

else

mkdir -p "{GRID_BASE}" "{GRID_HOME}" "${ORA_BASE}"

chown -R grid:oinstall /u01

chown -R oracle:oinstall "{ORA_BASE}" "{SOFT_DIR}"

fi

chmod -R 775 /u01 "${SOFT_DIR}" 2>/dev/null || true

9. 解压安装介质(仅主节点)

if \[ "${ROLE}" == "primary" ]; then

if \[ "${DB_MEDIA_MODE}" == "image" ]; then

mkdir -p "${ORACLE_HOME}"

chown -R oracle:oinstall "${ORACLE_HOME}"

for z in ${DB_ZIP}; do

su - oracle -c "unzip -oq {SOFT_DIR}/{z} -d ${ORACLE_HOME}"

|| { echo "ERROR: 解压 ${z} 失败"; exit 1; }

done

else

for z in ${DB_ZIP}; do

unzip -oq "{SOFT_DIR}/{z}" -d "${SOFT_DIR}"

|| { echo "ERROR: 解压 ${z} 失败"; exit 1; }

done

chown -R oracle:oinstall "${SOFT_DIR}/database"

fi

if \[ "${HA}" != "single" ]; then

if \[ "${GRID_MEDIA_MODE}" == "image" ]; then

mkdir -p "${GRID_HOME}"

chown -R grid:oinstall "${GRID_HOME}"

for z in ${GRID_ZIP}; do

su - grid -c "unzip -oq {SOFT_DIR}/{z} -d ${GRID_HOME}"

|| { echo "ERROR: 解压 ${z} 失败"; exit 1; }

done

else

for z in ${GRID_ZIP}; do

unzip -oq "{SOFT_DIR}/{z}" -d "${SOFT_DIR}"

|| { echo "ERROR: 解压 ${z} 失败"; exit 1; }

done

chown -R grid:oinstall "${SOFT_DIR}/grid"

fi

fi

fi

10. 环境变量

if \[ "${HA}" == "rac" ]; then

ORA_SID="{DB_SID}{NODE_SUFFIX}"

ASM_SID="+ASM${NODE_SUFFIX}"

else

ORA_SID="${DB_SID}"

ASM_SID="+ASM"

fi
sed -i '/^# >>> oradb oracle profile/,/^# <<< oradb oracle profile/d' /home/oracle/.bash_profile 2>/dev/null

cat >> /home/oracle/.bash_profile <<EOF

>>> oradb oracle profile

export TMP=/tmp

export TMPDIR=$TMP

export ORACLE_SID=${ORA_SID}

export ORACLE_BASE=${ORA_BASE}

export ORACLE_HOME=${ORACLE_HOME}

export ORACLE_TERM=xterm

export PATH=/usr/sbin:$PATH

export PATH=ORACLE_HOME/bin:PATH

export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib

export CLASSPATH=ORACLE_HOME/JRE:ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib

umask 022

<<< oradb oracle profile

EOF

chown oracle:oinstall /home/oracle/.bash_profile
if \[ "${HA}" != "single" ]; then

sed -i '/^# >>> oradb grid profile/,/^# <<< oradb grid profile/d' /home/grid/.bash_profile 2>/dev/null

cat >> /home/grid/.bash_profile <<EOF

>>> oradb grid profile

export ORACLE_BASE=${GRID_BASE}

export ORACLE_HOME=${GRID_HOME}

export ORACLE_SID=${ASM_SID}

export PATH=ORACLE_HOME/OPatch:ORACLE_HOME/bin:$PATH

umask 022

<<< oradb grid profile

EOF

chown grid:oinstall /home/grid/.bash_profile

fi
say "OS 初始化完成 (ROLE={ROLE}, NODE_SUFFIX={NODE_SUFFIX})"

EOS

chmod +x "${SOFT_DIR}/setos.sh"

}
gen_setos_env(){

cat > "${SOFT_DIR}/setos.env" <<EOF

export SOFT_DIR='${SOFT_DIR}'

export HA='${HA}'

export VER='${VER}'

export ORA_NUMBER='${ORA_NUMBER}'

export ORA_NUMBER_S='${ORA_NUMBER_S}'

export NODE_NAME='${NODE_NAME}'

export PUBLIC_IP='${PUBLIC_IP}'

export PUB1='${PUB1}'

export PUB2='${PUB2}'

export VIP1='${VIP1}'

export VIP2='${VIP2}'

export PRIV1='${PRIV1}'

export PRIV2='${PRIV2}'

export SCAN_IP='${SCAN_IP}'

export DB_PWD='${DB_PWD}'

export DB_SID='${DB_SID}'

export YUM_CMD='${YUM_CMD}'

export DB_ZIP='${DB_ZIP}'

export GRID_ZIP='${GRID_ZIP}'

export DB_MEDIA_MODE='${DB_MEDIA_MODE}'

export GRID_MEDIA_MODE='${GRID_MEDIA_MODE}'

export ORACLE_HOME='${ORACLE_HOME}'

export GRID_HOME='${GRID_HOME}'

export ORA_BASE='${ORA_BASE}'

export GRID_BASE='${GRID_BASE}'

EOF

chmod 600 "${SOFT_DIR}/setos.env"

}
run_setos_local(){

gen_setos; gen_setos_env

( source "{SOFT_DIR}/setos.env"; export ROLE=primary NODE_SUFFIX=1; bash "{SOFT_DIR}/setos.sh" )

|| die "本机 OS 初始化失败"

}
run_setos_remote(){

ssh "{NODE_NAME}db2" "mkdir -p {SOFT_DIR}" || die "无法 ssh 到 ${NODE_NAME}db2,请检查 root 互信"

local yum_cmd=$YUM_CMD

if \[ $YUM_SRC == \*.iso ]; then

scp "YUM_SRC" "{NODE_NAME}db2:${SOFT_DIR}/" || die "复制 yum 镜像失败"

yum_cmd="mount -o loop {SOFT_DIR}/(basename "$YUM_SRC") /mnt"

fi

scp "{SOFT_DIR}/setos.env" "{SOFT_DIR}/setos.sh" "{NODE_NAME}db2:{SOFT_DIR}/"

|| die "复制 setos 脚本失败"

ssh "{NODE_NAME}db2" "source {SOFT_DIR}/setos.env; export ROLE=secondary NODE_SUFFIX=2 YUM_CMD='{yum_cmd}'; bash {SOFT_DIR}/setos.sh"

|| die "node2 OS 初始化失败"

}

-----------------------------------------------------------------------------

RAC 互信 / ASM 存储

-----------------------------------------------------------------------------

find_ssh_setup_script(){

local p

for p in "${GRID_HOME}/oui/prov/resources/scripts/sshUserSetup.sh"

"${SOFT_DIR}/grid/oui/prov/resources/scripts/sshUserSetup.sh"

"${SOFT_DIR}/grid/sshsetup/sshUserSetup.sh"; do

\[ -f $p ] && { echo "$p"; return 0; }

done

return 1

}
config_ssh_trust(){

local user=$1 pwd script expfile

script=$(find_ssh_setup_script) || die "未找到 sshUserSetup.sh,请确认 Grid 介质已解压"

case user in root) pwd=ROOT_PWD ;; *) pwd=$DB_PWD ;; esac

expfile="{SOFT_DIR}/sshsetup_{user}.exp"

cat > "$expfile" <<EOF

set timeout 180

set pwd "${pwd}"

spawn {script} -hosts "{NODE_NAME}db1 {NODE_NAME}db2" -user {user} -advanced

expect {

-re "(?i)(yes/no)" { send "yes\r"; exp_continue }

-re "(?i)password" { send "$pwd\r"; exp_continue }

eof

}

EOF

chmod 600 "$expfile"

if \[ $user == root ]; then

expect "$expfile" || die "root 互信配置失败"

else

chown "{user}:oinstall" "expfile"

run_as "user" "expect expfile" || die "${user} 互信配置失败"

fi

log "${user} 互信配置完成"

}
setup_multipath(){

local disk wwid i

{

echo 'defaults {'

echo ' user_friendly_names yes'

echo ' find_multipaths yes'

echo '}'

echo 'blacklist {'

echo ' devnode "^sda"'

echo '}'

echo 'multipaths {'

i=0

for disk in ${OCR_DISKS//,/ }; do

i=$((i+1))

wwid=(/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device="disk" 2>/dev/null)

|| die "无法获取 $disk 的 wwid"

cat <<EOF

multipath {

wwid ${wwid}

alias ocr${i}

path_grouping_policy failover

}

EOF

done

i=0

for disk in ${DATA_DISKS//,/ }; do

i=$((i+1))

wwid=(/usr/lib/udev/scsi_id --whitelisted --replace-whitespace --device="disk" 2>/dev/null)

|| die "无法获取 $disk 的 wwid"

cat <<EOF

multipath {

wwid ${wwid}

alias data${i}

path_grouping_policy failover

}

EOF

done

echo '}'

} > /etc/multipath.conf
systemctl restart multipathd >/dev/null 2>&1 || true

systemctl enable multipathd >/dev/null 2>&1 || true

multipath -ll

}
setup_udev(){

local d uuid

: > /etc/udev/rules.d/99-oracle-asmdevices.rules

for d in $(ls /dev/mapper/ 2>/dev/null | grep -E '^(ocr|data)'); do

uuid=(udevadm info --query=property --name="/dev/mapper/d" 2>/dev/null

| awk -F= '/^DM_UUID=/{print $2}')

\[ -n $uuid ] || { log "WARN: 无法获取 $d 的 DM_UUID,跳过"; continue; }

echo "KERNEL"dm-*",ENV{DM_UUID}"{uuid}",SYMLINK+="oracleasm/disks/{d}",OWNER="grid",GROUP="asmadmin",MODE="0660""

>> /etc/udev/rules.d/99-oracle-asmdevices.rules

done

udevadm control --reload-rules

udevadm trigger

sleep 5

ls -ltr "${ASM_DISK_DIR}/"

}
push_asm_config_remote(){

scp /etc/multipath.conf "${NODE_NAME}db2:/etc/" || die "复制 multipath.conf 失败"

scp /etc/udev/rules.d/99-oracle-asmdevices.rules "${NODE_NAME}db2:/etc/udev/rules.d/"

|| die "复制 udev 规则失败"

ssh "{NODE_NAME}db2" "systemctl restart multipathd; systemctl enable multipathd; udevadm control --reload-rules; udevadm trigger; sleep 5; ls -ltr {ASM_DISK_DIR}/"

}
install_cvuqdisk(){

local rpm_path

rpm_path=(ls "{GRID_HOME}"/cv/rpm/cvuqdisk-.rpm "${SOFT_DIR}"/grid/rpm/cvuqdisk- .rpm 2>/dev/null | head -1)

\[ -n $rpm_path ] || { log "WARN: 未找到 cvuqdisk rpm,跳过"; return 0; }

rpm -q cvuqdisk >/dev/null 2>&1 || rpm -ivh "$rpm_path" || log "WARN: 本机 cvuqdisk 安装失败"

scp "rpm_path" "{NODE_NAME}db2:${SOFT_DIR}/" >/dev/null 2>&1 || true

ssh "{NODE_NAME}db2" "rpm -q cvuqdisk \>/dev/null 2\>\&1 \|\| rpm -ivh {SOFT_DIR}/(basename "rpm_path")"

|| log "WARN: node2 cvuqdisk 安装失败"

}
init_asm_disks(){

local d

for d in (ls "{ASM_DISK_DIR}/" 2>/dev/null | grep -E '^(ocr|data|redo|arch)'); do

dd if=/dev/zero of="{ASM_DISK_DIR}/{d}" bs=1M count=10 status=none ||

log "WARN: 擦除 ${d} 失败"

done

}

-----------------------------------------------------------------------------

响应文件

-----------------------------------------------------------------------------

write_netca_rsp(){

local ver

\[ $ORA_NUMBER == 11.2.0 ] && ver="11.2" || ver=$ORA_NUMBER

rm -f "${SOFT_DIR}/netca.rsp"

cat > "${SOFT_DIR}/netca.rsp" <<EOF

GENERAL

RESPONSEFILE_VERSION="${ver}"

CREATE_TYPE="CUSTOM"

oracle.net.ca

INSTALLED_COMPONENTS={"server","net8","javavm"}

INSTALL_TYPE="typical"

LISTENER_NUMBER=1

LISTENER_NAMES={"LISTENER"}

LISTENER_PROTOCOLS={"TCP;1521"}

LISTENER_START="LISTENER"

NAMING_METHODS={"TNSNAMES","ONAMES","HOSTNAME"}

NSN_NUMBER=1

NSN_NAMES={"EXTPROC_CONNECTION_DATA"}

NSN_SERVICE={"PLSExtProc"}

NSN_PROTOCOLS={"TCP;HOSTNAME;1521"}

EOF

}
write_db_rsp(){

local cluster_nodes="" host_name

\[ $HA == rac ] && cluster_nodes="{NODE_NAME}db1,{NODE_NAME}db2"

if \[ $HA == rac ]; then host_name="{NODE_NAME}db1"; else host_name=(hostname -s); fi

rm -f "${SOFT_DIR}/db_install.rsp"

if \[ $ORA_NUMBER == 11.2.0 ]; then

cat > "{SOFT_DIR}/db_install.rsp" \< "{SOFT_DIR}/db_install.rsp" <<EOF
oracle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_{RSP_DB_SCHEMA} oracle.install.option=INSTALL_DB_SWONLY UNIX_GROUP_NAME=oinstall INVENTORY_LOCATION={INVENTORY}
ORACLE_BASE={ORA_BASE} oracle.install.db.InstallEdition=EE oracle.install.db.OSDBA_GROUP=dba oracle.install.db.OSOPER_GROUP=oper oracle.install.db.OSBACKUPDBA_GROUP=backupdba oracle.install.db.OSDGDBA_GROUP=dgdba oracle.install.db.OSKMDBA_GROUP=kmdba oracle.install.db.OSRACDBA_GROUP=racdba oracle.install.db.rootconfig.executeRootScript=false oracle.install.db.rootconfig.configMethod= oracle.install.db.rootconfig.sudoPath= oracle.install.db.rootconfig.sudoUserName= oracle.install.db.CLUSTER_NODES={cluster_nodes}
EOF
fi
chown oracle:oinstall "{SOFT_DIR}/db_install.rsp" chmod 660 "{SOFT_DIR}/db_install.rsp"
}
write_grid_rsp(){

rm -f "${SOFT_DIR}/grid.rsp"

if \[ $HA == rac ]; then write_grid_rsp_rac; else write_grid_rsp_ha; fi

chown grid:oinstall "${SOFT_DIR}/grid.rsp"

chmod 660 "${SOFT_DIR}/grid.rsp"

}
write_grid_rsp_rac(){

local ocr_list

ocr_list=(ls "{ASM_DISK_DIR}"/ocr* 2>/dev/null | xargs | sed 's/ /,/g')

if \[ $ORA_NUMBER == 11.2.0 ]; then

cat > "${SOFT_DIR}/grid.rsp" <<EOF

oracle.install.responseFileVersion=/oracle/install/rspfmt_crsinstall_response_schema_${RSP_GRID_SCHEMA}

ORACLE_HOSTNAME=${NODE_NAME}db1

INVENTORY_LOCATION=${INVENTORY}

SELECTED_LANGUAGES=en,zh_CN

oracle.install.option=CRS_CONFIG

ORACLE_BASE=${GRID_BASE}

ORACLE_HOME=${GRID_HOME}

oracle.install.asm.OSDBA=asmdba

oracle.install.asm.OSOPER=asmoper

oracle.install.asm.OSASM=asmadmin

oracle.install.crs.config.gpnp.scanName=${NODE_NAME}db-scan

oracle.install.crs.config.gpnp.scanPort=1521

oracle.install.crs.config.clusterName=${NODE_NAME}db-cluster

oracle.install.crs.config.gpnp.configureGNS=false

oracle.install.crs.config.gpnp.gnsSubDomain=

oracle.install.crs.config.gpnp.gnsVIPAddress=

oracle.install.crs.config.autoConfigureClusterNodeVIP=false

oracle.install.crs.config.clusterNodes={NODE_NAME}db1:{NODE_NAME}db1-vip,{NODE_NAME}db2:{NODE_NAME}db2-vip

oracle.install.crs.config.networkInterfaceList={PUB_IF}😒(cidr24 "PUB1"):1,{PRIV_IF}😒(cidr24 "PRIV1"):2

oracle.install.crs.config.storageOption=ASM_STORAGE

oracle.install.crs.config.sharedFileSystemStorage.diskDriveMapping=

oracle.install.crs.config.sharedFileSystemStorage.votingDiskLocations=

oracle.install.crs.config.sharedFileSystemStorage.votingDiskRedundancy=${OCR_REDU}

oracle.install.crs.config.sharedFileSystemStorage.ocrLocations=

oracle.install.crs.config.sharedFileSystemStorage.ocrRedundancy=${OCR_REDU}

oracle.install.crs.config.useIPMI=false

oracle.install.crs.config.ipmi.bmcUsername=

oracle.install.crs.config.ipmi.bmcPassword=

oracle.install.asm.SYSASMPassword=${DB_PWD}

oracle.install.asm.diskGroup.name=OCR_VOT

oracle.install.asm.diskGroup.redundancy=${OCR_REDU}

oracle.install.asm.diskGroup.AUSize=${AU_SIZE}

oracle.install.asm.diskGroup.disks=${ocr_list}

oracle.install.asm.diskGroup.diskDiscoveryString=${ASM_DISK_DIR}/*

oracle.install.asm.monitorPassword=${DB_PWD}

oracle.install.crs.upgrade.clusterNodes=

oracle.install.asm.upgradeASM=false

oracle.installer.autoupdates.option=SKIP_UPDATES

oracle.installer.autoupdates.downloadUpdatesLoc=

AUTOUPDATES_MYORACLESUPPORT_USERNAME=

AUTOUPDATES_MYORACLESUPPORT_PASSWORD=

PROXY_HOST=

PROXY_PORT=0

PROXY_USER=

PROXY_PWD=

PROXY_REALM=

EOF

else

cat > "${SOFT_DIR}/grid.rsp" <<EOF

oracle.install.responseFileVersion=/oracle/install/rspfmt_crsinstall_response_schema_${RSP_GRID_SCHEMA}

INVENTORY_LOCATION=${INVENTORY}

oracle.install.option=CRS_CONFIG

ORACLE_BASE=${GRID_BASE}

oracle.install.asm.OSDBA=asmdba

oracle.install.asm.OSOPER=asmoper

oracle.install.asm.OSASM=asmadmin

oracle.install.crs.config.scanType=LOCAL_SCAN

oracle.install.crs.config.SCANClientDataFile=

oracle.install.crs.config.gpnp.scanName=${NODE_NAME}db-scan

oracle.install.crs.config.gpnp.scanPort=1521

oracle.install.crs.config.ClusterConfiguration=STANDALONE

oracle.install.crs.config.configureAsExtendedCluster=false

oracle.install.crs.config.memberClusterManifestFile=

oracle.install.crs.config.clusterName=${NODE_NAME}db-cluster

oracle.install.crs.config.gpnp.configureGNS=false

oracle.install.crs.config.autoConfigureClusterNodeVIP=false

oracle.install.crs.config.gpnp.gnsOption=

oracle.install.crs.config.gpnp.gnsClientDataFile=

oracle.install.crs.config.gpnp.gnsSubDomain=

oracle.install.crs.config.gpnp.gnsVIPAddress=

oracle.install.crs.config.sites=

oracle.install.crs.config.clusterNodes={NODE_NAME}db1:{NODE_NAME}db1-vip,{NODE_NAME}db2:{NODE_NAME}db2-vip

oracle.install.crs.config.networkInterfaceList={PUB_IF}😒(cidr24 "PUB1"):1,{PRIV_IF}😒(cidr24 "PRIV1"):5

oracle.install.crs.configureGIMR=false

oracle.install.asm.configureGIMRDataDG=false

oracle.install.crs.config.storageOption=FLEX_ASM_STORAGE

oracle.install.crs.config.sharedFileSystemStorage.votingDiskLocations=

oracle.install.crs.config.sharedFileSystemStorage.ocrLocations=

oracle.install.crs.config.useIPMI=false

oracle.install.crs.config.ipmi.bmcUsername=

oracle.install.crs.config.ipmi.bmcPassword=

oracle.install.asm.SYSASMPassword=${DB_PWD}

oracle.install.asm.diskGroup.name=OCR_VOT

oracle.install.asm.diskGroup.redundancy=${OCR_REDU}

oracle.install.asm.diskGroup.AUSize=${AU_SIZE}

oracle.install.asm.diskGroup.FailureGroups=

oracle.install.asm.diskGroup.disksWithFailureGroupNames=

oracle.install.asm.diskGroup.disks=${ocr_list}

oracle.install.asm.diskGroup.quorumFailureGroupNames=

oracle.install.asm.diskGroup.diskDiscoveryString=${ASM_DISK_DIR}/

oracle.install.asm.monitorPassword=${DB_PWD}

oracle.install.asm.gimrDG.name=

oracle.install.asm.gimrDG.redundancy=

oracle.install.asm.gimrDG.AUSize=1

oracle.install.asm.gimrDG.FailureGroups=

oracle.install.asm.gimrDG.disksWithFailureGroupNames=

oracle.install.asm.gimrDG.disks=

oracle.install.asm.gimrDG.quorumFailureGroupNames=

oracle.install.asm.configureAFD=false

oracle.install.crs.configureRHPS=false

EOF

fi

}

standalone(Oracle Restart)的 GI 响应文件

write_grid_rsp_ha(){

local ocr_list host="${NODE_NAME}db"

ocr_list=(ls "{ASM_DISK_DIR}"/ocr* 2>/dev/null | xargs | sed 's/ /,/g')

if \[ $ORA_NUMBER == 11.2.0 ]; then

cat > "${SOFT_DIR}/grid.rsp" <<EOF

oracle.install.responseFileVersion=/oracle/install/rspfmt_crsinstall_response_schema_${RSP_GRID_SCHEMA}

ORACLE_HOSTNAME=${host}

INVENTORY_LOCATION=${INVENTORY}

SELECTED_LANGUAGES=en,zh_CN

oracle.install.option=CRS_CONFIG

ORACLE_BASE=${GRID_BASE}

ORACLE_HOME=${GRID_HOME}

oracle.install.asm.OSDBA=asmdba

oracle.install.asm.OSOPER=asmoper

oracle.install.asm.OSASM=asmadmin

oracle.install.crs.config.gpnp.scanName=${host}

oracle.install.crs.config.gpnp.scanPort=1521

oracle.install.crs.config.clusterName=${host}-cluster

oracle.install.crs.config.gpnp.configureGNS=false

oracle.install.crs.config.gpnp.gnsSubDomain=

oracle.install.crs.config.gpnp.gnsVIPAddress=

oracle.install.crs.config.autoConfigureClusterNodeVIP=false

oracle.install.crs.config.clusterNodes=${host}

oracle.install.crs.config.networkInterfaceList={PUB_IF}😒(cidr24 "PUBLIC_IP"):1

oracle.install.crs.config.storageOption=ASM_STORAGE

oracle.install.crs.config.sharedFileSystemStorage.diskDriveMapping=

oracle.install.crs.config.sharedFileSystemStorage.votingDiskLocations=

oracle.install.crs.config.sharedFileSystemStorage.votingDiskRedundancy=${OCR_REDU}

oracle.install.crs.config.sharedFileSystemStorage.ocrLocations=

oracle.install.crs.config.sharedFileSystemStorage.ocrRedundancy=${OCR_REDU}

oracle.install.crs.config.useIPMI=false

oracle.install.crs.config.ipmi.bmcUsername=

oracle.install.crs.config.ipmi.bmcPassword=

oracle.install.asm.SYSASMPassword=${DB_PWD}

oracle.install.asm.diskGroup.name=OCR_VOT

oracle.install.asm.diskGroup.redundancy=${OCR_REDU}

oracle.install.asm.diskGroup.AUSize=${AU_SIZE}

oracle.install.asm.diskGroup.disks=${ocr_list}

oracle.install.asm.diskGroup.diskDiscoveryString=${ASM_DISK_DIR}/*

oracle.install.asm.monitorPassword=${DB_PWD}

oracle.installer.autoupdates.option=SKIP_UPDATES

oracle.installer.autoupdates.downloadUpdatesLoc=

AUTOUPDATES_MYORACLESUPPORT_USERNAME=

AUTOUPDATES_MYORACLESUPPORT_PASSWORD=

PROXY_HOST=

PROXY_PORT=0

PROXY_USER=

PROXY_PWD=

PROXY_REALM=

EOF

else

cat > "${SOFT_DIR}/grid.rsp" <<EOF

oracle.install.responseFileVersion=/oracle/install/rspfmt_crsinstall_response_schema_${RSP_GRID_SCHEMA}

INVENTORY_LOCATION=${INVENTORY}

oracle.install.option=CRS_CONFIG

ORACLE_BASE=${GRID_BASE}

oracle.install.asm.OSDBA=asmdba

oracle.install.asm.OSOPER=asmoper

oracle.install.asm.OSASM=asmadmin

oracle.install.crs.config.scanType=LOCAL_SCAN

oracle.install.crs.config.SCANClientDataFile=

oracle.install.crs.config.gpnp.scanName=${host}

oracle.install.crs.config.gpnp.scanPort=1521

oracle.install.crs.config.ClusterConfiguration=STANDALONE

oracle.install.crs.config.configureAsExtendedCluster=false

oracle.install.crs.config.memberClusterManifestFile=

oracle.install.crs.config.clusterName=${host}-cluster

oracle.install.crs.config.gpnp.configureGNS=false

oracle.install.crs.config.autoConfigureClusterNodeVIP=false

oracle.install.crs.config.gpnp.gnsOption=

oracle.install.crs.config.gpnp.gnsClientDataFile=

oracle.install.crs.config.gpnp.gnsSubDomain=

oracle.install.crs.config.gpnp.gnsVIPAddress=

oracle.install.crs.config.sites=

oracle.install.crs.config.clusterNodes=${host}

oracle.install.crs.config.networkInterfaceList={PUB_IF}😒(cidr24 "PUBLIC_IP"):1

oracle.install.crs.configureGIMR=false

oracle.install.asm.configureGIMRDataDG=false

oracle.install.crs.config.storageOption=FLEX_ASM_STORAGE

oracle.install.crs.config.sharedFileSystemStorage.votingDiskLocations=

oracle.install.crs.config.sharedFileSystemStorage.ocrLocations=

oracle.install.crs.config.useIPMI=false

oracle.install.crs.config.ipmi.bmcUsername=

oracle.install.crs.config.ipmi.bmcPassword=

oracle.install.asm.SYSASMPassword=${DB_PWD}

oracle.install.asm.diskGroup.name=OCR_VOT

oracle.install.asm.diskGroup.redundancy=${OCR_REDU}

oracle.install.asm.diskGroup.AUSize=${AU_SIZE}

oracle.install.asm.diskGroup.FailureGroups=

oracle.install.asm.diskGroup.disksWithFailureGroupNames=

oracle.install.asm.diskGroup.disks=${ocr_list}

oracle.install.asm.diskGroup.quorumFailureGroupNames=

oracle.install.asm.diskGroup.diskDiscoveryString=${ASM_DISK_DIR}/

oracle.install.asm.monitorPassword=${DB_PWD}

oracle.install.asm.gimrDG.name=

oracle.install.asm.gimrDG.redundancy=

oracle.install.asm.gimrDG.AUSize=1

oracle.install.asm.gimrDG.FailureGroups=

oracle.install.asm.gimrDG.disksWithFailureGroupNames=

oracle.install.asm.gimrDG.disks=

oracle.install.asm.gimrDG.quorumFailureGroupNames=

oracle.install.asm.configureAFD=false

oracle.install.crs.configureRHPS=false

EOF

fi

}

-----------------------------------------------------------------------------

安装执行

-----------------------------------------------------------------------------

install_grid(){

local runInstaller

if \[ $GRID_MEDIA_MODE == image ]; then

runInstaller=${GRID_HOME}/runInstaller

else

runInstaller=${SOFT_DIR}/grid/runInstaller

fi

\[ -x $runInstaller ] || die "未找到 Grid runInstaller: $runInstaller"

log "开始安装 Grid Infrastructure($HA)..."

run_as grid "cd {GRID_HOME} \&\& {runInstaller} -silent -waitforcompletion -responseFile {SOFT_DIR}/grid.rsp {IGNORE_FLAG}"

|| die "Grid Infrastructure 安装失败"

log "Grid Infrastructure 安装完成"

}
run_root_scripts_grid(){

log "执行 Grid root 脚本 ..."

\[ -f ${INVENTORY}/orainstRoot.sh ] && bash "${INVENTORY}/orainstRoot.sh"

bash "{GRID_HOME}/root.sh" \|\| die "node1 {GRID_HOME}/root.sh 失败"

if \[ $HA == rac ]; then

scp "{GRID_HOME}/root.sh" "{NODE_NAME}db2:${GRID_HOME}/root.sh" >/dev/null 2>&1

|| die "复制 root.sh 到 node2 失败"

ssh "{NODE_NAME}db2" "bash {GRID_HOME}/root.sh" || die "node2 ${GRID_HOME}/root.sh 失败"

fi

log "Grid root 脚本执行完成"

}
create_data_dg(){

local data_list

data_list=(ls "{ASM_DISK_DIR}"/data* 2>/dev/null | xargs | sed 's/ /,/g')

\[ -n $data_list ] || { log "WARN: 未发现 data 盘,跳过 DATA 磁盘组创建"; return 0; }

log "创建 DATA 磁盘组 ..."

run_as grid "${GRID_HOME}/bin/asmca -silent -createDiskGroup

-diskGroupName DATA -diskList '{data_list}' -redundancy {DATA_REDU}

-au_size {AU_SIZE} -sysAsmPassword '{DB_PWD}'"

|| die "创建 DATA 磁盘组失败"

log "DATA 磁盘组创建完成"

}
install_db(){

local runInstaller

if \[ $DB_MEDIA_MODE == image ]; then

runInstaller=${ORACLE_HOME}/runInstaller

else

runInstaller=${SOFT_DIR}/database/runInstaller

fi

\[ -x $runInstaller ] || die "未找到 DB runInstaller: $runInstaller"

log "开始安装数据库软件 ..."

run_as oracle "cd {ORACLE_HOME} \&\& {runInstaller} -silent -waitforcompletion -responseFile {SOFT_DIR}/db_install.rsp {IGNORE_FLAG}"

|| die "数据库软件安装失败"

log "数据库软件安装完成"

}
run_root_scripts_db(){

log "执行 DB root.sh ..."

\[ -f ${INVENTORY}/orainstRoot.sh ] && bash "${INVENTORY}/orainstRoot.sh"

bash "{ORACLE_HOME}/root.sh" \|\| die "{ORACLE_HOME}/root.sh 失败"

log "DB root.sh 执行完成"

}
config_netca(){

case $HA in

single)

log "配置监听(oracle home)..."

run_as oracle "{ORACLE_HOME}/bin/netca -silent -responsefile {SOFT_DIR}/netca.rsp"

|| die "netca 配置失败" ;;

standalone)

log "配置监听(grid home)..."

run_as grid "{GRID_HOME}/bin/netca -silent -responsefile {SOFT_DIR}/netca.rsp"

|| die "netca 配置失败" ;;

rac)

log "RAC 监听由 Grid 管理,跳过 netca" ;;

esac

}
create_db(){

local dbca common cdb_opt storage_opt user run_home

if \[ $HA == single ]; then

user=oracle; run_home=$ORACLE_HOME

storage_opt="-datafileDestination /oradata -storageType FS"

else

user=oracle; run_home=$ORACLE_HOME

storage_opt="-storageType ASM -diskGroupName DATA -recoveryGroupName DATA"

fi

if (( SUPPORTS_CDB == 1 )); then

if \[ $USE_CDB == TRUE ]; then

cdb_opt="-createAsContainerDatabase true -numberOfPDBs 1 -pdbName {PDB_NAME} -pdbAdminPassword '{DB_PWD}'"

else

cdb_opt="-createAsContainerDatabase false"

fi

else

cdb_opt=""

fi

common="-silent -createDatabase -templateName General_Purpose.dbc

-gdbname {DB_SID} -sid {DB_SID}

-characterSet {DB_CHARSET} -nationalCharacterSet {DB_NCHARSET}

-sysPassword '{DB_PWD}' -systemPassword '{DB_PWD}'

-emConfiguration NONE -sampleSchema false {storage_opt} {cdb_opt}"

if \[ $HA == rac \&\& $ORA_NUMBER == 11.2.0 ]; then

common="{common} -nodeinfo {NODE_NAME}db1,${NODE_NAME}db2"

fi

log "开始创建数据库 ${DB_SID} ..."

run_as "user" "{run_home}/bin/dbca ${common}" || die "dbca 建库失败"

log "数据库 ${DB_SID} 创建完成"

}

-----------------------------------------------------------------------------

主流程

-----------------------------------------------------------------------------

main(){

parse_args "$@"

normalize_inputs

load_profile

validate_params

resolve_yum_cmd

precheck
log "===== 部署模式: HA \| 版本: VER | SID: $DB_SID ====="

run_setos_local
if \[ $HA != single ]; then

if \[ $HA == rac ]; then

run_setos_remote

config_ssh_trust root

config_ssh_trust oracle

config_ssh_trust grid

fi

setup_multipath

setup_udev

\[ $HA == rac ] && push_asm_config_remote

install_cvuqdisk

init_asm_disks

write_grid_rsp

install_grid

run_root_scripts_grid

create_data_dg

fi
write_netca_rsp

write_db_rsp

install_db

run_root_scripts_db

config_netca

create_db
log "===== 全部部署完成 ====="

}
main "$@"


  1. A-Za-z ↩︎

  2. A-Za-z ↩︎