脚本再升级,兼容Oracle 26ai一键安装





脚本如下:

bash 复制代码
#!/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_LOG
run_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 Repository
baseurl=file:///mnt/BaseOS
gpgcheck=0
enabled=1

[localAppStream]
name=Local AppStream Repository
baseurl=file:///mnt/AppStream
gpgcheck=0
enabled=1

[local]
name=Local Fallback Repository
baseurl=file:///mnt
gpgcheck=0
enabled=0
EOF
    
    # 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 Environment
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/@@ORACLE_RELEASE@@/dbhome_1
export ORACLE_SID=orcl
export PATH=$ORACLE_HOME/bin:$PATH
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
export NLS_DATE_FORMAT="YYYY-MM-DD HH24:MI:SS"
umask 022
EOF
    
    # 替换版本号占位符
    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 Parameters
fs.aio-max-nr = 1048576
fs.file-max = 6815744
kernel.shmall = $shmall
kernel.shmmax = $shmmax
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
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
vm.swappiness = 10
EOF
    
    # 应用内核参数
    sysctl -p /etc/sysctl.d/99-oracle.conf 2>/dev/null || {
        log_warn "应用内核参数失败,但继续安装"
    }
    
    # 配置用户资源限制
    cat > /etc/security/limits.d/oracle.conf << EOF
# Oracle user resource limits
oracle soft nofile 1024
oracle hard nofile 65536
oracle soft nproc 2047
oracle hard nproc 16384
oracle soft stack 10240
oracle hard stack 32768
EOF
    
    # 配置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" << EOF
oracle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v11_2_0
oracle.install.option=INSTALL_DB_SWONLY
ORACLE_HOSTNAME=myoracle
UNIX_GROUP_NAME=oinstall
INVENTORY_LOCATION=/u01/app/oraInventory
SELECTED_LANGUAGES=en
ORACLE_HOME=$ORACLE_HOME
ORACLE_BASE=$ORACLE_BASE
oracle.install.db.InstallEdition=EE
oracle.install.db.DBA_GROUP=dba
oracle.install.db.OPER_GROUP=oinstall
SECURITY_UPDATES_VIA_MYORACLESUPPORT=false
DECLINE_SECURITY_UPDATES=true
EOF
    elif [[ "$ORACLE_VERSION" == "19c" ]]; then
        # 19c响应文件
        cat > "$response_dir/db_install.rsp" << EOF
oracle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v19_0_0
oracle.install.option=INSTALL_DB_SWONLY
ORACLE_HOSTNAME=myoracle
UNIX_GROUP_NAME=oinstall
INVENTORY_LOCATION=/u01/app/oraInventory
SELECTED_LANGUAGES=en
ORACLE_HOME=$ORACLE_HOME
ORACLE_BASE=$ORACLE_BASE
oracle.install.db.InstallEdition=EE
oracle.install.db.OSDBA_GROUP=dba
oracle.install.db.OSOPER_GROUP=oper
oracle.install.db.OSBACKUPDBA_GROUP=dba
oracle.install.db.OSDGDBA_GROUP=dba
oracle.install.db.OSKMDBA_GROUP=dba
SECURITY_UPDATES_VIA_MYORACLESUPPORT=false
DECLINE_SECURITY_UPDATES=true
EOF
    else
        # 26ai响应文件
        cat > "$response_dir/db_install.rsp" << EOF
oracle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v23_0_0
oracle.install.option=INSTALL_DB_SWONLY
ORACLE_HOSTNAME=myoracle
UNIX_GROUP_NAME=oinstall
INVENTORY_LOCATION=/u01/app/oraInventory
SELECTED_LANGUAGES=en
ORACLE_HOME=$ORACLE_HOME
ORACLE_BASE=$ORACLE_BASE
oracle.install.db.InstallEdition=EE
oracle.install.db.OSDBA_GROUP=dba
oracle.install.db.OSOPER_GROUP=oper
oracle.install.db.OSBACKUPDBA_GROUP=dba
oracle.install.db.OSDGDBA_GROUP=dba
oracle.install.db.OSKMDBA_GROUP=dba
oracle.install.db.OSRACDBA_GROUP=dba
SECURITY_UPDATES_VIA_MYORACLESUPPORT=false
DECLINE_SECURITY_UPDATES=true
EOF
    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=1
LISTENER_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" << EOF
responseFileVersion=/oracle/assistants/rspfmt_dbca_response_schema_v23.0.0
gdbName=orcl
sid=orcl
databaseConfigType=SI
createAsContainerDatabase=true
numberOfPDBs=1
pdbName=pdb1
templateName=General_Purpose.dbc
oracleHomeUserPassword=${ORACLE_PASSWORD}
sysPassword=${ORACLE_PASSWORD}
systemPassword=${ORACLE_PASSWORD}
pdbAdminPassword=${ORACLE_PASSWORD}
datafileDestination=/u01/app/oracle/oradata
characterSet=AL32UTF8
nationalCharacterSet=UTF8
databaseType=OLTP
automaticMemoryManagement=true
totalMemory=2048
redoLogFileSize=100
EOF
    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/oradata
