!/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 | 23AI11G / 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 insingle) ;;
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 ]; thenrequire "-or" "OCR_REDU"; require "-od" "OCR_DISKS"
require "-dr" "DATA_REDU"; require "-dd" "DATA_DISKS"
fi
if \[ $HA == rac ]; thenrequire "-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 || trueeval "YUM_CMD" \>/dev/null 2\>\&1 \|\| die "无法挂载 yum 源: YUM_CMD"
umount /mnt >/dev/null 2>&1 || true
local ffor 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/nullcat >> /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" ]; thensed -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 || truesystemctl 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 ]; thenif \[ $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_rspwrite_db_rsp
install_db
run_root_scripts_db
config_netca
create_db
log "===== 全部部署完成 ====="}
main "$@"
分享一个oracle全版本的RAC部署脚本
刘子毅2026-10-30 17:15