Sunday, April 20, 2025

dg_switchover/ ├── dg_switchover.sh # Main script ├── dg_config.cfg # Configuration variables └── dg_functions.sh # Core functions #!/bin/bash # Oracle Environment export ORACLE_HOME=/u01/app/oracle/product/19c/dbhome_1 export PATH=$ORACLE_HOME/bin:$PATH # Database Credentials export SYS_PASSWORD="your_sys_password" export PRIMARY_DB="primary_db" export STANDBY_DB="standby_db" export DG_BROKER_CONFIG="MyDGConfig" # Alerting export ALERT_EMAIL="admin@example.com" export LOG_DIR="/var/log/dg_operations" 2. dg_functions.sh (Function Library) #!/bin/bash # Load configuration source $(dirname "$0")/dg_config.cfg # Initialize logging init_logging() { local OPERATION=$1 LOG_FILE="${LOG_DIR}/dg_${OPERATION}_$(date +%Y%m%d%H%M%S).log" exec > >(tee -a "$LOG_FILE") 2>&1 } # Check DG configuration status check_dg_config() { dgmgrl -silent "sys/${SYS_PASSWORD}@${PRIMARY_DB}" <> "${LOG_FILE}" case $SEVERITY in "CRITICAL") echo "${MESSAGE}" | mail -s "[URGENT] ${SUBJECT}" "$ALERT_EMAIL" ;; "WARNING") echo "${MESSAGE}" | mail -s "${SUBJECT}" "$ALERT_EMAIL" ;; *) logger -t DG_OPERATION "${MESSAGE}" ;; esac } archive_logs() { local RETENTION_DAYS=30 find "${LOG_DIR}" -name "dg_*.log" -mtime +${RETENTION_DAYS} -delete } Enhanced dg_functions.sh #!/bin/bash # Password management get_db_password() { if [ "$ENCRYPT_PASSWORD" = true ]; then openssl enc -aes-256-cbc -d -in "${VAULT_FILE}" -pass pass:${SYS_USER} else echo "${SYS_PASSWORD}" fi } # Enhanced logging log() { local LEVEL=$1 local MSG=$2 local COLOR="\e[0m" case $LEVEL in "INFO") COLOR="\e[34m" ;; "SUCCESS") COLOR="\e[32m" ;; "WARNING") COLOR="\e[33m" ;; "ERROR") COLOR="\e[31m" ;; esac echo -e "$(date '+%Y-%m-%d %H:%M:%S') ${COLOR}[${LEVEL}]\e[0m ${MSG}" echo "$(date '+%Y-%m-%d %H:%M:%S') [${LEVEL}] ${MSG}" >> "${LOG_FILE}" } # Transactional rollback rollback_switchover() { log "INFO" "Attempting rollback..." # Implementation-specific rollback logic } 5. Enhanced dg_switchover.sh #!/bin/bash # Main script with enhanced features source "$(dirname "$0")/dg_config.cfg" source "$(dirname "$0")/dg_functions.sh" source "$(dirname "$0")/prechecks.sh" source "$(dirname "$0")/alert_handler.sh" trap "rollback_switchover; send_alert CRITICAL 'Operation Aborted' 'Script terminated unexpectedly'; exit 1" INT TERM main() { local OPERATION=$1 local TARGET_DB=$2 # Initialize environment export TNS_ADMIN="${ORACLE_HOME}/network/admin" init_logging "${OPERATION}" archive_logs # Pre-flight checks if ! verify_connectivity "${PRIMARY_DB}"; then log "ERROR" "Cannot connect to primary database" send_alert CRITICAL "Connectivity Failure" "Primary DB unreachable" exit 1 fi local LAG=$(check_apply_lag | tr -d '\n') if [ "${LAG}" -gt 300 ]; then # 5 minutes lag threshold log "WARNING" "High apply lag detected: ${LAG} seconds" send_alert WARNING "High Lag" "Switchover with ${LAG} sec lag" fi case $OPERATION in "switchover") timeout ${DG_TIMEOUT} perform_switchover "${TARGET_DB}" || { log "ERROR" "Switchover timed out" send_alert CRITICAL "Timeout" "Switchover exceeded ${DG_TIMEOUT}s" exit 1 } ;; "switchback") timeout ${DG_TIMEOUT} perform_switchback || { log "ERROR" "Switchback timed out" send_alert CRITICAL "Timeout" "Switchback exceeded ${DG_TIMEOUT}s" exit 1 } ;; esac # Post-operation verification if ! check_dg_health "${PRIMARY_DB}"; then log "ERROR" "Post-operation health check failed" send_alert CRITICAL "Health Check Failed" "Configuration unstable" exit 1 fi } # Parse arguments with validation if [[ $# -lt 1 ]]; then echo "Usage: $0 [switchover|switchback] [target_db]" exit 1 fi main "$@" # Encrypt credentials first echo "my_password" | openssl enc -aes-256-cbc -out ~/.dg_vault -pass pass:oracle_user # Switchover with enhanced checks ./dg_switchover.sh switchover standby_db --validate-lag 60 # Force switchover (override checks) ./dg_switchover.sh switchover standby_db --force # Dry-run mode ./dg_switchover.sh switchover standby_db --dry-run