别再找教程了!Oracle 26ai 一键安装,新版脚本直接用(脚本开源)
操作系统
一键安装
查看日志
查看日志

登录数据库
脚本如下:
#!/bin/bash# Oracle数据库一键安装脚本# 版本:3.0 set -euo pipefail# ========================= 全局配置=========================# 固定日志目录ORACLE_LOG_DIR="/var/log/oracle_install"# 主日志文件(记录所有步骤详细输出)MAIN_LOG="${ORACLE_LOG_DIR}/oracle_autoinstall_$(date +%Y%m%d_%H%M%S).log"# 步骤计数器(终端数字序号用)step_count=0# 颜色定义用于日志输出和终端步骤结果RED='\033[0;31m'GREEN='\033[0;32m'YELLOW='\033[1;33m'BLUE='\033[0;34m'NC='\033[0m' # No Color# ========================= 日志函数(核心修改:仅写入日志文件,不输出到终端)=========================# 所有详细日志仅写入MAIN_LOG,终端只显示步骤结果log_info() { echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" >> "${MAIN_LOG}"; }log_warn() { echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" >> "${MAIN_LOG}"; }log_error() { echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" >> "${MAIN_LOG}"; }log_step() { echo -e "${BLUE}[STEP]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" >> "${MAIN_LOG}"; }# ========================= 步骤执行函数(核心:数字序号+终端仅显示成功/失败)=========================# 用法:run_step "步骤名称" 步骤函数名# 终端仅输出「数字. 步骤名称: 成功/失败」,详细日志写入MAIN_LOGrun_step() { local step_name="$1" local step_func="$2" step_count=$((step_count + 1)) # 终端输出步骤序号和名称,等待执行结果 echo -n "${step_count}. ${step_name}: " # 执行步骤函数,所有输出重定向到主日志,判断执行结果 if $step_func >> "${MAIN_LOG}" 2>&1; then echo -e "${GREEN}成功${NC}" log_info "步骤${step_count} [${step_name}] 执行成功" else echo -e "${RED}失败${NC}" log_error "步骤${step_count} [${step_name}] 执行失败,终止安装" echo -e "${RED}[ERROR] 步骤${step_count} ${step_name}失败,详细日志见${MAIN_LOG}${NC}" exit 1 fi}start_time=$(date +%s)# 设置Oracle密码(符合Oracle安全标准)ORACLE_PASSWORD="Tiger@123"# 检测Oracle版本detect_oracle_version() { log_step "检测Oracle安装包版本..." local zip_file # 优先检查/soft目录,其次当前目录 for dir in /soft .; do zip_file=$(find "$dir" -maxdepth 1 -type f \( -name "*.zip" -o -name "*.tar.gz" \) 2>/dev/null | head -1) [[ -n "$zip_file" ]] && break done if [[ -z "$zip_file" ]]; then log_error "未找到Oracle安装包。请将安装包放置在当前目录或/soft目录下。" log_info "支持的安装包: LINUX.X64_112040_db_home.zip (11g), LINUX.X64_193000_db_home.zip (19c), LINUX.X64_2326100_db_home.zip (26ai)" exit 1 fi local filename=$(basename "$zip_file") log_info "找到安装包: $filename" INSTALLER_FILE="$zip_file" # 版本识别逻辑 if [[ "$filename" =~ 1120|11204|11g ]]; then ORACLE_VERSION="11g" ORACLE_RELEASE="11.2.0" RESPONSE_SCHEMA="v11_2_0" elif [[ "$filename" =~ 1930|19300|19c ]]; then ORACLE_VERSION="19c" ORACLE_RELEASE="19.0.0" RESPONSE_SCHEMA="v19_0_0" elif [[ "$filename" =~ 2326100|26ai|23c ]]; then ORACLE_VERSION="26ai" ORACLE_RELEASE="23.26.1" RESPONSE_SCHEMA="v23_0_0" else log_warn "无法精确识别版本,默认使用26ai配置" ORACLE_VERSION="26ai" ORACLE_RELEASE="23.26.1" RESPONSE_SCHEMA="v23_0_0" fi # 设置Oracle目录 ORACLE_BASE="/u01/app/oracle" ORACLE_HOME="$ORACLE_BASE/product/$ORACLE_RELEASE/dbhome_1" log_info "检测到: Oracle $ORACLE_VERSION" log_info "ORACLE_BASE: $ORACLE_BASE" log_info "ORACLE_HOME: $ORACLE_HOME"}# 调整共享内存大小adjust_shm_size() { log_step "调整共享内存大小..." # 检查当前共享内存大小 local current_shm=$(df -h /dev/shm | awk 'NR==2 {print $2}' 2>/dev/null || echo "0M") log_info "当前共享内存大小: $current_shm" # 提取数字和单位 local current_shm_num=$(echo "$current_shm" | sed 's/[A-Za-z]//g') local current_shm_unit=$(echo "$current_shm" | sed 's/[0-9.]//g') # 转换为MB(不使用bc,使用bash算术运算) local current_shm_mb=0 if [[ "$current_shm_unit" == "G" ]]; then # G转MB:乘以1024 current_shm_mb=$(echo "$current_shm_num * 1024" | awk '{printf "%d", $1 * 1024}') elif [[ "$current_shm_unit" == "M" ]]; then current_shm_mb=${current_shm_num%.*} elif [[ "$current_shm_unit" == "K" ]]; then # K转MB:除以1024 current_shm_mb=$(echo "$current_shm_num / 1024" | awk '{printf "%d", $1 / 1024}') fi log_info "当前共享内存大小(MB): ${current_shm_mb}MB" # 检查是否需要调整(Oracle需要至少2.5GB用于2048MB内存管理) if [[ $current_shm_mb -lt 2560 ]]; then log_info "共享内存不足,需要调整到至少3GB" # 备份fstab cp /etc/fstab /etc/fstab.bak.$(date +%Y%m%d_%H%M%S) # 检查是否已有/dev/shm配置 if grep -q "/dev/shm" /etc/fstab; then log_info "更新现有的/dev/shm配置" # 更新现有的配置 sed -i '/\/dev\/shm/d' /etc/fstab fi # 添加新的共享内存配置(3GB以确保足够) echo "tmpfs /dev/shm tmpfs defaults,size=3G 0 0" >> /etc/fstab # 重新挂载共享内存 mount -o remount /dev/shm 2>/dev/null || { log_warn "重新挂载/dev/shm失败,尝试umount后重新挂载" umount /dev/shm 2>/dev/null || true mount /dev/shm 2>/dev/null || true } # 验证挂载结果 local new_shm=$(df -h /dev/shm 2>/dev/null | awk 'NR==2 {print $2}' || echo "未知") log_info "共享内存已调整为: $new_shm" # 检查是否调整成功 local new_shm_size=$(df -m /dev/shm 2>/dev/null | awk 'NR==2 {print $2}' || echo "0") if [[ $new_shm_size -ge 3000 ]]; then log_info "共享内存调整成功: ${new_shm_size}MB" else log_warn "共享内存调整可能未完全生效,当前大小: ${new_shm_size}MB" log_info "您可能需要重启系统使共享内存设置生效" fi else log_info "共享内存大小已足够,无需调整" fi # 显示最终的共享内存状态 echo -e "\n${BLUE}共享内存状态:${NC}" >> "${MAIN_LOG}" df -h /dev/shm 2>/dev/null || echo "无法查看/dev/shm状态" >> "${MAIN_LOG}"}# 配置系统主机名和hosts文件configure_system_identity() { log_step "配置系统标识..." # 设置主机名 hostnamectl set-hostname myoracle 2>/dev/null || true # 配置hosts文件 local public_ip public_ip=$(hostname -I | awk '{print $1}' 2>/dev/null || echo "127.0.0.1") # 确保IP地址有效 [[ "$public_ip" == "0" || -z "$public_ip" ]] && public_ip="127.0.0.1" log_info "系统IP地址: $public_ip" # 更新/etc/hosts sed -i '/myoracle/d;/^'"$public_ip"'/d' /etc/hosts 2>/dev/null || true echo -e "# Oracle Database Configuration" >> /etc/hosts echo -e "${public_ip}\tmyoracle" >> /etc/hosts echo -e "127.0.0.1\tlocalhost" >> /etc/hosts log_info "主机名和hosts文件配置完成"}# 禁用安全模块disable_security() { log_step "禁用安全模块..." # 停止并禁用防火墙 if command -v systemctl &>/dev/null; then systemctl stop firewalld 2>/dev/null || true systemctl disable firewalld 2>/dev/null || true systemctl stop iptables 2>/dev/null || true systemctl disable iptables 2>/dev/null || true else service iptables stop 2>/dev/null || true chkconfig iptables off 2>/dev/null || true fi # 禁用SELinux if [[ -f /etc/selinux/config ]]; then sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config log_info "已永久禁用SELinux" fi setenforce 0 2>/dev/null || true log_info "安全模块配置完成"}# 创建Oracle用户和组create_oracle_user_and_groups() { log_step "创建Oracle用户和组..." # 创建用户组 for group in oinstall dba oper; do if ! getent group "$group" >/dev/null; then groupadd "$group" 2>/dev/null || { log_warn "创建组 $group 失败,尝试使用默认GID" groupadd -g 1001 "$group" 2>/dev/null || true } fi done # 创建Oracle用户 if ! id -u oracle >/dev/null 2>&1; then useradd -u 1000 -g oinstall -G dba,oper oracle 2>/dev/null || { log_warn "使用默认UID创建oracle用户失败,尝试自动分配UID" useradd -g oinstall -G dba,oper oracle 2>/dev/null || true } log_info "创建Oracle用户成功" fi # 设置Oracle用户密码 echo "oracle:oracle" | chpasswd 2>/dev/null || \ echo "oracle" | passwd --stdin oracle 2>/dev/null || { log_warn "设置Oracle用户密码失败,但继续安装" } log_info "Oracle用户和组创建完成"}# 准备安装目录结构prepare_directories() { log_step "准备Oracle安装目录..." # 创建所有必要的目录 mkdir -p /soft /mnt /u01/app/oracle /u01/app/oraInventory /home/oracle/response # 移动安装包到/soft目录(如果不在那里) if [[ -f "$INSTALLER_FILE" && "$(dirname "$INSTALLER_FILE")" != "/soft" ]]; then cp "$INSTALLER_FILE" /soft/ 2>/dev/null || { log_warn "无法复制安装包到/soft目录,将使用原路径" } fi # 设置目录权限 chown -R oracle:oinstall /u01 /home/oracle 2>/dev/null || { log_warn "更改目录所有者失败,但继续安装" } chmod -R 775 /u01 2>/dev/null || true log_info "目录结构准备完成"}# 挂载ISO镜像并配置本地YUM源mount_and_configure_yum() { log_step "配置本地YUM源..." # 1. 尝试挂载ISO local mounted=false for device in /dev/sr0 /dev/cdrom; do if [[ -b "$device" ]]; then mount "$device" /mnt 2>/dev/null && { mounted=true; break; } fi done if ! $mounted; then log_warn "未找到可挂载的ISO设备,跳过本地YUM源配置" return 0 fi log_info "ISO已挂载在/mnt" # 2. 备份原有YUM源配置 [[ -d /etc/yum.repos.d ]] && mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/ 2>/dev/null || true # 3. 创建本地YUM源 cat > /etc/yum.repos.d/local.repo << 'EOF'[localBaseOS]name=Local BaseOS Repositorybaseurl=file:///mnt/BaseOSgpgcheck=0enabled=1[localAppStream]name=Local AppStream Repositorybaseurl=file:///mnt/AppStreamgpgcheck=0enabled=1[local]name=Local Fallback Repositorybaseurl=file:///mntgpgcheck=0enabled=0EOF # 4. 测试YUM源并重建缓存 if yum repolist &>/dev/null; then yum clean all yum makecache log_info "本地YUM源配置成功" else # 如果标准路径失败,尝试回退到根目录 sed -i 's|file:///mnt/BaseOS|file:///mnt|' /etc/yum.repos.d/local.repo sed -i 's|file:///mnt/AppStream|file:///mnt|' /etc/yum.repos.d/local.repo sed -i 's/enabled=0/enabled=1/' /etc/yum.repos.d/local.repo if yum repolist &>/dev/null; then yum clean all yum makecache log_info "本地YUM源(回退模式)配置成功" else log_warn "YUM源配置失败,依赖安装可能受影响" fi fi}# 安装Oracle必需依赖包(增加Oracle 26ai需要的额外包)install_oracle_dependencies() { log_step "安装Oracle必需依赖包..." # Oracle 26ai/19c/11g 共同的核心依赖包 local core_packages=( bc binutils compat-libcap1 compat-libstdc++-33 elfutils-libelf fontconfig gcc gcc-c++ glibc glibc-devel ksh libaio libX11 libXau libXi libXtst libXrender libxcb libgcc libstdc++ libstdc++-devel make smartmontools sysstat unzip ) # 版本特定依赖包 if [[ "$ORACLE_VERSION" == "11g" ]]; then core_packages+=(compat-openssl10 libaio-devel.i686 libgcc.i686 libstdc++.i686) elif [[ "$ORACLE_VERSION" == "19c" ]]; then core_packages+=(libnsl) elif [[ "$ORACLE_VERSION" == "26ai" ]]; then # Oracle 26ai需要的额外依赖包(根据错误信息添加) core_packages+=( libnsl compat-openssl11 nfs-utils net-tools policycoreutils-python-utils # 以下是为确保兼容性添加的其他可能需要的包 libnsl2 libaio-devel libXrender-devel libXtst-devel libXi-devel libX11-devel libXau-devel libxcb-devel libibverbs librdmacm libasan liblsan ) fi log_info "开始安装 ${#core_packages[@]} 个核心依赖包..." # 确保bc包被安装(特别检查) if ! rpm -q bc &>/dev/null; then log_info "bc包未安装,正在安装bc..." yum install -y bc 2>&1 | tail -3 >> "${MAIN_LOG}" fi # 分组安装以提高效率 for ((i=0; i<${#core_packages[@]}; i+=5)); do local group=("${core_packages[@]:i:5}") log_info "安装包组: ${group[*]}" yum install -y "${group[@]}" 2>&1 | tail -5 >> "${MAIN_LOG}" || { log_warn "部分包安装失败,继续安装其他包" } done # 验证关键包是否安装成功 local critical_packages=(gcc make glibc-devel libaio unzip bc) if [[ "$ORACLE_VERSION" == "26ai" ]]; then critical_packages+=(compat-openssl11 nfs-utils net-tools policycoreutils-python-utils) fi local missing_packages=() for pkg in "${critical_packages[@]}"; do if ! rpm -q "$pkg" &>/dev/null; then missing_packages+=("$pkg") fi done if [[ ${#missing_packages[@]} -gt 0 ]]; then log_warn "以下关键包可能未安装成功: ${missing_packages[*]}" log_info "尝试使用通用包名重新安装..." for pkg in "${missing_packages[@]}"; do yum install -y "$pkg" 2>&1 | tail -3 >> "${MAIN_LOG}" || true done else log_info "所有关键依赖包安装成功" fi log_info "依赖包安装完成"}# 配置Oracle用户环境configure_oracle_environment() { log_step "配置Oracle用户环境..." # 配置Oracle用户环境 cat > /home/oracle/.bash_profile << 'EOF'# Oracle Environmentexport ORACLE_BASE=/u01/app/oracleexport ORACLE_HOME=$ORACLE_BASE/product/@@ORACLE_RELEASE@@/dbhome_1export ORACLE_SID=orclexport PATH=$ORACLE_HOME/bin:$PATHexport LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/libexport NLS_LANG=AMERICAN_AMERICA.AL32UTF8export NLS_DATE_FORMAT="YYYY-MM-DD HH24:MI:SS"umask 022EOF # 替换版本号占位符 sed -i "s/@@ORACLE_RELEASE@@/$ORACLE_RELEASE/" /home/oracle/.bash_profile # 设置权限 chown oracle:oinstall /home/oracle/.bash_profile 2>/dev/null || true chmod 644 /home/oracle/.bash_profile 2>/dev/null || true log_info "Oracle用户环境配置完成"}# 配置系统内核参数configure_system_parameters() { log_step "配置系统内核参数..." # 计算shmmax和shmall(基于可用内存) local mem_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}') local shmmax=$((mem_kb * 1024 * 80 / 100)) # 80% of memory local shmall=$((shmmax / 4096)) log_info "系统内存: $((mem_kb / 1024))MB" log_info "计算参数: shmmax=$shmmax, shmall=$shmall" # 配置sysctl参数 cat > /etc/sysctl.d/99-oracle.conf << EOF# Oracle Database 26ai/19c/11g Kernel Parametersfs.aio-max-nr = 1048576fs.file-max = 6815744kernel.shmall = $shmallkernel.shmmax = $shmmaxkernel.shmmni = 4096kernel.sem = 250 32000 100 128net.ipv4.ip_local_port_range = 9000 65500net.core.rmem_default = 262144net.core.rmem_max = 4194304net.core.wmem_default = 262144net.core.wmem_max = 1048576vm.swappiness = 10EOF # 应用内核参数 sysctl -p /etc/sysctl.d/99-oracle.conf 2>/dev/null || { log_warn "应用内核参数失败,但继续安装" } # 配置用户资源限制 cat > /etc/security/limits.d/oracle.conf << EOF# Oracle user resource limitsoracle soft nofile 1024oracle hard nofile 65536oracle soft nproc 2047oracle hard nproc 16384oracle soft stack 10240oracle hard stack 32768EOF # 配置PAM grep -q "pam_limits.so" /etc/pam.d/login || \ echo "session required pam_limits.so" >> /etc/pam.d/login log_info "系统内核参数配置完成"}# 解压Oracle安装包extract_oracle_installer() { log_step "解压Oracle安装包..." # 清理并创建ORACLE_HOME目录 [[ -d "$ORACLE_HOME" ]] && rm -rf "$ORACLE_HOME" mkdir -p "$ORACLE_HOME" chown -R oracle:oinstall "$ORACLE_HOME" 2>/dev/null || true log_info "解压安装包到: $ORACLE_HOME" # 根据文件类型解压 case "$INSTALLER_FILE" in *.zip) # 使用Oracle用户解压,保持文件权限 su - oracle -c "unzip -q $INSTALLER_FILE -d $ORACLE_HOME" 2>&1 | tail -10 >> "${MAIN_LOG}" || { log_error "解压安装包失败" return 1 } ;; *.tar.gz) su - oracle -c "tar -xzf $INSTALLER_FILE -C $ORACLE_HOME" 2>&1 | tail -10 >> "${MAIN_LOG}" || { log_error "解压安装包失败" return 1 } ;; *) log_error "不支持的安装包格式" return 1 ;; esac # 检查解压结果 if [[ -f "$ORACLE_HOME/runInstaller" ]]; then log_info "安装包解压成功,runInstaller已就绪" elif [[ -d "$ORACLE_HOME/database" && -f "$ORACLE_HOME/database/runInstaller" ]]; then # 处理解压到子目录的情况 mv "$ORACLE_HOME"/database/* "$ORACLE_HOME"/ 2>/dev/null || { log_warn "移动文件失败,尝试直接使用子目录" ORACLE_HOME="$ORACLE_HOME/database" } rmdir "$ORACLE_HOME/database" 2>/dev/null || true log_info "安装包解压成功(从子目录移动)" else log_warn "未找到runInstaller,尝试查找..." local found_installer=$(find "$ORACLE_HOME" -name "runInstaller" -type f 2>/dev/null | head -1) if [[ -n "$found_installer" ]]; then log_info "找到runInstaller: $found_installer" else log_error "未找到runInstaller,安装包可能损坏或格式不正确" return 1 fi fi # 确保权限正确 chown -R oracle:oinstall "$ORACLE_HOME" 2>/dev/null || true log_info "安装包解压完成"}# 创建静默安装响应文件create_response_files() { log_step "创建静默安装响应文件..." local response_dir="/home/oracle/response" mkdir -p "$response_dir" chown -R oracle:oinstall "$response_dir" 2>/dev/null || true # 根据Oracle版本创建不同的响应文件 if [[ "$ORACLE_VERSION" == "11g" ]]; then # 11g响应文件 cat > "$response_dir/db_install.rsp" << EOForacle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v11_2_0oracle.install.option=INSTALL_DB_SWONLYORACLE_HOSTNAME=myoracleUNIX_GROUP_NAME=oinstallINVENTORY_LOCATION=/u01/app/oraInventorySELECTED_LANGUAGES=enORACLE_HOME=$ORACLE_HOMEORACLE_BASE=$ORACLE_BASEoracle.install.db.InstallEdition=EEoracle.install.db.DBA_GROUP=dbaoracle.install.db.OPER_GROUP=oinstallSECURITY_UPDATES_VIA_MYORACLESUPPORT=falseDECLINE_SECURITY_UPDATES=trueEOF elif [[ "$ORACLE_VERSION" == "19c" ]]; then # 19c响应文件 cat > "$response_dir/db_install.rsp" << EOForacle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v19_0_0oracle.install.option=INSTALL_DB_SWONLYORACLE_HOSTNAME=myoracleUNIX_GROUP_NAME=oinstallINVENTORY_LOCATION=/u01/app/oraInventorySELECTED_LANGUAGES=enORACLE_HOME=$ORACLE_HOMEORACLE_BASE=$ORACLE_BASEoracle.install.db.InstallEdition=EEoracle.install.db.OSDBA_GROUP=dbaoracle.install.db.OSOPER_GROUP=operoracle.install.db.OSBACKUPDBA_GROUP=dbaoracle.install.db.OSDGDBA_GROUP=dbaoracle.install.db.OSKMDBA_GROUP=dbaSECURITY_UPDATES_VIA_MYORACLESUPPORT=falseDECLINE_SECURITY_UPDATES=trueEOF else # 26ai响应文件 cat > "$response_dir/db_install.rsp" << EOForacle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v23_0_0oracle.install.option=INSTALL_DB_SWONLYORACLE_HOSTNAME=myoracleUNIX_GROUP_NAME=oinstallINVENTORY_LOCATION=/u01/app/oraInventorySELECTED_LANGUAGES=enORACLE_HOME=$ORACLE_HOMEORACLE_BASE=$ORACLE_BASEoracle.install.db.InstallEdition=EEoracle.install.db.OSDBA_GROUP=dbaoracle.install.db.OSOPER_GROUP=operoracle.install.db.OSBACKUPDBA_GROUP=dbaoracle.install.db.OSDGDBA_GROUP=dbaoracle.install.db.OSKMDBA_GROUP=dbaoracle.install.db.OSRACDBA_GROUP=dbaSECURITY_UPDATES_VIA_MYORACLESUPPORT=falseDECLINE_SECURITY_UPDATES=trueEOF fi # 网络配置助手响应文件(简化版本) cat > "$response_dir/netca.rsp" << EOF[GENERAL]RESPONSEFILE_VERSION="23.0"CREATE_TYPE="CUSTOM"[oracle.net.ca]INSTALLED_COMPONENTS={"server","net8","javavm"}INSTALL_TYPE="typical"LISTENER_NUMBER=1LISTENER_NAMES={"LISTENER"}LISTENER_PROTOCOLS={"TCP;1521"}LISTENER_START="LISTENER"NAMING_METHODS={"TNSNAMES","ONAMES","HOSTNAME"}EOF # 数据库创建助手响应文件(针对Oracle 26ai/23c的新格式) if [[ "$ORACLE_VERSION" == "26ai" ]]; then # Oracle 26ai使用新的响应文件格式,创建容器数据库(CDB) cat > "$response_dir/dbca.rsp" << EOFresponseFileVersion=/oracle/assistants/rspfmt_dbca_response_schema_v23.0.0gdbName=orclsid=orcldatabaseConfigType=SIcreateAsContainerDatabase=truenumberOfPDBs=1pdbName=pdb1templateName=General_Purpose.dbcoracleHomeUserPassword=${ORACLE_PASSWORD}sysPassword=${ORACLE_PASSWORD}systemPassword=${ORACLE_PASSWORD}pdbAdminPassword=${ORACLE_PASSWORD}datafileDestination=/u01/app/oracle/oradatacharacterSet=AL32UTF8nationalCharacterSet=UTF8databaseType=OLTPautomaticMemoryManagement=truetotalMemory=2048redoLogFileSize=100EOF else # 其他版本使用旧格式 cat > "$response_dir/dbca.rsp" << EOF[GENERAL]RESPONSEFILE_VERSION = "11.2.0"OPERATION_TYPE = "createDatabase"[CREATEDATABASE]GDBNAME = "orcl"SID = "orcl"TEMPLATENAME = "General_Purpose.dbc"SYSPASSWORD = ${ORACLE_PASSWORD}SYSTEMPASSWORD = ${ORACLE_PASSWORD}DATAFILEDESTINATION= $ORACLE_BASE/oradataRECOVERYAREADESTINATION= $ORACLE_BASE/fast_recovery_areaCHARACTERSET = "AL32UTF8"NATIONALCHARACTERSET= "UTF8"AUTOMATICMEMORYMANAGEMENT = "TRUE"TOTALMEMORY = "2048"EOF fi chmod 644 "$response_dir"/*.rsp 2>/dev/null || true log_info "响应文件创建完成: $response_dir/" log_info "使用密码: ${ORACLE_PASSWORD} (符合Oracle安全标准)"}# 静默安装Oracle软件install_oracle_software() { log_step "开始静默安装Oracle数据库软件..." # 确保ORACLE_HOME存在且有权 mkdir -p "$ORACLE_HOME" chown -R oracle:oinstall "$ORACLE_HOME" 2>/dev/null || true local response_file="/home/oracle/response/db_install.rsp" log_info "使用响应文件: $response_file" # 检查runInstaller是否存在 if [[ ! -f "$ORACLE_HOME/runInstaller" ]]; then # 尝试在子目录中查找 local found_installer=$(find "$ORACLE_HOME" -name "runInstaller" -type f 2>/dev/null | head -1) if [[ -n "$found_installer" ]]; then log_info "找到runInstaller: $found_installer" else log_error "错误: 在 $ORACLE_HOME 中未找到 runInstaller" log_info "请检查安装包是否已正确解压" return 1 fi fi log_info "开始执行Oracle安装,此过程需要15-30分钟..." # 创建安装日志文件(独立日志,便于排查) local install_log="${ORACLE_LOG_DIR}/oracle_software_install.log" # 以Oracle用户执行安装 su - oracle << EOF 2>&1 | tee "$install_log" &export ORACLE_BASE=$ORACLE_BASEexport ORACLE_HOME=$ORACLE_HOMEexport PATH=\$ORACLE_HOME/bin:\$PATHcd $ORACLE_HOMEecho "=========================================="echo "Oracle $ORACLE_VERSION 静默安装开始"echo "时间: \$(date)"echo "ORACLE_HOME: \$ORACLE_HOME"echo "=========================================="# 执行安装命令./runInstaller -silent -responseFile $response_file -ignorePrereqFailure -waitforcompletionecho "安装程序已启动,请等待完成..."EOF local install_pid=$! log_info "安装进程PID: $install_pid" # 等待安装完成 local max_wait=2400 # 40分钟 local wait_time=0 local interval=30 while [[ $wait_time -lt $max_wait ]]; do if ps -p $install_pid > /dev/null 2>&1; then echo -n "." >> "${MAIN_LOG}" sleep $interval wait_time=$((wait_time + interval)) # 每5分钟输出一次进度 if [[ $((wait_time % 300)) -eq 0 ]]; then echo "" >> "${MAIN_LOG}" log_info "已等待 $((wait_time/60)) 分钟,安装仍在进行中..." fi else echo "" >> "${MAIN_LOG}" break fi done # 检查安装结果 if [[ -f "$ORACLE_HOME/bin/oracle" ]]; then log_info "Oracle软件安装成功!" else log_warn "Oracle二进制文件未找到,安装可能有问题" log_info "请检查安装日志: $install_log" log_info "和Oracle日志: $ORACLE_BASE/oraInventory/logs/" fi # 检查超时 if [[ $wait_time -ge $max_wait ]]; then log_warn "安装超时(超过40分钟),进程可能仍在运行" log_info "可以手动检查进程状态: ps -p $install_pid" fi log_info "Oracle软件安装阶段完成"}# 执行root配置脚本execute_root_scripts() { log_step "执行Oracle root配置脚本..." # 1. 执行orainstRoot.sh local orainst_script="/u01/app/oraInventory/orainstRoot.sh" if [[ -f "$orainst_script" ]]; then log_info "执行: $orainst_script" echo "y" | "$orainst_script" else log_warn "未找到 $orainst_script,尝试在其他位置查找..." find /u01 -name "orainstRoot.sh" 2>/dev/null | head -1 | while read found_script; do log_info "在其他位置找到并执行: $found_script" echo "y" | "$found_script" done fi # 2. 执行root.sh local root_script="$ORACLE_HOME/root.sh" if [[ -f "$root_script" ]]; then log_info "执行: $root_script" log_info "提示:如果脚本询问本地 bin 目录,请输入 'y'" # 修复root.sh脚本中可能存在的路径问题 if grep -q "/product/23.0.0/" "$root_script" 2>/dev/null; then log_info "检测到root.sh中的版本路径问题,尝试修复..." sed -i "s|/product/23.0.0/|/product/23.26.1/|g" "$root_script" 2>/dev/null || true fi # 执行脚本,并提供必要的输入 echo -e "y\ny" | "$root_script" else log_error "错误:未找到 $root_script" log_info "尝试查找其他位置的 root.sh..." find "$ORACLE_BASE" -name "root.sh" -type f 2>/dev/null | head -1 | while read found_root; do log_info "找到并执行: $found_root" echo -e "y\ny" | "$found_root" done fi log_info "root脚本执行完成"}# 配置Oracle监听器configure_oracle_listener() { log_step "配置Oracle监听器..." local netca_log="${ORACLE_LOG_DIR}/oracle_netca_config.log" su - oracle << EOF 2>&1 | tee "$netca_log"export ORACLE_HOME=$ORACLE_HOMEexport PATH=\$ORACLE_HOME/bin:\$PATHecho "配置Oracle监听器..."netca -silent -responseFile /home/oracle/response/netca.rspsleep 5echo "启动监听器..."lsnrctl startecho "监听器状态:"lsnrctl status | grep -E "(Status|Start|PORT)" | head -5EOF # 检查监听器状态 if su - oracle -c "lsnrctl status" 2>/dev/null | grep -q "STATUS.*READY"; then log_info "Oracle监听器配置成功" else log_warn "监听器可能未正确启动,请检查: $netca_log" fi}# 创建Oracle数据库实例(核心修复:PDB语句替换)create_oracle_database() { log_step "创建Oracle数据库实例..." # 创建数据库文件目录 mkdir -p "$ORACLE_BASE/oradata" "$ORACLE_BASE/fast_recovery_area" chown -R oracle:oinstall "$ORACLE_BASE/oradata" "$ORACLE_BASE/fast_recovery_area" 2>/dev/null || true log_info "开始创建数据库,此过程需要10-20分钟..." local dbca_log="${ORACLE_LOG_DIR}/oracle_dbca_create.log" # 先检查共享内存是否足够 log_info "检查共享内存是否足够..." local shm_available=$(df -m /dev/shm 2>/dev/null | awk 'NR==2 {print $4}' || echo "0") local required_memory=2560 # 需要2.5GB用于2048MB内存管理 if [[ $shm_available -lt $required_memory ]]; then log_warn "共享内存不足,当前可用: ${shm_available}MB,需要: ${required_memory}MB" log_info "尝试重新调整共享内存大小..." adjust_shm_size fi # 根据Oracle版本使用不同的dbca命令 su - oracle << EOF 2>&1 | tee "$dbca_log"export ORACLE_HOME=$ORACLE_HOMEexport ORACLE_SID=orclexport PATH=\$ORACLE_HOME/bin:\$PATHecho "=========================================="echo "开始创建Oracle数据库"echo "时间: \$(date)"echo "共享内存状态:"df -h /dev/shm 2>/dev/null || echo "无法获取共享内存状态"echo "使用密码: ${ORACLE_PASSWORD}"echo "=========================================="# 检查响应文件是否存在if [[ ! -f "/home/oracle/response/dbca.rsp" ]]; then echo "错误: 响应文件不存在" exit 1fi# 根据Oracle版本执行不同的dbca命令if [[ "$ORACLE_VERSION" == "26ai" ]]; then echo "使用Oracle 26ai格式的响应文件(创建CDB容器数据库)" echo "响应文件内容摘要:" grep -E "(gdbName|sid|createAsContainerDatabase|pdbName|templateName|totalMemory|sysPassword|systemPassword|pdbAdminPassword)" /home/oracle/response/dbca.rsp echo "" # 对于26ai,使用新的响应文件格式 dbca -silent -createDatabase -responseFile /home/oracle/response/dbca.rspelse echo "使用传统格式的响应文件" # 对于其他版本,使用传统方式 dbca -silent -responseFile /home/oracle/response/dbca.rspfiecho "数据库创建命令执行完成,退出状态: \$?"EOF # 等待数据库创建完成 sleep 30 # 验证数据库状态 log_info "验证数据库状态..." local db_status_log="${ORACLE_LOG_DIR}/oracle_db_status_check.log" su - oracle << 'EOF' 2>&1 | tee "$db_status_log"export ORACLE_HOME=$ORACLE_HOMEexport ORACLE_SID=orclexport PATH=$ORACLE_HOME/bin:$PATHecho "检查数据库状态..."# 等待数据库启动for i in {1..30}; do echo "尝试连接数据库 ($i/30)..." if echo "exit" | sqlplus -s / as sysdba >/dev/null 2>&1; then echo "数据库连接成功" break fi sleep 5doneecho ""echo "=== 数据库状态信息 ==="sqlplus -s / as sysdba << SQLset pagesize 100 linesize 120col "Database Info" format a60select 'CDB状态: ' || cdb as "Database Info" from v\$database;select '实例状态: ' || status as "Database Info" from v\$instance;select '数据库名称: ' || name as "Database Info" from v\$database;select '字符集: ' || value as "Database Info" from nls_database_parameters where parameter = 'NLS_CHARACTERSET';-- 核心修改:删除原STATUS查询,执行指定的打开PDB1+show pdbswhenever sqlerror continuealter session set container=cdb\$root;ALTER PLUGGABLE DATABASE PDB1 OPEN;show pdbs;exit;SQL# 检查监听器状态echo ""echo "=== 监听器状态 ==="lsnrctl status | grep -A5 "Services Summary"EOF # 检查数据库是否创建成功 if grep -q "实例状态: OPEN" "$db_status_log" 2>/dev/null || \ grep -q "Database opened" "$db_status_log" 2>/dev/null || \ grep -q "READ WRITE" "$db_status_log" 2>/dev/null; then log_info "Oracle数据库创建成功!" return 0 else log_warn "数据库可能未正确创建,检查日志..." # 检查日志文件中的错误信息 if grep -q "DBCA Operation failed" "$dbca_log" 2>/dev/null; then log_error "dbca操作失败,详细信息:" tail -30 "$dbca_log" >> "${MAIN_LOG}" # 如果是共享内存问题,尝试使用手动内存管理 if grep -q "自动内存管理" "$dbca_log" && grep -q "没有足够的空闲空间" "$dbca_log"; then log_info "检测到自动内存管理问题,尝试使用手动内存管理..." create_database_with_manual_memory return $? fi fi # 尝试手动启动数据库 log_info "尝试手动启动数据库..." manual_start_database fi}# 使用手动内存管理创建数据库create_database_with_manual_memory() { log_info "尝试使用手动内存管理创建数据库..." local manual_memory_log="${ORACLE_LOG_DIR}/oracle_dbca_manual_memory.log" su - oracle << 'EOF' 2>&1 | tee "$manual_memory_log"export ORACLE_HOME=$ORACLE_HOMEexport ORACLE_SID=orclexport PATH=$ORACLE_HOME/bin:$PATHecho "使用手动内存管理创建数据库..."# 使用命令行参数创建数据库,禁用自动内存管理dbca -silent \ -createDatabase \ -templateName General_Purpose.dbc \ -gdbName orcl \ -sid orcl \ -responseFile NO_VALUE \ -characterSet AL32UTF8 \ -nationalCharacterSet UTF8 \ -sysPassword ${ORACLE_PASSWORD} \ -systemPassword ${ORACLE_PASSWORD} \ -createAsContainerDatabase true \ -numberOfPDBs 1 \ -pdbName pdb1 \ -pdbAdminPassword ${ORACLE_PASSWORD} \ -databaseType OLTP \ -memoryMgmtType auto_sga \ -totalMemory 1024 \ -storageType FS \ -datafileDestination /u01/app/oracle/oradata \ -enableArchive false \ -recoveryAreaDestination /u01/app/oracle/fast_recovery_area \ -recoveryAreaSize 1024 \ -redoLogFileSize 50 \ -sampleSchema false \ -automaticMemoryManagement false \ -emConfiguration NONEecho "手动内存管理数据库创建完成,退出状态: $?"EOF # 等待并验证结果 sleep 30 check_database_status}# 检查数据库状态check_database_status() { log_info "检查数据库状态..." local status_log="${ORACLE_LOG_DIR}/oracle_db_status_final.log" su - oracle << 'EOF' 2>&1 | tee "$status_log"export ORACLE_HOME=$ORACLE_HOMEexport ORACLE_SID=orclexport PATH=$ORACLE_HOME/bin:$PATHecho "检查数据库连接..."for i in {1..10}; do if echo "exit" | sqlplus -s / as sysdba >/dev/null 2>&1; then echo "数据库连接成功" break fi echo "尝试 $i/10..." sleep 5doneecho ""echo "=== 数据库当前状态 ==="sqlplus -s / as sysdba << SQLset pagesize 100 linesize 120col "Database Info" format a60select '实例状态: ' || status as "Database Info" from v\$instance;select '数据库名称: ' || name as "Database Info" from v\$database;select 'CDB状态: ' || cdb as "Database Info" from v\$database;select '内存管理模式: ' || value as "Database Info" from v\$parameter where name = 'memory_target';-- 核心修改:执行打开PDB1+show pdbswhenever sqlerror continuealter session set container=cdb\$root;ALTER PLUGGABLE DATABASE PDB1 OPEN;show pdbs;exit;SQLEOF if grep -q "实例状态: OPEN" "$status_log" 2>/dev/null; then log_info "数据库创建成功!" return 0 else log_error "数据库创建失败" return 1 fi}# 手动启动数据库(备用方法)manual_start_database() { log_info "尝试手动启动数据库..." local manual_start_log="${ORACLE_LOG_DIR}/oracle_db_manual_start.log" su - oracle << 'EOF' 2>&1 | tee "$manual_start_log"export ORACLE_HOME=$ORACLE_HOMEexport ORACLE_SID=orclexport PATH=$ORACLE_HOME/bin:$PATHecho "检查数据库状态..."sqlplus / as sysdba << SQLstartupselect name, open_mode, cdb from v\$database;select instance_name, status from v\$instance;-- 核心修改:执行指定的打开PDB1+show pdbswhenever sqlerror continuealter session set container=cdb\$root;ALTER PLUGGABLE DATABASE PDB1 OPEN;show pdbs;exit;SQLEOF # 验证手动启动结果 if grep -q "DATABASE IS OPEN" "$manual_start_log" 2>/dev/null || \ grep -q "READ WRITE" "$manual_start_log" 2>/dev/null; then log_info "数据库启动成功!" return 0 else log_error "数据库启动失败,请检查日志" return 1 fi}# 配置Oracle自启动服务configure_autostart() { log_step "配置Oracle自启动服务..." # 配置/etc/oratab sed -i '/^orcl/d' /etc/oratab 2>/dev/null || true echo "orcl:$ORACLE_HOME:Y" >> /etc/oratab # 创建系统服务脚本 cat > /etc/init.d/oracle << EOF#!/bin/bash# chkconfig: 345 99 10# description: Oracle Database auto start-stop scriptORACLE_OWNER=oracleORACLE_HOME=$ORACLE_HOMEcase "\$1" instart) echo -n "启动Oracle数据库: " su - \$ORACLE_OWNER -c "export ORACLE_SID=orcl; \$ORACLE_HOME/bin/dbstart \$ORACLE_HOME" echo "完成" ;;stop) echo -n "停止Oracle数据库: " su - \$ORACLE_OWNER -c "export ORACLE_SID=orcl; \$ORACLE_HOME/bin/dbshut \$ORACLE_HOME" echo "完成" ;;restart) \$0 stop \$0 start ;;status) su - \$ORACLE_OWNER -c "export ORACLE_SID=orcl; echo 'exit' | sqlplus -s / as sysdba | grep -i 'ORACLE instance'" ;;*) echo "用法: \$0 {start|stop|restart|status}" exit 1esacexit 0EOF chmod 755 /etc/init.d/oracle # 配置服务自启动 if command -v chkconfig &>/dev/null; then chkconfig --add oracle chkconfig oracle on log_info "Oracle服务已配置为开机自启动 (chkconfig)" elif command -v systemctl &>/dev/null; then # 创建systemd服务文件 cat > /etc/systemd/system/oracle.service << SYSTEMD[Unit]Description=Oracle Database ServiceAfter=network.target[Service]Type=forkingEnvironment=ORACLE_HOME=$ORACLE_HOMEEnvironment=ORACLE_SID=orclExecStart=/etc/init.d/oracle startExecStop=/etc/init.d/oracle stopUser=oracleGroup=oinstall[Install]WantedBy=multi-user.targetSYSTEMD systemctl daemon-reload systemctl enable oracle log_info "Oracle服务已配置为开机自启动 (systemd)" fi # 启动Oracle服务 /etc/init.d/oracle start log_info "Oracle自启动服务配置完成"}# 完成安装并显示总结信息(简化终端输出,仅显示核心信息)complete_installation() { log_step "Oracle数据库安装完成,生成总结信息" end_time=$(date +%s) execution_time=$((end_time - start_time)) execution_minutes=$((execution_time / 60)) execution_seconds=$((execution_time % 60)) # 总结信息写入日志 cat << EOF >> "${MAIN_LOG}"======================================================= Oracle $ORACLE_VERSION 数据库安装成功!=======================================================安装信息总结:-------------------------------------------------------- 数据库版本: Oracle $ORACLE_VERSION $ORACLE_RELEASE- 主机名称: $(hostname)- 系统时间: $(date)- 安装用时: ${execution_minutes}分${execution_seconds}秒- 数据库类型: $( [[ "$ORACLE_VERSION" == "26ai" ]] && echo "容器数据库(CDB)" || echo "单实例数据库" )- 共享内存大小: $(df -h /dev/shm 2>/dev/null | awk 'NR==2 {print $2}' || echo "未知")- 数据库密码: ${ORACLE_PASSWORD}关键目录路径:- ORACLE_BASE: $ORACLE_BASE- ORACLE_HOME: $ORACLE_HOME- 数据库文件: $ORACLE_BASE/oradata- 监听日志: $ORACLE_HOME/network/log- 安装日志: ${ORACLE_LOG_DIR}数据库连接信息:1. 本地操作系统认证: su - oracle sqlplus / as sysdba2. 连接到PDB (如果是CDB): sqlplus sys/${ORACLE_PASSWORD}@//localhost:1521/pdb1 as sysdba 或者: sqlplus / as sysdba SQL> alter session set container=pdb1;3. 使用密码连接: 用户名: system 密 码: ${ORACLE_PASSWORD} 连接字符串: sqlplus system/${ORACLE_PASSWORD}@//localhost:1521/orcl服务管理命令:- 启动数据库: /etc/init.d/oracle start- 停止数据库: /etc/init.d/oracle stop- 重启数据库: /etc/init.d/oracle restart- 数据库状态: /etc/init.d/oracle status- 监听器状态: su - oracle -c "lsnrctl status"重要提醒:1. 首次登录后请立即修改默认密码 ${ORACLE_PASSWORD}!2. 生产环境请配置防火墙规则开放1521端口3. 定期检查$ORACLE_BASE/oradata目录空间4. 查看$ORACLE_HOME/network/admin/listener.ora配置=======================================================EOF # 终端仅显示简化的安装完成信息 echo -e "\n${GREEN}=======================================================${NC}" echo -e "${GREEN} Oracle $ORACLE_VERSION 数据库一键安装完成!${NC}" echo -e "${GREEN}=======================================================${NC}" echo -e "${BLUE}核心信息:${NC}" echo -e " 数据库密码: ${ORACLE_PASSWORD}" echo -e " 安装日志: ${ORACLE_LOG_DIR}" echo -e " 服务管理: /etc/init.d/oracle {start|stop|restart|status}" echo -e " 本地连接: su - oracle && sqlplus / as sysdba" echo -e "${GREEN}=======================================================${NC}" echo -e "${YELLOW}提醒: 首次登录请立即修改默认密码,生产环境开放1521端口!${NC}\n"}# 主函数:控制安装流程main() { clear echo "==============================================" echo " Oracle数据库一键安装脚本 (v3.0 )" echo " 支持: Oracle 11g, 19c, 26ai (23c)" echo " 终端输出: 仅显示步骤结果 | 详细日志: ${ORACLE_LOG_DIR}" echo " 数据库密码: ${ORACLE_PASSWORD}" echo "==============================================" echo "" # 检查root权限 [[ "$(id -u)" != "0" ]] && { echo -e "${RED}[ERROR] 请使用root用户运行此脚本${NC}" exit 1 } # 创建日志目录并设置权限 mkdir -p "${ORACLE_LOG_DIR}" chown -R oracle:oinstall "${ORACLE_LOG_DIR}" 2>/dev/null || true chmod -R 775 "${ORACLE_LOG_DIR}" 2>/dev/null || true echo -e "${BLUE}初始化日志目录: ${ORACLE_LOG_DIR}(所有详细日志均输出至此)${NC}\n" # 记录开始时间 log_info "Oracle数据库一键安装流程启动,主日志: ${MAIN_LOG}" # 执行所有安装步骤(核心:run_step 数字序号+极简终端输出) run_step "检测Oracle安装包版本" detect_oracle_version run_step "配置系统主机名和hosts" configure_system_identity run_step "禁用防火墙和SELinux" disable_security run_step "创建Oracle用户和组" create_oracle_user_and_groups run_step "配置本地YUM源" mount_and_configure_yum run_step "安装Oracle必需依赖包" install_oracle_dependencies run_step "准备Oracle安装目录" prepare_directories run_step "调整系统共享内存大小" adjust_shm_size run_step "配置Oracle用户环境变量" configure_oracle_environment run_step "配置系统内核参数" configure_system_parameters run_step "解压Oracle安装包" extract_oracle_installer run_step "创建静默安装响应文件" create_response_files run_step "静默安装Oracle数据库软件" install_oracle_software run_step "执行Oracle root配置脚本" execute_root_scripts run_step "配置并启动Oracle监听器" configure_oracle_listener run_step "创建Oracle数据库实例" create_oracle_database run_step "配置Oracle开机自启动服务" configure_autostart run_step "生成安装总结信息" complete_installation}# 执行主函数,所有输出已通过run_step和log函数分离(终端极简,日志详细)mainexit 0操作系统及数据库软件下载地址:
操作系统下载地址:https://yum.oracle.com/oracle-linux-isos.html 操作系统下载
26ai下载 :https://www.oracle.com/database/technologies/oracle26ai-linux-downloads.html数据库软件下载
说明:脚本默认的安装包路径在/soft下面
文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有