mirror of
https://github.com/uprightbass360/AzerothCore-RealmMaster.git
synced 2026-01-13 00:58:34 +00:00
266 lines
8.9 KiB
Bash
Executable File
266 lines
8.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# cleanup-orphaned-sql.sh
|
|
#
|
|
# Cleans up orphaned SQL update entries from the database.
|
|
# These are entries in the 'updates' table that reference files no longer on disk.
|
|
#
|
|
# This happens when:
|
|
# - Modules are removed/uninstalled
|
|
# - Modules are updated and old SQL files are deleted
|
|
# - Manual SQL cleanup occurs
|
|
#
|
|
# NOTE: These warnings are informational and don't affect server operation.
|
|
# This script is optional - it just cleans up the logs.
|
|
#
|
|
|
|
set -euo pipefail
|
|
|
|
# Configuration
|
|
MYSQL_CONTAINER="${MYSQL_CONTAINER:-ac-mysql}"
|
|
WORLDSERVER_CONTAINER="${WORLDSERVER_CONTAINER:-ac-worldserver}"
|
|
MYSQL_USER="${MYSQL_USER:-root}"
|
|
MYSQL_PASSWORD="${MYSQL_ROOT_PASSWORD:-}"
|
|
DRY_RUN=false
|
|
VERBOSE=false
|
|
DATABASES=("acore_world" "acore_characters" "acore_auth")
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Usage
|
|
usage() {
|
|
cat << EOF
|
|
Usage: $0 [OPTIONS]
|
|
|
|
Clean up orphaned SQL update entries from AzerothCore databases.
|
|
|
|
OPTIONS:
|
|
-p, --password PASSWORD MySQL root password (or use MYSQL_ROOT_PASSWORD env var)
|
|
-c, --container NAME MySQL container name (default: ac-mysql)
|
|
-w, --worldserver NAME Worldserver container name (default: ac-worldserver)
|
|
-d, --database DB Clean only specific database (world, characters, auth)
|
|
-n, --dry-run Show what would be cleaned without making changes
|
|
-v, --verbose Show detailed output
|
|
-h, --help Show this help message
|
|
|
|
EXAMPLES:
|
|
# Dry run to see what would be cleaned
|
|
$0 --dry-run
|
|
|
|
# Clean all databases
|
|
$0 --password yourpassword
|
|
|
|
# Clean only world database
|
|
$0 --password yourpassword --database world
|
|
|
|
# Verbose output
|
|
$0 --password yourpassword --verbose
|
|
|
|
NOTES:
|
|
- This script only removes entries from the 'updates' table
|
|
- It does NOT remove any actual data or tables
|
|
- It does NOT reverse any SQL that was applied
|
|
- This is safe to run and only cleans up tracking metadata
|
|
- Orphaned entries occur when modules are removed/updated
|
|
|
|
EOF
|
|
exit 0
|
|
}
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-p|--password)
|
|
MYSQL_PASSWORD="$2"
|
|
shift 2
|
|
;;
|
|
-c|--container)
|
|
MYSQL_CONTAINER="$2"
|
|
shift 2
|
|
;;
|
|
-w|--worldserver)
|
|
WORLDSERVER_CONTAINER="$2"
|
|
shift 2
|
|
;;
|
|
-d|--database)
|
|
case $2 in
|
|
world) DATABASES=("acore_world") ;;
|
|
characters) DATABASES=("acore_characters") ;;
|
|
auth) DATABASES=("acore_auth") ;;
|
|
*) echo -e "${RED}Error: Invalid database '$2'${NC}"; exit 1 ;;
|
|
esac
|
|
shift 2
|
|
;;
|
|
-n|--dry-run)
|
|
DRY_RUN=true
|
|
shift
|
|
;;
|
|
-v|--verbose)
|
|
VERBOSE=true
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
;;
|
|
*)
|
|
echo -e "${RED}Error: Unknown option '$1'${NC}"
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Check password
|
|
if [[ -z "$MYSQL_PASSWORD" ]]; then
|
|
echo -e "${RED}Error: MySQL password required${NC}"
|
|
echo "Use --password or set MYSQL_ROOT_PASSWORD environment variable"
|
|
exit 1
|
|
fi
|
|
|
|
# Check containers exist
|
|
if ! docker ps --format '{{.Names}}' | grep -q "^${MYSQL_CONTAINER}$"; then
|
|
echo -e "${RED}Error: MySQL container '$MYSQL_CONTAINER' not found or not running${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
if ! docker ps --format '{{.Names}}' | grep -q "^${WORLDSERVER_CONTAINER}$"; then
|
|
echo -e "${RED}Error: Worldserver container '$WORLDSERVER_CONTAINER' not found or not running${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${BLUE}║ AzerothCore Orphaned SQL Cleanup ║${NC}"
|
|
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
|
|
echo
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
echo -e "${YELLOW}DRY RUN MODE - No changes will be made${NC}"
|
|
echo
|
|
fi
|
|
|
|
# Function to get SQL files from worldserver container
|
|
get_sql_files() {
|
|
local db_type=$1
|
|
docker exec "$WORLDSERVER_CONTAINER" find "/azerothcore/data/sql/updates/${db_type}/" -name "*.sql" -type f 2>/dev/null | \
|
|
xargs -I {} basename {} 2>/dev/null || true
|
|
}
|
|
|
|
# Function to clean orphaned entries
|
|
clean_orphaned_entries() {
|
|
local database=$1
|
|
local db_type=$2
|
|
|
|
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -e "${GREEN}Processing: $database${NC}"
|
|
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
|
|
# Get list of SQL files on disk
|
|
local sql_files
|
|
sql_files=$(get_sql_files "$db_type")
|
|
|
|
if [[ -z "$sql_files" ]]; then
|
|
echo -e "${YELLOW}⚠ No SQL files found in /azerothcore/data/sql/updates/${db_type}/${NC}"
|
|
echo
|
|
return
|
|
fi
|
|
|
|
local file_count
|
|
file_count=$(echo "$sql_files" | wc -l)
|
|
echo -e "📁 Found ${file_count} SQL files on disk"
|
|
|
|
# Get entries from updates table
|
|
local total_updates
|
|
total_updates=$(docker exec "$MYSQL_CONTAINER" mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$database" -sN \
|
|
-e "SELECT COUNT(*) FROM updates" 2>/dev/null || echo "0")
|
|
|
|
echo -e "📊 Total updates in database: ${total_updates}"
|
|
|
|
if [[ "$total_updates" == "0" ]]; then
|
|
echo -e "${YELLOW}⚠ No updates found in database${NC}"
|
|
echo
|
|
return
|
|
fi
|
|
|
|
# Find orphaned entries (in DB but not on disk)
|
|
# We'll create a temp table with file names and do a LEFT JOIN
|
|
local orphaned_count=0
|
|
local orphaned_list=""
|
|
|
|
# Get all update names from DB
|
|
local db_updates
|
|
db_updates=$(docker exec "$MYSQL_CONTAINER" mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$database" -sN \
|
|
-e "SELECT name FROM updates ORDER BY name" 2>/dev/null || true)
|
|
|
|
if [[ -n "$db_updates" ]]; then
|
|
# Check each DB entry against disk files
|
|
while IFS= read -r update_name; do
|
|
if ! echo "$sql_files" | grep -qF "$update_name"; then
|
|
((orphaned_count++))
|
|
if [[ "$VERBOSE" == true ]] || [[ "$DRY_RUN" == true ]]; then
|
|
orphaned_list="${orphaned_list}${update_name}\n"
|
|
fi
|
|
|
|
# Delete if not dry run
|
|
if [[ "$DRY_RUN" == false ]]; then
|
|
docker exec "$MYSQL_CONTAINER" mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$database" -e \
|
|
"DELETE FROM updates WHERE name='${update_name}'" 2>/dev/null
|
|
fi
|
|
fi
|
|
done <<< "$db_updates"
|
|
fi
|
|
|
|
# Report results
|
|
if [[ $orphaned_count -gt 0 ]]; then
|
|
echo -e "${YELLOW}🗑️ Orphaned entries: ${orphaned_count}${NC}"
|
|
|
|
if [[ "$VERBOSE" == true ]] || [[ "$DRY_RUN" == true ]]; then
|
|
echo
|
|
echo -e "${YELLOW}Orphaned files:${NC}"
|
|
echo -e "$orphaned_list" | head -20
|
|
if [[ $orphaned_count -gt 20 ]]; then
|
|
echo -e "${YELLOW}... and $((orphaned_count - 20)) more${NC}"
|
|
fi
|
|
fi
|
|
|
|
if [[ "$DRY_RUN" == false ]]; then
|
|
echo -e "${GREEN}✅ Cleaned ${orphaned_count} orphaned entries${NC}"
|
|
else
|
|
echo -e "${YELLOW}Would clean ${orphaned_count} orphaned entries${NC}"
|
|
fi
|
|
else
|
|
echo -e "${GREEN}✅ No orphaned entries found${NC}"
|
|
fi
|
|
|
|
echo
|
|
}
|
|
|
|
# Process each database
|
|
for db in "${DATABASES[@]}"; do
|
|
case $db in
|
|
acore_world)
|
|
clean_orphaned_entries "$db" "db_world"
|
|
;;
|
|
acore_characters)
|
|
clean_orphaned_entries "$db" "db_characters"
|
|
;;
|
|
acore_auth)
|
|
clean_orphaned_entries "$db" "db_auth"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Summary
|
|
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -e "${GREEN}Cleanup Complete${NC}"
|
|
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
echo
|
|
echo -e "${YELLOW}This was a dry run. To actually clean orphaned entries, run:${NC}"
|
|
echo -e "${YELLOW} $0 --password yourpassword${NC}"
|
|
fi
|