RECOVERYAREADESTINATION= $ORACLE_BASE/fast_recovery_area
CHARACTERSET = "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_BASE
export ORACLE_HOME=$ORACLE_HOME
export PATH=\$ORACLE_HOME/bin:\$PATH

cd $ORACLE_HOME

echo "=========================================="
echo "Oracle $ORACLE_VERSION 静默安装开始"
echo "时间: \$(date)"
echo "ORACLE_HOME: \$ORACLE_HOME"
echo "=========================================="

# 执行安装命令
./runInstaller -silent -responseFile $response_file -ignorePrereqFailure -waitforcompletion

echo "安装程序已启动,请等待完成..."
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_HOME
export PATH=\$ORACLE_HOME/bin:\$PATH

echo "配置Oracle监听器..."
netca -silent -responseFile /home/oracle/response/netca.rsp

sleep 5

echo "启动监听器..."
lsnrctl start

echo "监听器状态:"
lsnrctl status | grep -E "(Status|Start|PORT)" | head -5
EOF
    
    # 检查监听器状态
    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_HOME
export ORACLE_SID=orcl
export PATH=\$ORACLE_HOME/bin:\$PATH

echo "=========================================="
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 1
fi

# 根据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.rsp
else
    echo "使用传统格式的响应文件"
    # 对于其他版本,使用传统方式
    dbca -silent -responseFile /home/oracle/response/dbca.rsp
fi

echo "数据库创建命令执行完成,退出状态: \$?"
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_HOME
export ORACLE_SID=orcl
export PATH=$ORACLE_HOME/bin:$PATH

echo "检查数据库状态..."

# 等待数据库启动
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 5
done

echo ""
echo "=== 数据库状态信息 ==="
sqlplus -s / as sysdba << SQL
set pagesize 100 linesize 120
col "Database Info" format a60
select '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 pdbs
whenever sqlerror continue
alter 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_HOME
export ORACLE_SID=orcl
export PATH=$ORACLE_HOME/bin:$PATH

echo "使用手动内存管理创建数据库..."

# 使用命令行参数创建数据库,禁用自动内存管理
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 NONE

echo "手动内存管理数据库创建完成,退出状态: $?"
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_HOME
export ORACLE_SID=orcl
export PATH=$ORACLE_HOME/bin:$PATH

echo "检查数据库连接..."
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 5
done

echo ""
echo "=== 数据库当前状态 ==="
sqlplus -s / as sysdba << SQL
set pagesize 100 linesize 120
col "Database Info" format a60
select '实例状态: ' || 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 pdbs
whenever sqlerror continue
alter session set container=cdb\$root;
ALTER PLUGGABLE DATABASE PDB1 OPEN;
show pdbs;
exit;
SQL
EOF
    
    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_HOME
export ORACLE_SID=orcl
export PATH=$ORACLE_HOME/bin:$PATH

echo "检查数据库状态..."
sqlplus / as sysdba << SQL
startup
select name, open_mode, cdb from v\$database;
select instance_name, status from v\$instance;
-- 核心修改:执行指定的打开PDB1+show pdbs
whenever sqlerror continue
alter session set container=cdb\$root;
ALTER PLUGGABLE DATABASE PDB1 OPEN;
show pdbs;
exit;
SQL
EOF
    
    # 验证手动启动结果
    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 script
ORACLE_OWNER=oracle
ORACLE_HOME=$ORACLE_HOME

case "\$1" in
start)
    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 1
esac
exit 0
EOF
    
    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 Service
After=network.target

[Service]
Type=forking
Environment=ORACLE_HOME=$ORACLE_HOME
Environment=ORACLE_SID=orcl
ExecStart=/etc/init.d/oracle start
ExecStop=/etc/init.d/oracle stop
User=oracle
Group=oinstall

[Install]
WantedBy=multi-user.target
SYSTEMD
        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 sysdba

2. 连接到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"
}

# 主函数:控制安装流程(核心修改:用run_step调用所有步骤,实现数字序号+极简输出)
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函数分离(终端极简,日志详细)
main

exit 0

操作系统及数据库软件下载地址:

bash 复制代码
操作系统下载地址:https://yum.oracle.com/oracle-linux-isos.html 
bash 复制代码
 26ai下载 :https://www.oracle.com/database/technologies/oracle26ai-linux-downloads.html

脚本默认的安装包路径在/sott下面

相关推荐
野生绿箭侠4 小时前
Ncos 2.3.2 版本集成达梦数据库
数据库
仍然.4 小时前
MYSQL--约束
数据库·mysql
乡野码圣5 小时前
【RK3588 Android12】RCU机制
java·jvm·数据库
亓才孓5 小时前
[数据库]应该注意的细节
数据库·sql
m0_561359676 小时前
掌握Python魔法方法(Magic Methods)
jvm·数据库·python
xxxmine6 小时前
redis学习
数据库·redis·学习
qq_5470261796 小时前
Redis 常见问题
数据库·redis·mybatis
APIshop6 小时前
Java 实战:调用 item_search_tmall 按关键词搜索天猫商品
java·开发语言·数据库
小陈phd7 小时前
混合知识库搭建:本地Docker部署Neo4j图数据库与Milvus向量库
数据库·docker·neo4j