a51d968185
- Complete security menu restructure (3-mode: Analysis/Actions/Live) - Intelligent cPHulk enablement with CSF whitelist import - Live network security monitoring dashboard - Multi-source threat detection and classification - 50+ organized security tools across 4-level menu hierarchy - System health diagnostics with cPanel/WHM integration - Reference database for cross-module intelligence sharing
423 lines
13 KiB
Bash
Executable File
423 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
#############################################################################
|
|
# MySQL Query Analyzer
|
|
# Deep forensics - identify problematic queries by domain and WordPress plugin
|
|
#############################################################################
|
|
|
|
# Get script directory and load libraries
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
source "$SCRIPT_DIR/lib/common-functions.sh"
|
|
source "$SCRIPT_DIR/lib/system-detect.sh"
|
|
source "$SCRIPT_DIR/lib/user-manager.sh"
|
|
source "$SCRIPT_DIR/lib/mysql-analyzer.sh"
|
|
|
|
# Require root
|
|
require_root
|
|
|
|
# Create session temp directory
|
|
create_temp_session
|
|
|
|
#############################################################################
|
|
# MAIN ANALYSIS
|
|
#############################################################################
|
|
|
|
main() {
|
|
clear
|
|
print_banner " MySQL Query Analyzer - Deep Forensics"
|
|
|
|
# Show system info
|
|
echo -e "${BOLD}System Detected:${NC}"
|
|
echo " Control Panel: $SYS_CONTROL_PANEL"
|
|
echo " Database: $SYS_DB_TYPE $SYS_DB_VERSION"
|
|
|
|
# Count databases and WordPress sites
|
|
local total_dbs=$(mysql -Ns -e "SHOW DATABASES" 2>/dev/null | grep -v "^information_schema$\|^mysql$\|^performance_schema$\|^sys$" | wc -l)
|
|
local wp_sites=$(find $SYS_USER_HOME_BASE -name "wp-config.php" 2>/dev/null | wc -l)
|
|
|
|
echo " Databases: $total_dbs total"
|
|
echo " WordPress Sites: $wp_sites detected"
|
|
echo ""
|
|
|
|
# Analysis options menu
|
|
echo -e "${BOLD}Analysis Options:${NC}"
|
|
echo ""
|
|
echo -e " ${GREEN}1)${NC} Full System Analysis (all databases)"
|
|
echo -e " ${GREEN}2)${NC} Single User Analysis"
|
|
echo -e " ${GREEN}3)${NC} Live Query Monitor (real-time)"
|
|
echo -e " ${GREEN}4)${NC} Slow Query Log Analysis"
|
|
echo -e " ${GREEN}5)${NC} Table Size Analysis"
|
|
echo -e " ${GREEN}6)${NC} Quick Health Check"
|
|
echo ""
|
|
echo -e " ${RED}0)${NC} Back to menu"
|
|
echo ""
|
|
|
|
read -p "Select option: " choice
|
|
|
|
case $choice in
|
|
1) run_full_analysis ;;
|
|
2) run_user_analysis ;;
|
|
3) run_live_monitor ;;
|
|
4) run_slow_query_analysis ;;
|
|
5) run_table_size_analysis ;;
|
|
6) run_quick_health_check ;;
|
|
0) return 0 ;;
|
|
*) print_error "Invalid option" ; sleep 2 ; main ;;
|
|
esac
|
|
}
|
|
|
|
#############################################################################
|
|
# ANALYSIS MODES
|
|
#############################################################################
|
|
|
|
run_full_analysis() {
|
|
clear
|
|
print_banner "Full System MySQL Analysis"
|
|
|
|
print_info "This will analyze all databases and queries system-wide..."
|
|
echo ""
|
|
|
|
if ! confirm "Continue with full analysis?"; then
|
|
return 0
|
|
fi
|
|
|
|
echo ""
|
|
print_section "Phase 1: Capturing Live Queries"
|
|
local live_queries=$(capture_live_queries)
|
|
|
|
print_section "Phase 2: Parsing Slow Query Log"
|
|
local slow_queries=$(parse_slow_query_log)
|
|
|
|
print_section "Phase 3: Analyzing Query Patterns"
|
|
local problems=$(analyze_queries_for_problems "$live_queries")
|
|
|
|
print_section "Phase 4: Analyzing Slow Queries"
|
|
analyze_queries_for_problems "$slow_queries" >> "${TEMP_SESSION_DIR}/query_problems.tmp"
|
|
|
|
print_section "Phase 5: Finding Largest Tables"
|
|
local large_tables=$(find_largest_tables 20)
|
|
|
|
print_section "Phase 6: Generating Statistics"
|
|
local stats=$(generate_plugin_statistics "${TEMP_SESSION_DIR}/query_problems.tmp")
|
|
|
|
echo ""
|
|
print_section "Analysis Complete - Generating Report"
|
|
echo ""
|
|
|
|
# Generate comprehensive report
|
|
generate_full_report
|
|
|
|
echo ""
|
|
read -p "Press Enter to continue..."
|
|
}
|
|
|
|
run_user_analysis() {
|
|
clear
|
|
print_banner "Per-User MySQL Analysis"
|
|
|
|
# Select user
|
|
local selected_user=$(select_user_interactive "Select user to analyze")
|
|
|
|
if [ $? -ne 0 ] || [ -z "$selected_user" ]; then
|
|
return 0
|
|
fi
|
|
|
|
if [ "$selected_user" = "ALL" ]; then
|
|
run_full_analysis
|
|
return 0
|
|
fi
|
|
|
|
echo ""
|
|
print_section "Analyzing user: $selected_user"
|
|
|
|
# Get user databases
|
|
local user_dbs=$(get_user_databases "$selected_user")
|
|
local db_count=$(echo "$user_dbs" | wc -l)
|
|
|
|
echo " Databases found: $db_count"
|
|
echo "$user_dbs" | sed 's/^/ - /'
|
|
echo ""
|
|
|
|
# Analyze each database
|
|
for db in $user_dbs; do
|
|
analyze_database "$db" "$selected_user"
|
|
done
|
|
|
|
echo ""
|
|
read -p "Press Enter to continue..."
|
|
}
|
|
|
|
run_live_monitor() {
|
|
clear
|
|
print_banner "Live Query Monitor"
|
|
|
|
print_info "Monitoring active MySQL queries (press Ctrl+C to stop)"
|
|
echo ""
|
|
|
|
while true; do
|
|
clear
|
|
print_section "Active Queries - $(date '+%H:%M:%S')"
|
|
|
|
mysql -e "SHOW FULL PROCESSLIST" 2>/dev/null | while read id user host db command time state info; do
|
|
if [ "$command" != "Sleep" ] && [ -n "$info" ] && [ "$info" != "SHOW FULL PROCESSLIST" ]; then
|
|
local domain=$(get_database_domain "$db")
|
|
local plugin=$(identify_plugin_from_table "$(extract_tables_from_query "$info" | head -1)")
|
|
|
|
echo -e "${YELLOW}DB: $db${NC} (${CYAN}$domain${NC}) - ${GREEN}$plugin${NC}"
|
|
echo " Time: ${time}s"
|
|
echo " Query: $(echo "$info" | cut -c1-100)..."
|
|
echo ""
|
|
fi
|
|
done
|
|
|
|
sleep 2
|
|
done
|
|
}
|
|
|
|
run_slow_query_analysis() {
|
|
clear
|
|
print_banner "Slow Query Log Analysis"
|
|
|
|
print_info "Analyzing slow query log..."
|
|
echo ""
|
|
|
|
local slow_log=$(parse_slow_query_log)
|
|
|
|
if [ ! -s "$slow_log" ]; then
|
|
print_warning "No slow queries found or slow query log is not enabled"
|
|
echo ""
|
|
echo "To enable slow query log:"
|
|
echo " 1. Edit /etc/my.cnf or /etc/mysql/my.cnf"
|
|
echo " 2. Add under [mysqld]:"
|
|
echo " slow_query_log = 1"
|
|
echo " slow_query_log_file = /var/log/mysql/slow.log"
|
|
echo " long_query_time = 2"
|
|
echo " 3. Restart MySQL: systemctl restart mysql"
|
|
echo ""
|
|
read -p "Press Enter to continue..."
|
|
return 0
|
|
fi
|
|
|
|
# Analyze slow queries
|
|
local problems=$(analyze_queries_for_problems "$slow_log")
|
|
|
|
# Show top 10 slowest
|
|
print_section "Top 10 Problematic Slow Queries"
|
|
echo ""
|
|
|
|
grep "^PROBLEM" "$problems" 2>/dev/null | head -10 | while IFS='|' read -r type domain owner db plugin table issue query_time query; do
|
|
echo -e "${RED}[$query_time s] $plugin on $domain${NC}"
|
|
echo " Database: $db | Table: $table"
|
|
echo " Issue: $issue"
|
|
echo " Recommended Fix:"
|
|
recommend_fix "$issue" "$db" "$table" "$plugin" | sed 's/^/ /'
|
|
echo ""
|
|
done
|
|
|
|
echo ""
|
|
read -p "Press Enter to continue..."
|
|
}
|
|
|
|
run_table_size_analysis() {
|
|
clear
|
|
print_banner "Table Size Analysis"
|
|
|
|
print_info "Finding largest tables and checking for bloat..."
|
|
echo ""
|
|
|
|
local large_tables=$(find_largest_tables 30)
|
|
|
|
print_section "Top 30 Largest Tables"
|
|
echo ""
|
|
|
|
printf "${BOLD}%-40s %-30s %15s %10s %20s${NC}\n" "Database" "Table" "Size (MB)" "Bloat" "Plugin"
|
|
echo "──────────────────────────────────────────────────────────────────────────────────────────────────────────────────"
|
|
|
|
while read -r db_name table_name size_mb; do
|
|
local plugin=$(identify_plugin_from_table "$table_name")
|
|
local domain=$(get_database_domain "$db_name")
|
|
local bloat=$(check_table_bloat "$db_name" "$table_name")
|
|
|
|
local bloat_color="${GREEN}"
|
|
[ "$bloat" != "OK" ] && bloat_color="${RED}"
|
|
|
|
printf "%-40s %-30s %15s ${bloat_color}%10s${NC} %20s\n" \
|
|
"$db_name" "$table_name" "${size_mb} MB" "$bloat" "$plugin"
|
|
|
|
# Recommend optimization if bloated
|
|
if [ "$bloat" != "OK" ]; then
|
|
echo " → Recommended: OPTIMIZE TABLE \`$db_name\`.\`$table_name\`;"
|
|
fi
|
|
done < "$large_tables"
|
|
|
|
echo ""
|
|
|
|
# Offer to optimize bloated tables
|
|
echo ""
|
|
if confirm "Optimize bloated tables now? (This may take time)"; then
|
|
echo ""
|
|
while read -r db_name table_name size_mb; do
|
|
local bloat=$(check_table_bloat "$db_name" "$table_name")
|
|
if [ "$bloat" != "OK" ]; then
|
|
print_info "Optimizing $db_name.$table_name..."
|
|
mysql -e "OPTIMIZE TABLE \`$db_name\`.\`$table_name\`" 2>/dev/null
|
|
print_success "Optimized $db_name.$table_name"
|
|
fi
|
|
done < "$large_tables"
|
|
fi
|
|
|
|
echo ""
|
|
read -p "Press Enter to continue..."
|
|
}
|
|
|
|
run_quick_health_check() {
|
|
clear
|
|
print_banner "Quick MySQL Health Check"
|
|
|
|
echo ""
|
|
print_section "Database Server Status"
|
|
echo ""
|
|
|
|
# Check if MySQL is running
|
|
if systemctl is-active --quiet mysql 2>/dev/null || systemctl is-active --quiet mariadb 2>/dev/null; then
|
|
print_success "MySQL/MariaDB service is running"
|
|
else
|
|
print_error "MySQL/MariaDB service is NOT running"
|
|
fi
|
|
|
|
# Get current connections
|
|
local connections=$(mysql -Ns -e "SHOW STATUS LIKE 'Threads_connected'" | awk '{print $2}')
|
|
local max_connections=$(mysql -Ns -e "SHOW VARIABLES LIKE 'max_connections'" | awk '{print $2}')
|
|
local conn_percent=$((connections * 100 / max_connections))
|
|
|
|
echo " Active Connections: $connections / $max_connections (${conn_percent}%)"
|
|
|
|
if [ $conn_percent -gt 80 ]; then
|
|
print_warning "Connection usage is high (${conn_percent}%)"
|
|
fi
|
|
|
|
# Check slow queries
|
|
local slow_queries_count=$(mysql -Ns -e "SHOW STATUS LIKE 'Slow_queries'" | awk '{print $2}')
|
|
echo " Slow Queries (total): $slow_queries_count"
|
|
|
|
# Check aborted connections
|
|
local aborted=$(mysql -Ns -e "SHOW STATUS LIKE 'Aborted_connects'" | awk '{print $2}')
|
|
echo " Aborted Connections: $aborted"
|
|
|
|
if [ "$aborted" -gt 100 ]; then
|
|
print_warning "High number of aborted connections - check for connection issues"
|
|
fi
|
|
|
|
echo ""
|
|
print_section "Top 5 Largest Databases"
|
|
echo ""
|
|
|
|
mysql -Ns -e "SELECT table_schema,
|
|
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb
|
|
FROM information_schema.TABLES
|
|
WHERE table_schema NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys')
|
|
GROUP BY table_schema
|
|
ORDER BY size_mb DESC
|
|
LIMIT 5" 2>/dev/null | while read db size; do
|
|
local owner=$(get_database_owner "$db")
|
|
local domain=$(get_database_domain "$db")
|
|
printf " %-30s %10s MB (%s - %s)\n" "$db" "$size" "$owner" "$domain"
|
|
done
|
|
|
|
echo ""
|
|
print_section "Current Resource Usage"
|
|
echo ""
|
|
|
|
echo " CPU Usage: ${CPU_USED}%"
|
|
echo " Memory Usage: ${MEM_PERCENT}%"
|
|
echo " Load Average: $LOAD_AVERAGE (${LOAD_PERCENT}% of capacity)"
|
|
|
|
echo ""
|
|
read -p "Press Enter to continue..."
|
|
}
|
|
|
|
#############################################################################
|
|
# HELPER FUNCTIONS
|
|
#############################################################################
|
|
|
|
analyze_database() {
|
|
local db_name="$1"
|
|
local username="$2"
|
|
|
|
print_section "Database: $db_name"
|
|
|
|
# Get tables
|
|
local tables=$(get_database_tables "$db_name")
|
|
local table_count=$(echo "$tables" | wc -l)
|
|
|
|
echo " Tables: $table_count"
|
|
|
|
# Identify plugins
|
|
local plugins=""
|
|
for table in $tables; do
|
|
local plugin=$(identify_plugin_from_table "$table")
|
|
if [ "$plugin" != "WordPress Core" ] && [ "$plugin" != "Unknown Plugin" ]; then
|
|
plugins="$plugins\n - $plugin"
|
|
fi
|
|
done
|
|
|
|
if [ -n "$plugins" ]; then
|
|
echo -e " Plugins detected:$plugins" | sort -u
|
|
fi
|
|
|
|
# Get database size
|
|
local db_size=$(mysql -Ns -e "SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2)
|
|
FROM information_schema.TABLES
|
|
WHERE table_schema='$db_name'" 2>/dev/null)
|
|
|
|
echo " Size: ${db_size} MB"
|
|
echo ""
|
|
}
|
|
|
|
generate_full_report() {
|
|
local report_file="/tmp/mysql_analysis_$(date +%Y%m%d_%H%M%S).txt"
|
|
local problems_file="${TEMP_SESSION_DIR}/query_problems.tmp"
|
|
|
|
exec > >(tee "$report_file")
|
|
|
|
print_banner "MySQL Deep Analysis Report"
|
|
|
|
echo "Generated: $(date)"
|
|
echo "Server: $(hostname)"
|
|
echo "Control Panel: $SYS_CONTROL_PANEL"
|
|
echo "Database: $SYS_DB_TYPE $SYS_DB_VERSION"
|
|
echo ""
|
|
|
|
# Critical issues
|
|
local critical_count=$(grep -c "^PROBLEM" "$problems_file" 2>/dev/null || echo 0)
|
|
|
|
print_section "CRITICAL ISSUES: $critical_count found"
|
|
echo ""
|
|
|
|
if [ "$critical_count" -gt 0 ]; then
|
|
grep "^PROBLEM" "$problems_file" | nl | while read num type domain owner db plugin table issue query_time query; do
|
|
echo -e "${RED}[$num] $plugin on $domain${NC}"
|
|
echo " Database: $db"
|
|
echo " Table: $table"
|
|
echo " Issue: $issue"
|
|
[ -n "$query_time" ] && [ "$query_time" != "PROBLEM" ] && echo " Query Time: ${query_time}s"
|
|
echo " Recommended Fix:"
|
|
recommend_fix "$issue" "$db" "$table" "$plugin" | sed 's/^/ /'
|
|
echo ""
|
|
done
|
|
else
|
|
print_success "No critical issues detected"
|
|
fi
|
|
|
|
echo ""
|
|
print_info "Full report saved to: $report_file"
|
|
|
|
exec > /dev/tty
|
|
}
|
|
|
|
#############################################################################
|
|
# RUN
|
|
#############################################################################
|
|
|
|
main
|