分享一个Oracle 数据库信息收集脚本

LINUX:

复制代码
#!/bin/sh
##############################################################################
# 脚本名称:oracle_db_info_collector.sh
# 脚本版本:V3.0
# 功能描述:Oracle数据库信息收集工具,支持10g+版本,生成HTML格式巡检报告
##############################################################################

set -euo pipefail

# 定义全局变量
SCRIPT_NAME=$(basename "$0")
TEMP_DIR=$(mktemp -d /tmp/oracle_collect_XXXXXX)  # 临时目录
REPORT_SUFFIX="xifenfei_db_recover"
HTML_STYLE="
<style>
  body {font-family: Arial, sans-serif; margin: 20px; line-height: 1.6;}
  h1, h2, h3 {color: #2c3e50; border-bottom: 1px solid #ecf0f1; padding-bottom: 5px;}
  .section {margin: 20px 0; padding: 15px; background: #f8f9fa; border-radius: 5px;}
  .code-block {background: #2c3e50; color: #ecf0f1; padding: 10px; border-radius: 3px; overflow-x: auto;}
</style>
"

# 清理临时目录(脚本退出时执行)
trap 'rm -rf "$TEMP_DIR" && echo "临时目录已清理:$TEMP_DIR"' EXIT

##############################################################################
# 函数名:sql_exec
# 功能:执行SQL语句并返回结果(去除SQL>提示符和空行)
# 参数:$1 - 待执行的SQL语句
##############################################################################
sql_exec() {
  local sql_stmt="$1"
  "$SQLPLUS" "/ as sysdba" <<EOF
set termout off echo off feedback off verify off wrap on trimspool on serveroutput on escape on
set pages 0 lines 200
$sql_stmt
exit;
EOF
  # 过滤无效输出
  grep -vE "SQL>|^$|^-" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
}

##############################################################################
# 第一步:环境预检查
##############################################################################
echo "===== 开始环境预检查 ====="

# 检查ORACLE_HOME
if [ -z "$ORACLE_HOME" ]; then
  echo "ERROR: ORACLE_HOME环境变量未配置!" >&2
  exit 1
fi

# 检查ORACLE_SID
if [ -z "$ORACLE_SID" ]; then
  echo "ERROR: ORACLE_SID环境变量未配置!" >&2
  exit 1
fi

# 检查实例是否运行(通过pmon进程)
PMON_PROCESSES=$(ps -ef | grep "ora_pmon_$ORACLE_SID" | grep -v grep)
if [ -z "$PMON_PROCESSES" ]; then
  echo "ERROR: 实例[$ORACLE_SID]未运行,请先启动实例!" >&2
  exit 1
fi

# 检查sqlplus可执行文件
SQLPLUS="$ORACLE_HOME/bin/sqlplus"
if [ ! -x "$SQLPLUS" ]; then
  echo "ERROR: 未找到可执行的sqlplus(路径:$SQLPLUS)!" >&2
  exit 1
fi

# 获取Oracle主版本号
ORACLE_VERSION=$(sqlplus -v | awk '{print $3}' | awk -F. '{print $1}')
echo "Oracle版本:$ORACLE_VERSION"

# 检查数据库状态(需处于MOUNT/OPEN状态)
DB_STATUS=$(sql_exec "select status from v\$instance;")
if [ "$DB_STATUS" = "STARTED" ]; then
  echo "ERROR: 数据库处于STARTED状态,请先挂载(mount)数据库!" >&2
  exit 1
fi
echo "数据库状态:$DB_STATUS"
echo "===== 环境预检查通过 ====="

##############################################################################
# 第二步:生成报告文件名
##############################################################################
DB_NAME=$(sql_exec "select lower(name) from v\$database;")
REPORT_DATE=$(date +%Y%m%d)
REPORT_FILE="${REPORT_SUFFIX}_${DB_NAME}_${REPORT_DATE}.html"
echo "报告文件:$(pwd)/$REPORT_FILE"

# 初始化HTML报告
cat > "$REPORT_FILE" <<EOF
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>Oracle数据库信息收集报告 - $DB_NAME($REPORT_DATE)</title>
  $HTML_STYLE
</head>
<body>
  <h1>Oracle数据库信息收集报告</h1>
  <p>数据库名称:$DB_NAME</p>
  <p>实例名称:$ORACLE_SID</p>
  <p>Oracle版本:$ORACLE_VERSION</p>
  <p>收集时间:$(date +"%Y-%m-%d %H:%M:%S")</p>
  
  <div class="section">
    <h2>一、数据库基础信息</h2>
    <div class="code-block">
EOF

##############################################################################
# 第三步:收集数据库核心信息(按版本执行对应SQL脚本)
##############################################################################
echo "===== 开始收集数据库基础信息 ====="
if [ "$ORACLE_VERSION" -gt 11 ]; then
  SQL_SCRIPT="check_recover_db_12c.sql"
else
  SQL_SCRIPT="check_recover_db.sql"
fi

if [ -f "$SQL_SCRIPT" ]; then
  "$SQLPLUS" "/ as sysdba" @("$SQL_SCRIPT") >> "$REPORT_FILE" 2>&1
else
  echo "警告:未找到SQL脚本$SQL_SCRIPT,跳过基础信息收集!" >&2
  echo "<!-- 未找到SQL脚本$SQL_SCRIPT,基础信息收集跳过 -->" >> "$REPORT_FILE"
fi
echo "===== 数据库基础信息收集完成 ====="

# 关闭基础信息代码块
echo "    </div>
  </div>" >> "$REPORT_FILE"

##############################################################################
# 第四步:收集补丁信息(OPatch)
##############################################################################
echo "===== 开始收集补丁信息 ====="
OPATCH="$ORACLE_HOME/OPatch/opatch"
cat >> "$REPORT_FILE" <<EOF
  <div class="section">
    <h2>二、补丁信息</h2>
    <div class="code-block">
EOF

if [ -x "$OPATCH" ]; then
  "$OPATCH" lsinventory >> "$REPORT_FILE" 2>&1
else
  echo "警告:未找到OPatch工具(路径:$OPATCH),跳过补丁收集!" >&2
  echo "<!-- 未找到OPatch工具,补丁信息收集跳过 -->" >> "$REPORT_FILE"
fi

echo "    </div>
  </div>" >> "$REPORT_FILE"
echo "===== 补丁信息收集完成 ====="

##############################################################################
# 第五步:收集告警日志(兼容10g/11g/12c+)
##############################################################################
echo "===== 开始收集告警日志 ====="
cat >> "$REPORT_FILE" <<EOF
  <div class="section">
    <h2>三、告警日志(最新1000行)</h2>
    <div class="code-block">
EOF

# 获取告警日志路径
if [ "$ORACLE_VERSION" -gt 10 ]; then
  # 11g+使用diagnostic_dest路径
  DIAGNOSTIC_DEST=$(sql_exec "select value from v\$parameter where name='diagnostic_dest';")
  DB_UNIQUE_NAME=$(sql_exec "select value from v\$parameter where name='db_unique_name';")
  ALERT_PATH="${DIAGNOSTIC_DEST}/diag/rdbms/${DB_UNIQUE_NAME}/${ORACLE_SID}/trace"
else
  # 10g使用background_dump_dest路径
  ALERT_PATH=$(sql_exec "select value from v\$parameter where name='background_dump_dest';")
fi

ALERT_LOG="${ALERT_PATH}/alert_${ORACLE_SID}.log"
echo "告警日志路径:$ALERT_LOG"

if [ -f "$ALERT_LOG" ]; then
  # 截取最新1000行并写入报告
  tail -1000 "$ALERT_LOG" >> "$REPORT_FILE" 2>&1
else
  echo "警告:未找到告警日志文件$ALERT_LOG,跳过告警日志收集!" >&2
  echo "<!-- 未找到告警日志文件$ALERT_LOG -->" >> "$REPORT_FILE"
fi

echo "    </div>
  </div>" >> "$REPORT_FILE"
echo "===== 告警日志收集完成 ====="

##############################################################################
# 第六步:dbv校验系统数据文件(移除硬编码密码)
##############################################################################
echo "===== 开始执行系统数据文件校验 ====="
cat >> "$REPORT_FILE" <<EOF
  <div class="section">
    <h2>四、系统数据文件DBV校验结果</h2>
    <div class="code-block">
EOF

# 生成dbv执行命令(使用操作系统认证,无需硬编码密码)
DBV_COMMANDS=$(sql_exec "select 'dbv userid=/ file='||name||' blocksize='||BLOCK_SIZE||' logfile=${TEMP_DIR}/dbv_'||file#||'.log' from v\$datafile where ts#=0;")

if [ -n "$DBV_COMMANDS" ]; then
  echo "$DBV_COMMANDS" > "${TEMP_DIR}/dbv_exec.sh"
  chmod +x "${TEMP_DIR}/dbv_exec.sh"
  # 执行dbv校验
  "${TEMP_DIR}/dbv_exec.sh" >> "$REPORT_FILE" 2>&1
  # 合并校验日志
  cat "${TEMP_DIR}/dbv_"*.log >> "$REPORT_FILE" 2>&1
else
  echo "警告:未查询到系统表空间数据文件,跳过DBV校验!" >&2
  echo "<!-- 未查询到系统表空间数据文件,DBV校验跳过 -->" >> "$REPORT_FILE"
fi

echo "    </div>
  </div>" >> "$REPORT_FILE"
echo "===== 系统数据文件校验完成 ====="

##############################################################################
# 第七步:收集磁盘空间信息
##############################################################################
echo "===== 开始收集磁盘空间信息 ====="
cat >> "$REPORT_FILE" <<EOF
  <div class="section">
    <h2>五、磁盘空间状态</h2>
    <div class="code-block">
EOF

# df命令使用人类可读格式
df -h >> "$REPORT_FILE" 2>&1

echo "    </div>
  </div>" >> "$REPORT_FILE"
echo "===== 磁盘空间信息收集完成 ====="

##############################################################################
# 第八步:完成报告生成
##############################################################################
cat >> "$REPORT_FILE" <<EOF
</body>
</html>
EOF

# 输出报告路径提示
echo "===== 信息收集完成 ====="
echo "********************************************************************************"
echo "请查阅报告文件:$(pwd)/$REPORT_FILE"
echo "********************************************************************************"

二、WINDOWS:

复制代码
@echo off
setlocal enabledelayedexpansion
cls

:: 颜色配置(标题蓝、成功绿、错误红、提示白)
set "COLOR_TITLE=0b"   :: 亮蓝色
set "COLOR_SUCCESS=0a" :: 绿色
set "COLOR_ERROR=0c"   :: 红色
set "COLOR_INFO=07"    :: 白色

:: 初始化变量
set "ORACLE_SID="
set "ORACLE_HOME="
set "SQLPLUS_PATH="
set "DB_VERSION="
set "SQL_SCRIPT="
set "REPORT_PATTERN=xifenfei*.html"

:: ==============================================
:: 第一步:脚本标题与环境说明
:: ==============================================
color %COLOR_TITLE%
echo.
echo =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
echo          🌟  Oracle Database Recovery Check (Windows版)  🌟
echo =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
echo 功能:自动校验环境、识别版本、执行恢复检查脚本、生成HTML报告
echo 支持版本:Oracle 10g/11g/12c/18c/19c/21c
echo 脚本依赖:check_recover_db.sql / check_recover_db_12c.sql(需与批处理同目录)
echo =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
echo.
color %COLOR_INFO%

:: ==============================================
:: 第二步:环境预检查(ORACLE_SID + ORACLE_HOME)
:: ==============================================
echo [🔍 环境预检查] 开始校验Oracle环境配置...
echo.

:: 检查ORACLE_SID是否已配置
if not defined ORACLE_SID (
    echo ⚠️  未检测到ORACLE_SID环境变量,尝试自动获取已启动的Oracle服务...
    :: 从已启动的Oracle服务中提取SID(服务名格式:OracleService<SID>)
    for /f "tokens=2 delims=OracleService" %%s in ('wmic service where "name like 'OracleService%' and state='Running'" get name /value ^| findstr "OracleService"') do (
        set "AUTO_SID=%%s"
    )
    if defined AUTO_SID (
        echo ✅ 自动获取到SID:!AUTO_SID!
        set "ORACLE_SID=!AUTO_SID!"
    ) else (
        color %COLOR_ERROR%
        echo ❌ 错误:未配置ORACLE_SID,且无运行中的Oracle服务!
        echo 请按以下步骤配置:
        echo 1. 计算机 → 管理 → 服务 → 找到OracleServiceXXXX(XXXX为你的SID)
        echo 2. 打开CMD,执行:set ORACLE_SID=XXXX
        echo 3. 执行:set ORACLE_HOME=你的Oracle安装目录(如D:\app\product\11.2.0\dbhome_1)
        echo 4. 执行:set PATH=!ORACLE_HOME!\bin;!PATH!
        echo 5. 重新运行本脚本
        echo.
        pause >nul
        exit /b 1
    )
) else (
    echo ✅ ORACLE_SID已配置:%ORACLE_SID%
)

:: 检查ORACLE_HOME是否已配置且有效
if not defined ORACLE_HOME (
    color %COLOR_ERROR%
    echo ❌ 错误:未配置ORACLE_HOME环境变量!
    echo 请执行:set ORACLE_HOME=你的Oracle安装目录(如D:\app\product\11.2.0\dbhome_1)
    echo.
    pause >nul
    exit /b 1
) else (
    :: 检查ORACLE_HOME下的sqlplus是否存在
    set "SQLPLUS_PATH=%ORACLE_HOME%\bin\sqlplus.exe"
    if not exist "!SQLPLUS_PATH!" (
        color %COLOR_ERROR%
        echo ❌ 错误:ORACLE_HOME路径无效(未找到sqlplus)!
        echo 当前ORACLE_HOME:%ORACLE_HOME%
        echo 请确认路径正确,且bin目录下存在sqlplus.exe
        echo.
        pause >nul
        exit /b 1
    )
    echo ✅ ORACLE_HOME已配置:%ORACLE_HOME%
)

:: 检查Oracle服务是否运行
echo.
echo [🔍 服务状态检查] 正在检查OracleService%ORACLE_SID%...
sc query "OracleService%ORACLE_SID%" | findstr "RUNNING" >nul 2>&1
if %errorlevel% equ 0 (
    echo ✅ OracleService%ORACLE_SID% 服务正在运行
) else (
    color %COLOR_ERROR%
    echo ❌ 错误:OracleService%ORACLE_SID% 服务未启动!
    echo 请按以下步骤操作:
    echo 1. 计算机 → 管理 → 服务 → 找到OracleService%ORACLE_SID%
    echo 2. 右键选择"启动",等待服务启动完成
    echo 3. 重新运行本脚本
    echo.
    pause >nul
    exit /b 1
)
color %COLOR_INFO%
echo.

:: ==============================================
:: 第三步:自动识别数据库版本
:: ==============================================
echo [🔍 版本识别] 正在获取数据库版本...
for /f "tokens=3 delims= " %%v in ('sqlplus -v ^| findstr "Version"') do (
    set "FULL_VERSION=%%v"
)
:: 提取主版本号(如11.2.0.4 → 11,12.1.0.2 → 12)
for /f "tokens=1 delims=." %%v in ("!FULL_VERSION!") do (
    set "DB_VERSION=%%v"
)
if not defined DB_VERSION (
    color %COLOR_ERROR%
    echo ❌ 错误:无法识别数据库版本!
    echo 请确认sqlplus已加入PATH,或手动执行 sqlplus -v 检查
    echo.
    pause >nul
    exit /b 1
)
echo ✅ 数据库版本:!FULL_VERSION!(主版本:!DB_VERSION!)
echo.

:: ==============================================
:: 第四步:自动选择对应的SQL脚本
:: ==============================================
echo [📝 脚本选择] 正在匹配对应脚本...
if !DB_VERSION! geq 12 (
    set "SQL_SCRIPT=check_recover_db_12c.sql"
) else (
    set "SQL_SCRIPT=check_recover_db.sql"
)
:: 检查脚本是否存在
if not exist "!SQL_SCRIPT!" (
    color %COLOR_ERROR%
    echo ❌ 错误:未找到脚本文件!
    echo 所需脚本:!SQL_SCRIPT!(需与本批处理同目录)
    echo 请确认脚本文件存在后重新运行
    echo.
    pause >nul
    exit /b 1
)
echo ✅ 自动选择脚本:!SQL_SCRIPT!
echo.

:: ==============================================
:: 第五步:执行SQL脚本(sysdba身份)
:: ==============================================
color %COLOR_TITLE%
echo [🚀 执行检查] 正在通过sqlplus执行恢复检查脚本...
echo 执行命令:sqlplus "/ as sysdba" @!SQL_SCRIPT!
echo =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
color %COLOR_INFO%
echo.

:: 执行SQL脚本,捕获返回码
sqlplus "/ as sysdba" @!SQL_SCRIPT!
if %errorlevel% equ 0 (
    color %COLOR_SUCCESS%
    echo.
    echo ✅ 脚本执行成功!正在查找生成的HTML报告...
    echo.
) else (
    color %COLOR_ERROR%
    echo.
    echo ❌ 错误:sqlplus执行脚本失败!
    echo 可能原因:
    echo 1. 数据库实例未正常启动(处于STARTED状态需挂载)
    echo 2.  sysdba权限认证失败
    echo 3. SQL脚本存在语法错误
    echo.
    pause >nul
    exit /b 1
)

:: ==============================================
:: 第六步:展示报告文件(优化原dir命令)
:: ==============================================
color %COLOR_INFO%
echo [📄 报告列表] 生成的恢复检查报告如下(完整路径):
echo =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
set "REPORT_FOUND=0"
:: 遍历当前目录下的报告文件,显示完整路径
for /f "delims=" %%f in ('dir /b /s "%cd%\%REPORT_PATTERN%" 2^>nul') do (
    echo ✅ %%f
    set "REPORT_FOUND=1"
)
if !REPORT_FOUND! equ 0 (
    color %COLOR_ERROR%
    echo ❌ 未找到生成的HTML报告!
    echo 可能原因:SQL脚本未生成报告,或报告文件名不匹配%REPORT_PATTERN%
    echo.
) else (
    color %COLOR_SUCCESS%
    echo.
    echo ✅ 报告查找完成!请复制上方路径直接打开查看
    echo.
)

:: ==============================================
:: 第七步:脚本结束
:: ==============================================
color %COLOR_TITLE%
echo =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
echo 🎉 Oracle数据库恢复检查执行完成!
color %COLOR_INFO%
echo 提示:若需重新执行,可直接运行本批处理(无需重复配置环境)
echo.
pause >nul
endlocal