Saturday, February 1, 2025

#!/bin/bash # Configuration ORACLE_USER="remote_user" ORACLE_PASS="password" RAC_NODE="rac_node1" EMAIL_RECIPIENT="admin@example.com" REPORT_FILE="/tmp/oracle_health_report.html" # Create HTML Report Header cat << EOF > $REPORT_FILE Oracle RAC Health Check Report

Oracle RAC Health Check Report

Generated on: $(date)

EOF # Run Database Checks sqlplus -s /nolog << EOF >> $REPORT_FILE connect $ORACLE_USER/$ORACLE_PASS@$RAC_NODE set markup html on pre off entmap off set pagesize 500 linesize 200 set feedback off heading on prompt

Recent ORA Errors (Last 5 Minutes)

SELECT INST_ID, TO_CHAR(ORIGINATING_TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP, MESSAGE_TEXT FROM GV\$DIAG_ALERT_EXT WHERE MESSAGE_TEXT LIKE 'ORA-%' AND ORIGINATING_TIMESTAMP >= SYSDATE - 5/1440 ORDER BY ORIGINATING_TIMESTAMP DESC; prompt

Top Waiting Events (Last 5 Minutes)

SELECT INST_ID, EVENT, COUNT(*) AS WAIT_COUNT, ROUND(COUNT(*)*100/SUM(COUNT(*)) OVER(), 2) AS PCT FROM GV\$ACTIVE_SESSION_HISTORY WHERE SAMPLE_TIME >= SYSDATE - 5/1440 AND EVENT IS NOT NULL GROUP BY INST_ID, EVENT ORDER BY WAIT_COUNT DESC; exit EOF # Add HTML Footer cat << EOF >> $REPORT_FILE EOF # Send Email with HTML Report mailx -s "$(echo -e "Oracle RAC Health Check Report\nContent-Type: text/html")" \ $EMAIL_RECIPIENT < $REPORT_FILE # Cleanup rm -f $REPORT_FILE #### #!/bin/bash set -eo pipefail trap 'echo "Error at line $LINENO"; exit 1' ERR # Configuration REMOTE_USER="oracleuser" REMOTE_HOSTS=("rac-node1" "rac-node2") # Multiple RAC nodes ORACLE_SID="ORCLCDB" ORACLE_HOME="/u01/app/oracle/product/19.0.0/dbhome_1" EMAIL_RECIPIENT="dba@example.com" EMAIL_SUBJECT="Oracle RAC Health Check Report - $(date +%Y%m%d)" REPORT_FILE="/tmp/rac_health_report.html" LOG_FILE="/tmp/rac_health_check.log" AWK_SCRIPT="/tmp/rac_stats.awk" declare -A THRESHOLDS=( [TABLESPACE]=90 [WAIT_TIME]=1000 [CPU_PER_SESSION]=75 [ASM_FREE]=10 ) # Initialize files : > "$REPORT_FILE" : > "$LOG_FILE" # Create HTML template cat >> "$REPORT_FILE" << EOF Oracle RAC Health Check Report

Oracle RAC Health Check Report

Generated on: $(date "+%Y-%m-%d %H:%M:%S")

EOF # Function to run remote SQL run_remote_sql() { local host=$1 local sql=$2 ssh -q "$REMOTE_USER@$host" " export ORACLE_SID=$ORACLE_SID export ORACLE_HOME=$ORACLE_HOME \$ORACLE_HOME/bin/sqlplus -S / as sysdba << SQLEND SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF $sql SQLEND" } # Cluster Health Check echo "

► Cluster Health

" >> "$REPORT_FILE" echo "" >> "$REPORT_FILE" # AWR/ASH Report Generation echo "

► AWR/ASH Reports

" >> "$REPORT_FILE" echo "" >> "$REPORT_FILE" # Historical Trend Analysis echo "

► Historical Trends

" >> "$REPORT_FILE" echo "" >> "$REPORT_FILE" # Backup Status Check echo "

► Backup Status

" >> "$REPORT_FILE" echo "" >> "$REPORT_FILE" # JavaScript for collapsible sections cat >> "$REPORT_FILE" << EOF EOF # Send email with mailx ( echo "From: Oracle Health Check " echo "To: $EMAIL_RECIPIENT" echo "Subject: $EMAIL_SUBJECT" echo "MIME-Version: 1.0" echo "Content-Type: text/html" echo cat "$REPORT_FILE" ) | mailx -s "$EMAIL_SUBJECT" -a "$REPORT_FILE" "$EMAIL_RECIPIENT" # Cleanup rm -f "$REPORT_FILE" "$LOG_FILE" #!/bin/bash # Configuration (Modify these parameters) DB_USER="your_db_user" DB_PASS="your_db_password" DB_HOST="your_db_host" DB_SERVICE="your_db_service" EMAIL_TO="your_email@example.com" EMAIL_SUBJECT="Oracle RAC Health Check Report" HTML_REPORT="/tmp/oracle_rac_health_check.html" # Start HTML Output echo "Oracle RAC Health Check" > $HTML_REPORT echo "

Oracle RAC Database Health Check Report

" >> $HTML_REPORT echo "
" >> $HTML_REPORT # Function to run SQL and format output as HTML run_sql() { local title=$1 local sql_query=$2 echo "

$title

" >> $HTML_REPORT echo "
" >> $HTML_REPORT

    sqlplus -s "$DB_USER/$DB_PASS@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=$DB_HOST)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=$DB_SERVICE)))" <> $HTML_REPORT
SET LINESIZE 200
SET PAGESIZE 100
SET TRIMSPOOL ON
SET HEADING OFF
$sql_query
EXIT;
EOF
    echo "

" >> $HTML_REPORT } # 1) All Instance / DB Status run_sql "RAC Instance and Database Status" "SELECT inst_id, instance_name, status, database_status FROM GV\$INSTANCE;" # 2) Long Running Sessions (active > 1 hour) run_sql "Long Running Sessions (per instance)" " SELECT inst_id, sid, serial#, username, status, sql_id, last_call_et FROM GV\$SESSION WHERE status='ACTIVE' AND last_call_et > 3600 ORDER BY last_call_et DESC;" # 3) DB Blocking run_sql "Blocking Sessions Across Instances" " SELECT inst_id, blocking_session, sid, serial#, wait_class, seconds_in_wait FROM GV\$SESSION WHERE blocking_session IS NOT NULL;" # 4) DB Locking run_sql "Database Locks" " SELECT inst_id, sid, type, id1, id2, lmode, request, block FROM GV\$LOCK WHERE block != 0;" # 5) DB Load Last 1 Hour run_sql "Database Load Last 1 Hour" " SELECT inst_id, TO_CHAR(begin_time, 'YYYY-MM-DD HH24:MI:SS'), average_active_sessions FROM GV\$SYSMETRIC_HISTORY WHERE metric_name = 'Average Active Sessions' AND group_id = 2 ORDER BY begin_time DESC FETCH FIRST 12 ROWS ONLY;" # 6) DB Load Last 5 Minutes run_sql "Database Load Last 5 Minutes" " SELECT inst_id, TO_CHAR(begin_time, 'YYYY-MM-DD HH24:MI:SS'), average_active_sessions FROM GV\$SYSMETRIC_HISTORY WHERE metric_name = 'Average Active Sessions' AND group_id = 2 ORDER BY begin_time DESC FETCH FIRST 1 ROW ONLY;" # 7) DB Parallel Processing run_sql "Parallel Execution Processes" " SELECT inst_id, degree, req_degree, dop, requested_dop FROM GV\$PX_PROCESS;" # 8) Invalid Objects run_sql "Invalid Objects Across All Nodes" " SELECT inst_id, owner, object_name, object_type FROM GV\$DBA_OBJECTS WHERE status <> 'VALID';" # 9) Session Failures run_sql "Failed User Sessions" " SELECT inst_id, username, machine, terminal, logon_time FROM GV\$AUDIT_SESSION WHERE returncode != 0;" # 10) Active Session Count run_sql "Active Sessions Count per Instance" " SELECT inst_id, COUNT(*) AS active_sessions FROM GV\$SESSION WHERE status = 'ACTIVE' GROUP BY inst_id;" # 11) Database Service Info run_sql "Database Services Across All Instances" " SELECT inst_id, name, pdb FROM GV\$ACTIVE_SERVICES;" # 12) ORA-ERRORs in Alert Logs (Last 24 Hours) run_sql "Recent ORA-Errors in Alert Logs" " SELECT inst_id, originating_timestamp, message_text FROM GV\$DIAG_ALERT_EXT WHERE message_text LIKE 'ORA-%' AND originating_timestamp > SYSDATE - 1 ORDER BY originating_timestamp DESC;" # Close HTML Output echo "" >> $HTML_REPORT # Send Email with the HTML report mailx -a "$HTML_REPORT" -s "$EMAIL_SUBJECT" "$EMAIL_TO" < $HTML_REPORT echo "RAC Health Check Report Sent to $EMAIL_TO" ### #!/bin/bash set -eo pipefail # Configuration DB_USER="sys as sysdba" DB_PASSWORD="your_password" DB_HOST="rac-scan.example.com" DB_PORT=1521 SERVICE_NAME="ORCLCDB" EMAIL_TO="dba@example.com" REPORT_FILE="/tmp/rac_health_report.html" # Oracle Connection String CONN_STR="${DB_USER}/${DB_PASSWORD}@//${DB_HOST}:${DB_PORT}/${SERVICE_NAME}" # HTML Header cat > $REPORT_FILE < Oracle RAC Health Report

Oracle RAC Health & Performance Report

Generated: $(date "+%Y-%m-%d %H:%M:%S")

EOF # Function to run SQL and format output run_sql() { local sql=$1 local title=$2 local critical=$3 echo "

$title

" >> $REPORT_FILE output=$(sqlplus -S -L "${CONN_STR}" <No issues found

" >> $REPORT_FILE else echo "" >> $REPORT_FILE while IFS= read -r line; do echo "" >> $REPORT_FILE done <<< "$output" echo "
$line
" >> $REPORT_FILE fi } # 1. Instance/DB Status run_sql " SELECT 'Instance ' || instance_name || ' - ' || status || ' | Version: ' || version || ' | Uptime: ' || ROUND((SYSDATE - startup_time)*24) || ' hours' FROM gv\$instance;" "Cluster Instance Status" # 2. Long Running Sessions (>30 minutes) run_sql " SELECT 'SID: ' || sid || ', Inst: ' || inst_id || ', User: ' || username || ', SQL_ID: ' || sql_id || ', Elapsed: ' || ROUND((SYSDATE - logon_time)*1440) || ' mins' FROM gv\$session WHERE status = 'ACTIVE' AND (SYSDATE - logon_time)*1440 > 30;" "Long Running Sessions" "warning" # 3. DB Blocking/Locking run_sql " SELECT 'Blocker: ' || b.inst_id || ':' || b.sid || ' | Waiter: ' || w.inst_id || ':' || w.sid || ' | Object: ' || o.object_name || ' | Wait: ' || ROUND((SYSDATE - w.logon_time)*1440) || ' mins' FROM gv\$lock b, gv\$lock w, dba_objects o WHERE b.block = 1 AND w.request > 0 AND b.id1 = w.id1 AND b.id2 = w.id2 AND o.object_id = b.id1;" "Blocking Sessions" "critical" # 4. DB Load Analysis run_sql " SELECT 'Last Hour: CPU ' || ROUND(AVG(cpu_percent)) || '%' || ' | Active: ' || AVG(active_sessions) || ' | Parallel: ' || AVG(parallel_servers) || ' | Last 5m: ' || ROUND(5min_cpu) || '%' FROM ( SELECT h.metric_value cpu_percent, (SELECT COUNT(*) FROM gv\$session WHERE status = 'ACTIVE') active_sessions, (SELECT SUM(servers_in_use) FROM gv\$px_process_sysstat) parallel_servers, LEAD(h.metric_value, 12) OVER (ORDER BY h.begin_time) 5min_cpu FROM gv\$sysmetric_history h WHERE h.metric_name = 'CPU Usage Per Sec' AND h.begin_time > SYSDATE - 1/24 );" "Load Analysis" # 5. Parallel Processes run_sql " SELECT 'Inst ' || inst_id || ' | Used: ' || servers_in_use || ' | Available: ' || servers_available || ' | Status: ' || status FROM gv\$px_process_sysstat;" "Parallel Execution Status" # 6. Invalid Objects run_sql " SELECT owner || '.' || object_name || ' (' || object_type || ')' FROM dba_objects WHERE status != 'VALID' AND owner NOT IN ('SYS','SYSTEM');" "Invalid Objects" "warning" # 7. Session Failures run_sql " SELECT 'Inst ' || inst_id || ' | User: ' || username || ' | Count: ' || COUNT(*) || ' | Last: ' || MAX(timestamp) FROM gv\$session WHERE status = 'FAILED' GROUP BY inst_id, username;" "Session Failures" "critical" # 8. Active Session Count run_sql " SELECT 'Inst ' || inst_id || ' | Active: ' || COUNT(*) || ' | CPU: ' || SUM(CASE WHEN state = 'ON CPU' THEN 1 ELSE 0 END) FROM gv\$session WHERE status = 'ACTIVE' GROUP BY inst_id;" "Active Sessions" # 9. Database Services run_sql " SELECT name || ' | ' || status || ' | Node: ' || node || ' | Created: ' || TO_CHAR(creation_date, 'YYYY-MM-DD HH24:MI') FROM gv\$services;" "Database Services" # 10. ORA-Errors run_sql " SELECT 'Inst ' || inst_id || ' | ' || TO_CHAR(timestamp, 'YYYY-MM-DD HH24:MI') || ' | ' || REGEXP_SUBSTR(message_text, 'ORA-[0-9]+:.*') FROM gv\$diag_alert_ext WHERE message_type = 'ERROR' AND timestamp > SYSDATE - 1;" "Recent ORA Errors" "critical" # Complete HTML cat >> $REPORT_FILE < EOF # Send Email ( echo "From: Oracle Monitor " echo "To: $EMAIL_TO" echo "Subject: Oracle RAC Health Report" echo "MIME-Version: 1.0" echo "Content-Type: text/html" echo cat $REPORT_FILE ) | sendmail -t # Cleanup rm -f $REPORT_FILE