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