#!/bin/bash
# Trigger Data Guard failover
source /u01/app/oracle/env.prod
dgmgrl sys/Password123@primary_db <
/tmp/backup.log 2>&1
####
#!/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
}
###################
#!/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 "$@"
###############################
main() {
# ... existing code ...
case $OPERATION in
"switchover")
init_logging "switchover"
local RESTORE_POINT=$(create_restore_point "${PRIMARY_DB}")
if [ $? -ne 0 ]; then
send_alert "CRITICAL" "Restore Point Creation Failed" "Could not create pre-switchover restore point"
exit 1
fi
# Perform switchover
if perform_switchover "$TARGET_DB"; then
purge_old_restore_points "${TARGET_DB}"
create_restore_point "${TARGET_DB}"
fi
;;
"switchback")
init_logging "switchback"
drop_all_restore_points "${STANDBY_DB}"
# ... rest of switchback logic ...
;;
esac
# ... existing code ...
}
##
# Add to prechecks.sh
verify_mrp_status() {
local DB=$1
local STATUS=$(sqlplus -s /nolog < /dev/null 2>&1; then
{
echo "To: $EMAIL_RECIPIENT"
echo "Subject: $EMAIL_SUBJECT - $host_entry"
echo "Content-Type: text/html"
echo
cat "$report_file"
} | sendmail -t
log_msg "Email sent as inline HTML using sendmail for $host_entry"
elif command -v mailx > /dev/null 2>&1; then
mailx -a "Content-Type: text/html" -s "$EMAIL_SUBJECT - $host_entry" "$EMAIL_RECIPIENT" < "$report_file"
log_msg "Email sent as inline HTML using mailx for $host_entry"
else
log_msg "ERROR: Neither sendmail nor mailx available for sending inline HTML email."
fi
else
# Compress report and attach
local zip_file="${report_file%.html}.zip"
zip -j "$zip_file" "$report_file" > /dev/null
if command -v sendmail > /dev/null 2>&1; then
{
echo "To: $EMAIL_RECIPIENT"
echo "Subject: $EMAIL_SUBJECT - $host_entry (Attached)"
echo "MIME-Version: 1.0"
echo "Content-Type: multipart/mixed; boundary="MIXED-BOUNDARY""
echo
echo "--MIXED-BOUNDARY"
echo "Content-Type: text/plain"
echo
echo "Health check report for $host_entry is attached (compressed)."
echo
echo "--MIXED-BOUNDARY"
echo "Content-Type: application/zip; name="$(basename "$zip_file")""
echo "Content-Disposition: attachment; filename="$(basename "$zip_file")""
echo "Content-Transfer-Encoding: base64"
echo
base64 "$zip_file"
echo "--MIXED-BOUNDARY--"
} | sendmail -t
log_msg "Email with ZIP attachment sent using sendmail for $host_entry"
elif command -v mailx > /dev/null 2>&1; then
echo "Health check report for $host_entry is attached (compressed)." | mailx -a "$zip_file" -s "$EMAIL_SUBJECT - $host_entry (Attached)" "$EMAIL_RECIPIENT"
log_msg "Email with ZIP attachment sent using mailx for $host_entry"
else
log_msg "ERROR: Neither sendmail nor mailx available for sending ZIP attachment."
fi
fi
}
send_email() {
local host_entry="$1"
local report_file="$2"
local max_inline_size=2097152 # 2MB in bytes
local file_size
file_size=$(stat -c%s "$report_file")
if [[ "$file_size" -le "$max_inline_size" ]]; then
# Send as HTML body
{
echo "To: $EMAIL_RECIPIENT"
echo "Subject: $EMAIL_SUBJECT - $host_entry"
echo "Content-Type: text/html"
echo
cat "$report_file"
} | sendmail -t
log_msg "Email sent as inline HTML for $host_entry"
else
# Send as attachment
{
echo "To: $EMAIL_RECIPIENT"
echo "Subject: $EMAIL_SUBJECT - $host_entry (Attached)"
echo "MIME-Version: 1.0"
echo "Content-Type: multipart/mixed; boundary="MIXED-BOUNDARY""
echo
echo "--MIXED-BOUNDARY"
echo "Content-Type: text/plain"
echo
echo "Health check report is attached for $host_entry (size exceeds 2MB)."
echo
echo "--MIXED-BOUNDARY"
echo "Content-Type: text/html; name="$(basename "$report_file")""
echo "Content-Disposition: attachment; filename="$(basename "$report_file")""
echo "Content-Transfer-Encoding: base64"
echo
base64 "$report_file"
echo "--MIXED-BOUNDARY--"
} | sendmail -t
log_msg "Email sent with attachment for $host_entry (file too large)"
fi
}
##
#!/bin/bash
# Refreshable PDB Clone Precheck Script
# Usage: ./pdb_clone_precheck.sh
# Define SQL*Plus path (update if needed)
SQLPLUS="/u01/app/oracle/product/19c/dbhome_1/bin/sqlplus -s"
# Check input file
if [ $# -ne 1 ] || [ ! -f "$1" ]; then
echo "Usage: $0 "
echo "Input file format:"
echo "source_cdb|source_pdb|target_cdb|target_pdb"
exit 1
fi
INPUT_FILE="$1"
LOG_FILE="pdb_clone_precheck_$(date +%Y%m%d_%H%M%S).log"
# Precheck validation function
validate_clone_prerequisites() {
local src_cdb="$1"
local src_pdb="$2"
local tgt_cdb="$3"
local tgt_pdb="$4"
echo "================================================================="
echo " Starting precheck for:"
echo " Source: $src_cdb/$src_pdb"
echo " Target: $tgt_cdb/$tgt_pdb"
echo "================================================================="
# 1. Source CDB Checks
echo "Checking Source CDB ($src_cdb)..."
$SQLPLUS "/ as sysdba" <
# Configuration
SQLPLUS="/u01/app/oracle/product/19c/dbhome_1/bin/sqlplus -s"
HTML_FILE="pdb_precheck_$(date +%Y%m%d_%H%M%S).html"
EMAIL_TO="$2"
EMAIL_FROM="dba@company.com"
EMAIL_SUBJECT="Oracle PDB Clone Precheck Report"
# HTML Template Functions
html_header() {
echo "
PDB Clone Precheck Report
Oracle PDB Clone Precheck Report
Generated at: $(date)
Check | Source | Target | Status | Details |
" > "$HTML_FILE"
}
html_add_row() {
local check="$1"
local source="$2"
local target="$3"
local status="$4"
local details="$5"
case $status in
"PASS") class="pass" ;;
"FAIL") class="fail" ;;
*) class="warning" ;;
esac
echo "
$check |
$source |
$target |
$status |
$details |
" >> "$HTML_FILE"
}
html_footer() {
echo "
Report generated by Oracle Precheck Script
" >> "$HTML_FILE"
}
# Database Check Functions
run_sql() {
local conn="$1"
local query="$2"
$SQLPLUS -S "/ as sysdba" < [email]" && exit 1
html_header
while IFS="|" read -r src_cdb src_pdb tgt_cdb tgt_pdb; do
[[ "$src_cdb" =~ ^# || -z "$src_cdb" ]] && continue
validate_clone_prerequisites "$src_cdb" "$src_pdb" "$tgt_cdb" "$tgt_pdb"
done < "$1"
html_footer
send_email
echo "Precheck completed. HTML report: $HTML_FILE"
exit 0
####
#!/bin/bash
# Enhanced PDB Clone Precheck Script with Connectivity Checks
# Usage: ./pdb_clone_precheck.sh
# Configuration
SQLPLUS="/u01/app/oracle/product/19c/dbhome_1/bin/sqlplus -s"
HTML_FILE="pdb_precheck_$(date +%Y%m%d_%H%M%S).html"
EMAIL_TO="$2"
EMAIL_FROM="dba@company.com"
EMAIL_SUBJECT="Oracle PDB Clone Precheck Report"
OVERALL_STATUS=0
# HTML Template Functions (keep existing implementation)
html_header() { ... }
html_add_row() { ... }
html_footer() { ... }
# Database Connection Validation
check_db_connectivity() {
local cdb="$1"
local cdb_type="$2"
local query="SELECT 1 FROM DUAL;"
echo "Checking $cdb_type connectivity ($cdb)..."
local output=$(run_sql "/@$cdb as sysdba" "$query" 2>&1)
if [ $? -ne 0 ]; then
html_add_row "$cdb_type Connectivity" "$cdb" "N/A" "FAIL" "Connection failed: $output"
return 1
else
html_add_row "$cdb_type Connectivity" "$cdb" "N/A" "PASS" "Successfully connected"
return 0
fi
}
# Enhanced Validation Function with Connectivity Checks
validate_clone_prerequisites() {
local src_cdb="$1"
local src_pdb="$2"
local tgt_cdb="$3"
local tgt_pdb="$4"
local status=0
# Check source DB connectivity
if ! check_db_connectivity "$src_cdb" "Source CDB"; then
OVERALL_STATUS=1
status=1
fi
# Check target DB connectivity
if ! check_db_connectivity "$tgt_cdb" "Target CDB"; then
OVERALL_STATUS=1
status=1
fi
# Skip further checks if connectivity failed
[ $status -ne 0 ] && return 1
# Proceed with other checks (keep existing implementation)
# TDE, Charset, Patching checks...
}
# Main Execution with Exit Code Handling
[ $# -lt 1 ] && echo "Usage: $0 [email]" && exit 1
html_header
while IFS="|" read -r src_cdb src_pdb tgt_cdb tgt_pdb; do
[[ "$src_cdb" =~ ^# || -z "$src_cdb" ]] && continue
echo "Processing: $src_cdb/$src_pdb -> $tgt_cdb/$tgt_pdb"
validate_clone_prerequisites "$src_cdb" "$src_pdb" "$tgt_cdb" "$tgt_pdb"
done < "$1"
html_footer
# Send email and exit with proper status
[ -n "$EMAIL_TO" ] && send_email
echo "Precheck completed. Exit code: $OVERALL_STATUS"
exit $OVERALL_STATUS
###
check_db_connectivity() {
local cdb="$1"
local cdb_type="$2"
local query="SELECT 1 FROM DUAL;"
echo "Checking $cdb_type connectivity ($cdb)..."
local output=$(run_sql "/@$cdb as sysdba" "$query" 2>&1)
if [ $? -ne 0 ]; then
html_add_row "$cdb_type Connectivity" "$cdb" "N/A" "FAIL" "Connection failed: $output"
return 1
else
html_add_row "$cdb_type Connectivity" "$cdb" "N/A" "PASS" "Successfully connected"
return 0
fi
}
###
validate_clone_prerequisites() {
# Check source DB connectivity
if ! check_db_connectivity "$src_cdb" "Source CDB"; then
OVERALL_STATUS=1
status=1
fi
# Check target DB connectivity
if ! check_db_connectivity "$tgt_cdb" "Target CDB"; then
OVERALL_STATUS=1
status=1
fi
# Skip further checks if connectivity failed
[ $status -ne 0 ] && return 1
# ... existing checks ...
}
####
#!/bin/bash
# Refreshable PDB Clone Precheck Script with Parameter Comparison
# Usage: ./pdb_clone_precheck.sh
# Configuration
SQLPLUS="/u01/app/oracle/product/19c/dbhome_1/bin/sqlplus -s"
HTML_FILE="pdb_precheck_$(date +%Y%m%d_%H%M%S).html"
EMAIL_TO="$2"
EMAIL_FROM="dba@company.com"
EMAIL_SUBJECT="Oracle PDB Clone Precheck Report"
OVERALL_STATUS=0
EXCLUDED_PARAMS="db_name|db_unique_name|instance_name|control_files|local_listener|remote_login_passwordfile|log_archive_dest_1|dg_broker_config_file1|dg_broker_config_file2"
# HTML Template Functions (keep existing implementation)
html_header() { ... }
html_add_row() { ... }
html_footer() { ... }
# Parameter Comparison Function
compare_parameters() {
local src_cdb="$1"
local tgt_cdb="$2"
local differences=0
# Get parameters from both databases
src_params=$(mktemp)
tgt_params=$(mktemp)
run_sql "/@$src_cdb as sysdba" "SELECT name, value FROM v\$system_parameter
WHERE name NOT IN (${EXCLUDED_PARAMS//|/,})
ORDER BY name;" | awk -F' ' '{print $1 "|" $2}' > "$src_params"
run_sql "/@$tgt_cdb as sysdba" "SELECT name, value FROM v\$system_parameter
WHERE name NOT IN (${EXCLUDED_PARAMS//|/,})
ORDER BY name;" | awk -F' ' '{print $1 "|" $2}' > "$tgt_params"
# Compare parameters and format output
diff --suppress-common-lines -y "$src_params" "$tgt_params" | while read -r line; do
param=$(echo "$line" | awk -F'|' '{print $1}' | tr -d ' ')
src_val=$(echo "$line" | awk -F'|' '{print $2}' | awk '{$1=$1;print}')
tgt_val=$(echo "$line" | awk -F'|' '{print $4}' | awk '{$1=$1;print}')
html_add_row "Parameter: $param" "$src_val" "$tgt_val" "FAIL" "Parameter mismatch"
((differences++))
done
[ $differences -gt 0 ] && OVERALL_STATUS=1
rm "$src_params" "$tgt_params"
}
# Enhanced Validation Function
validate_clone_prerequisites() {
local src_cdb="$1"
local src_pdb="$2"
local tgt_cdb="$3"
local tgt_pdb="$4"
local status=0
# Check connectivity (existing implementation)
# ...
# Perform parameter comparison
compare_parameters "$src_cdb" "$tgt_cdb"
# Existing checks (TDE, charset, etc.)
# ...
}
# Main Execution (keep existing flow)
# ...
###
#!/bin/bash
# Refreshable PDB Clone Precheck Script with Storage Checks
# Usage: ./pdb_clone_precheck.sh
# Configuration
SQLPLUS="/u01/app/oracle/product/19c/dbhome_1/bin/sqlplus -s"
HTML_FILE="pdb_precheck_$(date +%Y%m%d_%H%M%S).html"
EMAIL_TO="$2"
EMAIL_FROM="dba@company.com"
EMAIL_SUBJECT="Oracle PDB Clone Precheck Report"
OVERALL_STATUS=0
# Existing functions (html_header, html_add_row, html_footer, etc.)
check_max_pdb_storage() {
local src_cdb="$1"
local src_pdb="$2"
local tgt_cdb="$3"
local tgt_pdb="$4"
# Get source PDB storage limit
src_storage=$(run_sql "/@$src_cdb as sysdba" "
ALTER SESSION SET CONTAINER = $src_pdb;
SELECT value FROM v\$parameter WHERE name = 'max_pdb_storage';")
# Get target CDB storage capabilities (if target PDB exists)
tgt_storage=$(run_sql "/@$tgt_cdb as sysdba" "
SELECT NVL2(p.name,
(SELECT value FROM v\$parameter
WHERE name = 'max_pdb_storage'
AND con_id = p.con_id), 'NOT_CREATED')
FROM v\$pdbs p WHERE p.name = '$tgt_pdb';")
# Format comparison results
if [ "$tgt_storage" == "NOT_CREATED" ]; then
html_add_row "MAX_PDB_STORAGE" "$src_storage" "N/A" "INFO" "Target PDB not created"
elif [ "$src_storage" != "$tgt_storage" ]; then
html_add_row "MAX_PDB_STORAGE" "$src_storage" "$tgt_storage" "WARN" "Storage limit mismatch"
OVERALL_STATUS=1
else
html_add_row "MAX_PDB_STORAGE" "$src_storage" "$tgt_storage" "PASS" "Storage limits match"
fi
}
validate_clone_prerequisites() {
local src_cdb="$1"
local src_pdb="$2"
local tgt_cdb="$3"
local tgt_pdb="$4"
local status=0
# Existing connectivity checks...
# MAX_PDB_STORAGE Check
check_max_pdb_storage "$src_cdb" "$src_pdb" "$tgt_cdb" "$tgt_pdb"
# Existing TDE, charset, patching checks...
}
# Main execution remains the same
pdb_clone_precheck/
├── precheck.conf # Configuration variables
├── precheck_main.sh # Main execution script
├── precheck_helpers.sh # Core helper functions
└── precheck_db_checks.sh # Database validation functions
1. precheck.conf (Configuration File):
bash
#!/bin/bash
# Configuration File - Edit these values for your environment
# Database Configuration
SQLPLUS="/u01/app/oracle/product/19c/dbhome_1/bin/sqlplus -s"
EXCLUDED_PARAMS="db_name|db_unique_name|instance_name|control_files|local_listener|remote_login_passwordfile"
WHITELISTED_PARAMS="compatible|db_block_size|memory_target"
# Email Configuration
EMAIL_FROM="dba@company.com"
EMAIL_SUBJECT="Oracle PDB Clone Precheck Report"
# File Paths
LOG_DIR="./logs"
REPORT_DIR="./reports"
2. precheck_helpers.sh (Helper Functions):
bash
#!/bin/bash
# Helper Functions
html_header() {
echo "
Oracle PDB Clone Precheck Report
Generated at: $(date)
"
}
html_add_row() {
# Existing implementation
}
html_footer() {
echo "
"
}
validate_input_file() {
[ $# -ne 1 ] || [ ! -f "$1" ] && return 1
return 0
}
initialize_directories() {
mkdir -p "$LOG_DIR" "$REPORT_DIR"
}
3. precheck_db_checks.sh (Database Validation Functions):
bash
#!/bin/bash
# Database Validation Functions
check_db_connectivity() {
# Existing implementation
}
check_tde_settings() {
# Existing implementation
}
compare_parameters() {
# Existing implementation
}
check_max_pdb_storage() {
# Existing implementation
}
check_patch_level() {
# Existing implementation
}
4. precheck_main.sh (Main Script):
bash
#!/bin/bash
# Main Execution Script
# Source configuration and functions
source ./precheck.conf
source ./precheck_helpers.sh
source ./precheck_db_checks.sh
# Initialize environment
initialize_directories
HTML_FILE="${REPORT_DIR}/pdb_precheck_$(date +%Y%m%d_%H%M%S).html"
OVERALL_STATUS=0
# Main logic
html_header > "$HTML_FILE"
while IFS="|" read -r src_cdb src_pdb tgt_cdb tgt_pdb; do
[[ "$src_cdb" =~ ^# || -z "$src_cdb" ]] && continue
validate_clone_prerequisites "$src_cdb" "$src_pdb" "$tgt_cdb" "$tgt_pdb"
done < "$1"
html_footer >> "$HTML_FILE"
send_email
exit $OVERALL_STATUS
Directory Structure Explanation:
pdb_clone_precheck/
├── config/
│ └── precheck.conf # Environment-specific settings
├── lib/
│ ├── precheck_helpers.sh # Generic helper functions
│ └── precheck_db_checks.sh # Database-specific checks
├── bin/
│ └── precheck_main.sh # Main executable script
├── logs/ # Auto-generated logs
└── reports/ # HTML reports
Usage Instructions:
Set Up Directory Structure:
bash
mkdir -p pdb_clone_precheck/{config,lib,bin,logs,reports}
Make Scripts Executable:
bash
chmod +x bin/precheck_main.sh
Run the Script:
bash
cd pdb_clone_precheck
bin/precheck_main.sh input_file.txt dba@company.com
###
#!/bin/bash
# Variables (update as needed)
SYS_USER="sys"
SYS_PASSWORD="your_password"
EMAIL_RECIPIENT="you@example.com"
INPUT_FILE="db_targets.txt"
SQL_SCRIPT="db_healthcheck_clean.sql"
LOG_DIR="./healthcheck_logs"
EMAIL_SUBJECT="Oracle DB Health Check Report"
LOG_FILE="$LOG_DIR/healthcheck_run.log"
# Ensure log directory exists
mkdir -p "$LOG_DIR"
# Function to log messages with timestamp
log_msg() {
local msg="$1"
echo "$(date '+%Y-%m-%d %H:%M:%S') : $msg" | tee -a "$LOG_FILE"
}
# Function to extract DB info
get_db_info() {
log_msg "Reading DB targets from $INPUT_FILE"
if [[ ! -f "$INPUT_FILE" ]]; then
log_msg "ERROR: Input file $INPUT_FILE not found."
exit 1
fi
mapfile -t DB_LIST < <(grep -v '^#' "$INPUT_FILE" | tr -d '[:space:]' | grep -v '^$')
if [[ ${#DB_LIST[@]} -eq 0 ]]; then
log_msg "ERROR: No valid DB entries found in $INPUT_FILE"
exit 1
fi
}
# Function to run health check for a DB
db_health_check() {
local host_entry="$1"
local timestamp
timestamp=$(date +"%Y%m%d_%H%M%S")
local report_file="$LOG_DIR/healthcheck_$(echo "$host_entry" | tr '/:' '_')_${timestamp}.html"
log_msg "Running health check for $host_entry"
sqlplus -s "$SYS_USER/$SYS_PASSWORD@$host_entry as sysdba" @"$SQL_SCRIPT" | awk 'BEGIN { print "" } { print } END { print "
" }' > "$report_file"
if [[ ! -s "$report_file" ]]; then
log_msg "WARNING: Empty or failed report for $host_entry"
else
log_msg "Health check report saved to $report_file"
fi
echo "$report_file"
}
# Function to send HTML email, fallback to mailx if sendmail not present
send_email() {
local host_entry="$1"
local report_file="$2"
if command -v sendmail > /dev/null 2>&1; then
{
echo "To: $EMAIL_RECIPIENT"
echo "Subject: $EMAIL_SUBJECT - $host_entry"
echo "Content-Type: text/html"
echo
cat "$report_file"
} | sendmail -t
log_msg "Email sent via sendmail for $host_entry"
elif command -v mailx > /dev/null 2>&1; then
mailx -a "Content-Type: text/html" -s "$EMAIL_SUBJECT - $host_entry" "$EMAIL_RECIPIENT" < "$report_file"
log_msg "Email sent via mailx for $host_entry"
else
log_msg "ERROR: No supported mail client (sendmail or mailx) found."
fi
}
# Main driver function
main() {
get_db_info
for host_entry in "${DB_LIST[@]}"; do
log_msg "Processing target: $host_entry"
report_file=$(db_health_check "$host_entry")
send_email "$host_entry" "$report_file"
done
log_msg "Health check run complete for all targets."
}
# Execute main
main