PostgreSQL、MySQL、Redis数据库管理脚本

PostgreSQL、MySQL、Redis数据库管理脚本

由于需要通过容器部署以上数据库,对Linux又不熟悉,于是使用Grok写了一个数据库管理脚本。如下:

#!/bin/bash

# 容器数据库管理工具
# 支持PostgreSQL、MySQL和Redis容器的管理

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # 无颜色

# 全局设置
CLEAR_SCREEN=true  # 是否在菜单间清屏

# 检查Docker是否安装
check_docker() {
  if ! command -v docker &> /dev/null; then
    echo -e "${RED}错误: Docker未安装或不在PATH中。请先安装Docker。${NC}"
    exit 1
  fi
}

# 查找数据库容器
find_containers() {
  echo -e "${BLUE}正在搜索数据库容器...${NC}"

  # 查找PostgreSQL容器
  pg_containers=()
  pg_images=()
  pg_names=()
  pg_running_status=()

  # 获取所有运行中的PostgreSQL容器
  while IFS= read -r container_id; do
    if [ -n "$container_id" ]; then
      pg_containers+=("$container_id")
      pg_images+=("$(docker inspect --format='{{.Config.Image}}' $container_id)")
      pg_names+=("$(docker inspect --format='{{.Name}}' $container_id | sed 's/\///')")
      pg_running_status+=(true)
    fi
  done < <(docker ps | grep -E "postgres|pgvector" | awk '{print $1}')

  # 获取所有已停止的PostgreSQL容器
  while IFS= read -r container_id; do
    if [ -n "$container_id" ] && ! [[ " ${pg_containers[@]} " =~ " ${container_id} " ]]; then
      pg_containers+=("$container_id")
      pg_images+=("$(docker inspect --format='{{.Config.Image}}' $container_id)")
      pg_names+=("$(docker inspect --format='{{.Name}}' $container_id | sed 's/\///')")
      pg_running_status+=(false)
    fi
  done < <(docker ps -a | grep -E "postgres|pgvector" | awk '{print $1}')

  # 查找MySQL容器
  mysql_container=$(docker ps | grep -E "mysql" | awk '{print $1}' | head -1)
  if [ -z "$mysql_container" ]; then
    mysql_container=$(docker ps -a | grep -E "mysql" | awk '{print $1}' | head -1)
    mysql_running=false
  else
    mysql_running=true
  fi

  # 查找Redis容器
  redis_container=$(docker ps | grep -E "redis" | awk '{print $1}' | head -1)
  if [ -z "$redis_container" ]; then
    redis_container=$(docker ps -a | grep -E "redis" | awk '{print $1}' | head -1)
    redis_running=false
  else
    redis_running=true
  fi

  # 获取容器详细信息
  if [ -n "$mysql_container" ]; then
    mysql_image=$(docker inspect --format='{{.Config.Image}}' $mysql_container)
    mysql_name=$(docker inspect --format='{{.Name}}' $mysql_container | sed 's/\///')
  fi

  if [ -n "$redis_container" ]; then
    redis_image=$(docker inspect --format='{{.Config.Image}}' $redis_container)
    redis_name=$(docker inspect --format='{{.Name}}' $redis_container | sed 's/\///')
  fi
}

# 检查容器状态并提供启动选项
check_container_status() {
  local container_id=$1
  local container_name=$2
  local container_image=$3
  local running=$4

  if [ -z "$container_id" ]; then
    echo -e "${YELLOW}未找到${container_name}容器${NC}"
    return 1
  fi

  if [ "$running" = false ]; then
    echo -e "${YELLOW}容器 ${container_name} (${container_id}) 当前已停止${NC}"
    read -p "是否启动该容器? (y/n): " start_choice
    if [[ $start_choice == [yY] || $start_choice == [yY][eE][sS] ]]; then
      echo -e "${BLUE}正在启动容器 ${container_id}...${NC}"
      docker start $container_id
      if [ $? -eq 0 ]; then
        echo -e "${GREEN}容器已成功启动${NC}"
        return 0
      else
        echo -e "${RED}启动容器失败${NC}"
        return 1
      fi
    else
      echo -e "${YELLOW}容器未启动,无法执行管理操作${NC}"
      return 1
    fi
  else
    echo -e "${GREEN}容器 ${container_name} (${container_image}) 正在运行${NC}"
    return 0
  fi
}

# 显示主菜单
show_main_menu() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "      容器数据库管理工具 v1.0"
  echo -e "========================================${NC}"
  echo -e "请选择要管理的数据库:"

  # 显示PostgreSQL容器选项
  if [ ${#pg_containers[@]} -gt 0 ]; then
    echo -e "${GREEN}PostgreSQL 容器:${NC}"
    for i in "${!pg_containers[@]}"; do
      if [ "${pg_running_status[$i]}" = true ]; then
        echo -e "${GREEN}$((i+1))) ${pg_names[$i]} (${pg_images[$i]}) ${GREEN}[运行中]${NC}"
      else
        echo -e "${GREEN}$((i+1))) ${pg_names[$i]} (${pg_images[$i]}) ${RED}[已停止]${NC}"
      fi
    done
  else
    echo -e "${YELLOW}未检测到PostgreSQL容器${NC}"
  fi

  # 显示MySQL选项
  pg_count=${#pg_containers[@]}
  mysql_option=$((pg_count+1))
  if [ -n "$mysql_container" ]; then
    if [ "$mysql_running" = true ]; then
      echo -e "${GREEN}${mysql_option}) MySQL (${mysql_image}) ${GREEN}[运行中]${NC}"
    else
      echo -e "${GREEN}${mysql_option}) MySQL (${mysql_image}) ${RED}[已停止]${NC}"
    fi
  else
    echo -e "${YELLOW}未检测到MySQL容器${NC}"
  fi

  # 显示Redis选项
  redis_option=$((mysql_option+1))
  if [ -n "$redis_container" ]; then
    if [ "$redis_running" = true ]; then
      echo -e "${GREEN}${redis_option}) Redis (${redis_image}) ${GREEN}[运行中]${NC}"
    else
      echo -e "${GREEN}${redis_option}) Redis (${redis_image}) ${RED}[已停止]${NC}"
    fi
  else
    echo -e "${YELLOW}未检测到Redis容器${NC}"
  fi

  # 设置选项
  settings_option=$((redis_option+1))
  echo -e "${GREEN}${settings_option}) 设置${NC}"

  # 退出选项
  exit_option=$((settings_option+1))
  echo -e "${YELLOW}${exit_option}) 退出${NC}"
  echo ""
  read -p "请输入选择 [1-${exit_option}]: " main_choice
}

# 显示设置菜单
show_settings_menu() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "             设置菜单"
  echo -e "========================================${NC}"
  echo -e "当前设置:"
  if [ "$CLEAR_SCREEN" = true ]; then
    echo -e "1) 清屏模式: ${GREEN}开启${NC}"
  else
    echo -e "1) 清屏模式: ${RED}关闭${NC}"
  fi
  echo -e "2) 重置Redis密码"
  echo -e "3) 重置MySQL密码"
  echo -e "4) 重置PostgreSQL密码"
  echo -e "${YELLOW}5) 返回主菜单${NC}"
  echo ""
  read -p "请输入选择 [1-5]: " settings_choice

  case $settings_choice in
    1)
      if [ "$CLEAR_SCREEN" = true ]; then
        CLEAR_SCREEN=false
        echo -e "${YELLOW}清屏模式已关闭${NC}"
      else
        CLEAR_SCREEN=true
        echo -e "${GREEN}清屏模式已开启${NC}"
      fi
      sleep 1
      show_settings_menu
      ;;
    2)
      redis_password=""
      redis_needs_auth=false
      echo -e "${GREEN}Redis密码已重置,下次使用Redis功能时将重新询问密码${NC}"
      sleep 1
      show_settings_menu
      ;;
    3)
      mysql_root_password=""
      echo -e "${GREEN}MySQL密码已重置,下次使用MySQL功能时将重新询问密码${NC}"
      sleep 1
      show_settings_menu
      ;;
    4)
      postgres_password=""
      pg_superuser=""
      echo -e "${GREEN}PostgreSQL密码和超级用户已重置,下次使用PostgreSQL功能时将重新检测${NC}"
      sleep 1
      show_settings_menu
      ;;
    5)
      return
      ;;
    *)
      echo -e "${RED}无效选择,请重试${NC}"
      sleep 1
      show_settings_menu
      ;;
  esac
}

# 检查PostgreSQL容器是否有psql工具
check_psql_in_container() {
  local container_id=$1

  # 尝试在容器中运行psql命令
  if ! docker exec $container_id which psql &>/dev/null; then
    echo -e "${YELLOW}警告: 容器中未找到psql命令。尝试使用PostgreSQL官方客户端容器连接...${NC}"
    return 1
  fi

  return 0
}

# 检测PostgreSQL超级用户
detect_pg_superuser() {
  local container_id=$1

  # 尝试从环境变量获取用户名
  local pg_user=$(docker inspect --format='{{range .Config.Env}}{{if or (eq (index (split . "=") 0) "POSTGRES_USER") (eq (index (split . "=") 0) "POSTGRESQL_USER")}}{{index (split . "=") 1}}{{end}}{{end}}' $container_id)

  # 如果环境变量中没有用户名,尝试使用默认用户名
  if [ -z "$pg_user" ]; then
    # 尝试常见的超级用户名
    local common_users=("postgres" "admin" "root" "master")

    for user in "${common_users[@]}"; do
      if docker exec $container_id psql -U $user -c "SELECT 1" &>/dev/null; then
        echo "$user"
        return 0
      fi
    done

    # 如果找不到超级用户,询问用户
    echo -e "${YELLOW}无法自动检测PostgreSQL超级用户。${NC}"
    read -p "请输入PostgreSQL超级用户名: " pg_user
    echo "$pg_user"
    return 0
  else
    echo "$pg_user"
    return 0
  fi
}

# 使用PostgreSQL客户端容器执行命令
run_pg_command() {
  local container_id=$1
  local command=$2
  local db_name=$3
  local user=${4:-}

  # 如果没有指定用户,尝试检测超级用户
  if [ -z "$user" ]; then
    if [ -z "$pg_superuser" ]; then
      pg_superuser=$(detect_pg_superuser "$container_id")
    fi
    user=$pg_superuser
  fi

  # 获取PostgreSQL容器的网络信息
  local network=$(docker inspect --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}}{{end}}' $container_id)
  local ip_address=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $container_id)
  local port=$(docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{if eq $p "5432/tcp"}}{{(index $conf 0).HostPort}}{{end}}{{end}}' $container_id)

  # 如果没有映射端口,使用默认端口5432
  if [ -z "$port" ]; then
    port="5432"
  fi

  # 获取PostgreSQL密码环境变量
  local pg_password=$(docker inspect --format='{{range .Config.Env}}{{if or (eq (index (split . "=") 0) "POSTGRES_PASSWORD") (eq (index (split . "=") 0) "POSTGRESQL_PASSWORD")}}{{index (split . "=") 1}}{{end}}{{end}}' $container_id)

  # 如果没有找到密码环境变量,询问用户
  if [ -z "$pg_password" ]; then
    if [ -z "$postgres_password" ]; then
      echo -e "${YELLOW}需要PostgreSQL密码来执行管理操作${NC}"
      read -s -p "请输入PostgreSQL密码: " postgres_password
      echo ""
      pg_password=$postgres_password
    else
      pg_password=$postgres_password
    fi
  else
    postgres_password=$pg_password
  fi

  # 创建临时脚本
  local temp_script=$(mktemp)
  echo "#!/bin/bash" > $temp_script
  echo "export PGPASSWORD='$pg_password'" >> $temp_script

  if [ -n "$db_name" ]; then
    echo "psql -h $ip_address -p $port -U $user -d $db_name -c \"$command\"" >> $temp_script
  else
    echo "psql -h $ip_address -p $port -U $user -c \"$command\"" >> $temp_script
  fi

  chmod +x $temp_script

  # 使用PostgreSQL客户端容器执行命令
  local output=$(docker run --rm --network $network -v $temp_script:/tmp/script.sh postgres:14-alpine /tmp/script.sh)
  echo "$output"

  # 删除临时脚本
  rm $temp_script
}

# PostgreSQL菜单
show_postgres_menu() {
  # 选择PostgreSQL容器
  if [ ${#pg_containers[@]} -gt 1 ]; then
    if [ "$CLEAR_SCREEN" = true ]; then
      clear
    else
      echo ""
      echo -e "${BLUE}----------------------------------------${NC}"
      echo ""
    fi

    echo -e "${CYAN}========================================"
    echo -e "         选择PostgreSQL容器"
    echo -e "========================================${NC}"
    echo -e "请选择要管理的PostgreSQL容器:"

    for i in "${!pg_containers[@]}"; do
      if [ "${pg_running_status[$i]}" = true ]; then
        echo -e "${GREEN}$((i+1))) ${pg_names[$i]} (${pg_images[$i]}) ${GREEN}[运行中]${NC}"
      else
        echo -e "${GREEN}$((i+1))) ${pg_names[$i]} (${pg_images[$i]}) ${RED}[已停止]${NC}"
      fi
    done

    echo -e "${YELLOW}$((${#pg_containers[@]}+1))) 返回主菜单${NC}"
    echo ""
    read -p "请输入选择 [1-$((${#pg_containers[@]}+1))]: " pg_container_choice

    if [ "$pg_container_choice" -eq $((${#pg_containers[@]}+1)) ]; then
      return
    fi

    if [ "$pg_container_choice" -lt 1 ] || [ "$pg_container_choice" -gt ${#pg_containers[@]} ]; then
      echo -e "${RED}无效选择,请重试${NC}"
      sleep 1
      show_postgres_menu
      return
    fi

    pg_container_index=$((pg_container_choice-1))
    pg_container=${pg_containers[$pg_container_index]}
    pg_image=${pg_images[$pg_container_index]}
    pg_name=${pg_names[$pg_container_index]}
    pg_running=${pg_running_status[$pg_container_index]}
  else
    pg_container=${pg_containers[0]}
    pg_image=${pg_images[0]}
    pg_name=${pg_names[0]}
    pg_running=${pg_running_status[0]}
  fi

  if ! check_container_status "$pg_container" "PostgreSQL" "$pg_image" "$pg_running"; then
    read -p "按回车键返回主菜单..." temp
    return
  fi

  # 检查容器中是否有psql工具
  has_psql=true
  if ! check_psql_in_container "$pg_container"; then
    has_psql=false
    echo -e "${YELLOW}将使用PostgreSQL客户端容器执行命令${NC}"
    sleep 2
  fi

  # 检测PostgreSQL超级用户
  if [ -z "$pg_superuser" ]; then
    pg_superuser=$(detect_pg_superuser "$pg_container")
    echo -e "${GREEN}检测到PostgreSQL超级用户: $pg_superuser${NC}"
    sleep 1
  fi

  # 获取PostgreSQL密码
  if [ "$has_psql" = true ]; then
    # 如果容器有psql,尝试获取密码环境变量
    postgres_password=$(docker inspect --format='{{range .Config.Env}}{{if or (eq (index (split . "=") 0) "POSTGRES_PASSWORD") (eq (index (split . "=") 0) "POSTGRESQL_PASSWORD")}}{{index (split . "=") 1}}{{end}}{{end}}' $pg_container)

    # 如果没有找到密码环境变量,询问用户
    if [ -z "$postgres_password" ]; then
      echo -e "${YELLOW}需要PostgreSQL密码来执行管理操作${NC}"
      read -s -p "请输入PostgreSQL密码: " postgres_password
      echo ""
    fi
  fi

  while true; do
    if [ "$CLEAR_SCREEN" = true ]; then
      clear
    else
      echo ""
      echo -e "${BLUE}----------------------------------------${NC}"
      echo ""
    fi

    echo -e "${CYAN}========================================"
    echo -e "         PostgreSQL 管理菜单"
    echo -e "========================================${NC}"
    echo -e "当前连接的容器: ${GREEN}${pg_image}${NC} (${YELLOW}${pg_container}${NC})"
    echo -e "使用超级用户: ${GREEN}${pg_superuser}${NC}"
    echo ""
    echo -e "请选择操作:"
    echo -e "${GREEN}1) 创建用户和数据库${NC}"
    echo -e "${GREEN}2) 查询所有用户和数据库${NC}"
    echo -e "${GREEN}3) 删除用户或数据库${NC}"
    echo -e "${GREEN}4) 开启PGVector插件${NC}"
    echo -e "${YELLOW}5) 返回主菜单${NC}"
    echo ""
    read -p "请输入选择 [1-5]: " pg_choice

    case $pg_choice in
      1) create_postgres_user_db ;;
      2) list_postgres_users_dbs ;;
      3) delete_postgres_user_db ;;
      4) enable_pgvector ;;
      5) break ;;
      *) echo -e "${RED}无效选择,请重试${NC}" 
         sleep 1 ;;
    esac
  done
}

# MySQL菜单
show_mysql_menu() {
  if ! check_container_status "$mysql_container" "MySQL" "$mysql_image" "$mysql_running"; then
    read -p "按回车键返回主菜单..." temp
    return
  fi

  # 第一次进入MySQL菜单,获取root密码
  if [ -z "$mysql_root_password" ]; then
    # 尝试从环境变量获取密码
    mysql_root_password=$(docker inspect --format='{{range .Config.Env}}{{if eq (index (split . "=") 0) "MYSQL_ROOT_PASSWORD"}}{{index (split . "=") 1}}{{end}}{{end}}' $mysql_container)

    # 如果没有找到密码环境变量,询问用户
    if [ -z "$mysql_root_password" ]; then
      echo -e "${YELLOW}需要MySQL root密码来执行管理操作${NC}"
      read -s -p "请输入MySQL root密码: " mysql_root_password
      echo ""
    else
      echo -e "${GREEN}已从容器环境变量中获取MySQL root密码${NC}"
      sleep 1
    fi

    # 验证密码是否正确
    if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SELECT 1" >/dev/null 2>&1; then
      echo -e "${RED}密码验证失败,无法连接到MySQL${NC}"
      mysql_root_password=""
      read -p "按回车键返回主菜单..." temp
      return
    fi
    echo -e "${GREEN}密码验证成功${NC}"
  fi

  while true; do
    if [ "$CLEAR_SCREEN" = true ]; then
      clear
    else
      echo ""
      echo -e "${BLUE}----------------------------------------${NC}"
      echo ""
    fi

    echo -e "${CYAN}========================================"
    echo -e "           MySQL 管理菜单"
    echo -e "========================================${NC}"
    echo -e "当前连接的容器: ${GREEN}${mysql_image}${NC} (${YELLOW}${mysql_container}${NC})"
    echo ""
    echo -e "请选择操作:"
    echo -e "${GREEN}1) 创建用户和数据库${NC}"
    echo -e "${GREEN}2) 查询所有用户和数据库${NC}"
    echo -e "${GREEN}3) 删除用户或数据库${NC}"
    echo -e "${YELLOW}4) 返回主菜单${NC}"
    echo ""
    read -p "请输入选择 [1-4]: " mysql_choice

    case $mysql_choice in
      1) create_mysql_user_db ;;
      2) list_mysql_users_dbs ;;
      3) delete_mysql_user_db ;;
      4) break ;;
      *) echo -e "${RED}无效选择,请重试${NC}" 
         sleep 1 ;;
    esac
  done
}

# Redis菜单
show_redis_menu() {
  if ! check_container_status "$redis_container" "Redis" "$redis_image" "$redis_running"; then
    read -p "按回车键返回主菜单..." temp
    return
  fi

  # 检查是否需要Redis密码
  if [ -z "$redis_password" ]; then
    # 默认假设Redis需要密码
    redis_needs_auth=true

    # 尝试从环境变量获取密码
    redis_password=$(docker inspect --format='{{range .Config.Env}}{{if or (eq (index (split . "=") 0) "REDIS_PASSWORD") (eq (index (split . "=") 0) "REDIS_PASS") (eq (index (split . "=") 0) "REDIS_AUTH")}}{{index (split . "=") 1}}{{end}}{{end}}' $redis_container)

    # 如果环境变量中没有密码,询问用户
    if [ -z "$redis_password" ]; then
      echo -e "${YELLOW}Redis可能需要密码认证${NC}"
      read -s -p "请输入Redis密码 (如果不需要密码,直接按回车): " redis_password
      echo ""
    else
      echo -e "${GREEN}已从容器环境变量中获取Redis密码${NC}"
      sleep 1
    fi

    # 测试无密码连接
    if [ -z "$redis_password" ] && docker exec $redis_container redis-cli ping >/dev/null 2>&1; then
      echo -e "${GREEN}Redis不需要密码认证${NC}"
      redis_needs_auth=false
      sleep 1
    elif [ -n "$redis_password" ]; then
      # 验证密码是否正确
      if ! docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning ping >/dev/null 2>&1; then
        echo -e "${RED}密码验证失败,无法连接到Redis${NC}"

        # 再次尝试获取密码
        echo -e "${YELLOW}请再次尝试输入Redis密码${NC}"
        read -s -p "请输入Redis密码: " redis_password
        echo ""

        # 再次验证密码
        if ! docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning ping >/dev/null 2>&1; then
          echo -e "${RED}密码验证再次失败${NC}"

          # 尝试一些常见的默认密码
          echo -e "${YELLOW}尝试常见的默认密码...${NC}"
          for default_pass in "redis" "admin" "password" "123456" "root"; do
            echo -e "${BLUE}尝试密码: $default_pass${NC}"
            if docker exec $redis_container redis-cli -a "$default_pass" --no-auth-warning ping >/dev/null 2>&1; then
              redis_password=$default_pass
              echo -e "${GREEN}找到有效密码: $default_pass${NC}"
              sleep 1
              break
            fi
          done

          # 如果仍然失败,提示用户手动输入正确的密码
          if ! docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning ping >/dev/null 2>&1; then
            echo -e "${RED}无法自动找到有效的Redis密码${NC}"
            echo -e "${YELLOW}请确保输入正确的Redis密码,或者检查Redis配置${NC}"
            read -p "按回车键继续,将尝试使用当前密码..." temp
          fi
        else
          echo -e "${GREEN}密码验证成功${NC}"
        fi
      else
        echo -e "${GREEN}密码验证成功${NC}"
      fi
    else
      echo -e "${RED}无法连接到Redis,可能需要密码${NC}"
      echo -e "${YELLOW}请输入Redis密码${NC}"
      read -s -p "请输入Redis密码: " redis_password
      echo ""

      # 验证密码
      if ! docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning ping >/dev/null 2>&1; then
        echo -e "${RED}密码验证失败${NC}"
        echo -e "${YELLOW}将尝试使用当前密码继续操作,如果操作失败,请在设置菜单中重置Redis密码${NC}"
        read -p "按回车键继续..." temp
      else
        echo -e "${GREEN}密码验证成功${NC}"
      fi
    fi
  fi

  while true; do
    if [ "$CLEAR_SCREEN" = true ]; then
      clear
    else
      echo ""
      echo -e "${BLUE}----------------------------------------${NC}"
      echo ""
    fi

    echo -e "${CYAN}========================================"
    echo -e "           Redis 管理菜单"
    echo -e "========================================${NC}"
    echo -e "当前连接的容器: ${GREEN}${redis_image}${NC} (${YELLOW}${redis_container}${NC})"
    if [ "$redis_needs_auth" = true ] && [ -n "$redis_password" ]; then
      echo -e "认证状态: ${GREEN}已认证 (使用密码)${NC}"
    elif [ "$redis_needs_auth" = false ]; then
      echo -e "认证状态: ${GREEN}无需密码${NC}"
    else
      echo -e "认证状态: ${RED}未认证${NC}"
    fi
    echo ""
    echo -e "请选择操作:"
    echo -e "${GREEN}1) 查看Redis信息${NC}"
    echo -e "${GREEN}2) 查看内存使用${NC}"
    echo -e "${GREEN}3) 查看键值统计${NC}"
    echo -e "${GREEN}4) 设置Redis密码${NC}"
    echo -e "${YELLOW}5) 返回主菜单${NC}"
    echo ""
    read -p "请输入选择 [1-5]: " redis_choice

    case $redis_choice in
      1) show_redis_info ;;
      2) show_redis_memory ;;
      3) show_redis_keys ;;
      4) set_redis_password ;;
      5) break ;;
      *) echo -e "${RED}无效选择,请重试${NC}" 
         sleep 1 ;;
    esac
  done
}

# Redis功能:设置Redis密码
set_redis_password() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "           设置Redis密码"
  echo -e "========================================${NC}"
  echo ""

  echo -e "${YELLOW}请输入Redis密码:${NC}"
  read -s -p "密码: " new_redis_password
  echo ""

  # 测试新密码
  if [ -z "$new_redis_password" ]; then
    echo -e "${YELLOW}尝试无密码连接...${NC}"
    if docker exec $redis_container redis-cli ping >/dev/null 2>&1; then
      echo -e "${GREEN}无密码连接成功${NC}"
      redis_password=""
      redis_needs_auth=false
    else
      echo -e "${RED}无密码连接失败,Redis可能需要密码${NC}"
      redis_needs_auth=true
    fi
  else
    echo -e "${YELLOW}尝试使用新密码连接...${NC}"
    if docker exec $redis_container redis-cli -a "$new_redis_password" --no-auth-warning ping >/dev/null 2>&1; then
      echo -e "${GREEN}密码验证成功${NC}"
      redis_password=$new_redis_password
      redis_needs_auth=true
    else
      echo -e "${RED}密码验证失败${NC}"
      echo -e "${YELLOW}保留原密码设置${NC}"
    fi
  fi

  read -p "按回车键继续..." temp
}

# PostgreSQL功能:创建用户和数据库
create_postgres_user_db() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "       创建PostgreSQL用户和数据库"
  echo -e "========================================${NC}"
  echo ""

  # 获取基础名称
  read -p "请输入基础名称 (如输入lobe将创建lobe_user和lobe_db): " base_name
  if [ -z "$base_name" ]; then
    echo -e "${RED}错误: 名称不能为空${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  # 检查名称格式
  if ! [[ $base_name =~ ^[a-zA-Z0-9_]+$ ]]; then
    echo -e "${RED}错误: 名称只能包含字母、数字和下划线${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  user_name="${base_name}_user"
  db_name="${base_name}_db"

  # 检查用户名是否已存在
  echo -e "${BLUE}检查用户是否存在...${NC}"
  if [ "$has_psql" = true ]; then
    exists=$(docker exec $pg_container psql -U $pg_superuser -tAc "SELECT 1 FROM pg_roles WHERE rolname='$user_name'")
  else
    exists=$(run_pg_command "$pg_container" "SELECT 1 FROM pg_roles WHERE rolname='$user_name'" "" "$pg_superuser")
  fi

  if [[ $exists == *"1"* ]]; then
    echo -e "${RED}错误: 用户 $user_name 已经存在${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  # 检查数据库是否已存在
  echo -e "${BLUE}检查数据库是否存在...${NC}"
  if [ "$has_psql" = true ]; then
    exists=$(docker exec $pg_container psql -U $pg_superuser -tAc "SELECT 1 FROM pg_database WHERE datname='$db_name'")
  else
    exists=$(run_pg_command "$pg_container" "SELECT 1 FROM pg_database WHERE datname='$db_name'" "" "$pg_superuser")
  fi

  if [[ $exists == *"1"* ]]; then
    echo -e "${RED}错误: 数据库 $db_name 已经存在${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  # 获取密码
  read -s -p "请设置用户密码: " password
  echo ""
  read -s -p "确认密码: " password_confirm
  echo ""

  if [ "$password" != "$password_confirm" ]; then
    echo -e "${RED}错误: 两次输入的密码不匹配${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  echo -e "${BLUE}创建用户 $user_name...${NC}"
  if [ "$has_psql" = true ]; then
    if ! docker exec $pg_container psql -U $pg_superuser -c "CREATE USER $user_name WITH PASSWORD '$password';" >/dev/null 2>&1; then
      echo -e "${RED}创建用户失败${NC}"
      read -p "按回车键继续..." temp
      return
    fi
  else
    if ! run_pg_command "$pg_container" "CREATE USER $user_name WITH PASSWORD '$password';" "" "$pg_superuser" >/dev/null 2>&1; then
      echo -e "${RED}创建用户失败${NC}"
      read -p "按回车键继续..." temp
      return
    fi
  fi
  echo -e "${GREEN}成功${NC}"

  echo -e "${BLUE}创建数据库 $db_name...${NC}"
  if [ "$has_psql" = true ]; then
    if ! docker exec $pg_container psql -U $pg_superuser -c "CREATE DATABASE $db_name OWNER $user_name;" >/dev/null 2>&1; then
      echo -e "${RED}创建数据库失败${NC}"
      echo -e "${YELLOW}正在回滚,删除已创建的用户...${NC}"
      docker exec $pg_container psql -U $pg_superuser -c "DROP USER $user_name;" >/dev/null 2>&1
      read -p "按回车键继续..." temp
      return
    fi
  else
    if ! run_pg_command "$pg_container" "CREATE DATABASE $db_name OWNER $user_name;" "" "$pg_superuser" >/dev/null 2>&1; then
      echo -e "${RED}创建数据库失败${NC}"
      echo -e "${YELLOW}正在回滚,删除已创建的用户...${NC}"
      run_pg_command "$pg_container" "DROP USER $user_name;" "" "$pg_superuser" >/dev/null 2>&1
      read -p "按回车键继续..." temp
      return
    fi
  fi
  echo -e "${GREEN}成功${NC}"

  echo -e "${BLUE}授予用户 $user_name 对数据库 $db_name 的全部权限...${NC}"
  if [ "$has_psql" = true ]; then
    if ! docker exec $pg_container psql -U $pg_superuser -c "GRANT ALL PRIVILEGES ON DATABASE $db_name TO $user_name;" >/dev/null 2>&1; then
      echo -e "${RED}授权失败${NC}"
      read -p "按回车键继续..." temp
      return
    fi
  else
    if ! run_pg_command "$pg_container" "GRANT ALL PRIVILEGES ON DATABASE $db_name TO $user_name;" "" "$pg_superuser" >/dev/null 2>&1; then
      echo -e "${RED}授权失败${NC}"
      read -p "按回车键继续..." temp
      return
    fi
  fi
  echo -e "${GREEN}成功${NC}"

  # 询问是否开启PGVector插件
  read -p "是否开启PGVector插件? (y/n): " enable_vector
  if [[ $enable_vector == [yY] || $enable_vector == [yY][eE][sS] ]]; then
    echo -e "${BLUE}在数据库 $db_name 中开启PGVector插件...${NC}"
    if [ "$has_psql" = true ]; then
      if ! docker exec $pg_container psql -U $pg_superuser -d $db_name -c "CREATE EXTENSION IF NOT EXISTS vector;" >/dev/null 2>&1; then
        echo -e "${RED}执行CREATE EXTENSION命令失败${NC}"
        read -p "按回车键继续..." temp
        return
      fi
      # 验证是否启用成功
      vector_enabled=$(docker exec $pg_container psql -U $pg_superuser -d $db_name -tAc "SELECT 1 FROM pg_extension WHERE extname='vector'")
      if [[ $vector_enabled == *"1"* ]]; then
        vector_version=$(docker exec $pg_container psql -U $pg_superuser -d $db_name -tAc "SELECT extversion FROM pg_extension WHERE extname='vector'")
        echo -e "${GREEN}PGVector 插件已成功启用 (版本: $vector_version)${NC}"
      else
        echo -e "${RED}PGVector 插件未能启用,请检查容器配置${NC}"
        read -p "按回车键继续..." temp
        return
      fi
    else
      if ! run_pg_command "$pg_container" "CREATE EXTENSION IF NOT EXISTS vector;" "$db_name" "$pg_superuser" >/dev/null 2>&1; then
        echo -e "${RED}执行CREATE EXTENSION命令失败${NC}"
        read -p "按回车键继续..." temp
        return
      fi
      # 验证是否启用成功
      vector_enabled=$(run_pg_command "$pg_container" "SELECT 1 FROM pg_extension WHERE extname='vector'" "$db_name" "$pg_superuser")
      if [[ $vector_enabled == *"1"* ]]; then
        vector_version=$(run_pg_command "$pg_container" "SELECT extversion FROM pg_extension WHERE extname='vector'" "$db_name" "$pg_superuser")
        echo -e "${GREEN}PGVector 插件已成功启用 (版本: $vector_version)${NC}"
      else
        echo -e "${RED}PGVector 插件未能启用,请检查容器配置${NC}"
        read -p "按回车键继续..." temp
        return
      fi
    fi
  fi

  echo -e "${GREEN}操作完成!${NC}"
  read -p "按回车键继续..." temp
}

# PostgreSQL功能:查询所有用户和数据库
list_postgres_users_dbs() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "      PostgreSQL 用户和数据库列表"
  echo -e "========================================${NC}"
  echo ""

  echo -e "${YELLOW}数据库列表:${NC}"
  if [ "$has_psql" = true ]; then
    docker exec $pg_container psql -U $pg_superuser -c "SELECT datname AS database_name, pg_size_pretty(pg_database_size(datname)) AS size FROM pg_database WHERE datistemplate = false ORDER BY datname;"
  else
    run_pg_command "$pg_container" "SELECT datname AS database_name, pg_size_pretty(pg_database_size(datname)) AS size FROM pg_database WHERE datistemplate = false ORDER BY datname;" "" "$pg_superuser"
  fi
  echo ""

  echo -e "${YELLOW}用户列表:${NC}"
  if [ "$has_psql" = true ]; then
    docker exec $pg_container psql -U $pg_superuser -c "SELECT rolname AS user_name, rolsuper AS is_superuser FROM pg_roles WHERE rolname NOT LIKE 'pg_%' ORDER BY rolname;"
  else
    run_pg_command "$pg_container" "SELECT rolname AS user_name, rolsuper AS is_superuser FROM pg_roles WHERE rolname NOT LIKE 'pg_%' ORDER BY rolname;" "" "$pg_superuser"
  fi
  echo ""

  echo -e "${YELLOW}用户权限:${NC}"
  if [ "$has_psql" = true ]; then
    docker exec $pg_container psql -U $pg_superuser -c "SELECT DISTINCT grantee AS user_name, table_catalog AS database_name, privilege_type FROM information_schema.table_privileges WHERE grantee NOT LIKE 'pg_%' ORDER BY grantee, table_catalog;"
  else
    run_pg_command "$pg_container" "SELECT DISTINCT grantee AS user_name, table_catalog AS database_name, privilege_type FROM information_schema.table_privileges WHERE grantee NOT LIKE 'pg_%' ORDER BY grantee, table_catalog;" "" "$pg_superuser"
  fi

  read -p "按回车键继续..." temp
}

# PostgreSQL功能:删除用户或数据库
delete_postgres_user_db() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "        删除PostgreSQL用户或数据库"
  echo -e "========================================${NC}"
  echo ""

  echo -e "请选择要删除的对象:"
  echo -e "${GREEN}1) 用户${NC}"
  echo -e "${GREEN}2) 数据库${NC}"
  echo -e "${YELLOW}3) 返回上级菜单${NC}"
  echo ""
  read -p "请输入选择 [1-3]: " delete_choice

  case $delete_choice in
    1) # 删除用户
      echo -e "${YELLOW}当前PostgreSQL用户列表:${NC}"
      if [ "$has_psql" = true ]; then
        docker exec $pg_container psql -U $pg_superuser -c "SELECT rolname AS user_name FROM pg_roles WHERE rolname NOT LIKE 'pg_%' AND rolname != '$pg_superuser' ORDER BY rolname;"
      else
        run_pg_command "$pg_container" "SELECT rolname AS user_name FROM pg_roles WHERE rolname NOT LIKE 'pg_%' AND rolname != '$pg_superuser' ORDER BY rolname;" "" "$pg_superuser"
      fi
      echo ""

      read -p "请输入要删除的用户名: " user_name
      if [ -z "$user_name" ]; then
        echo -e "${RED}错误: 用户名不能为空${NC}"
        read -p "按回车键继续..." temp
        return
      fi

      # 检查用户是否存在
      if [ "$has_psql" = true ]; then
        exists=$(docker exec $pg_container psql -U $pg_superuser -tAc "SELECT 1 FROM pg_roles WHERE rolname='$user_name'")
      else
        exists=$(run_pg_command "$pg_container" "SELECT 1 FROM pg_roles WHERE rolname='$user_name'" "" "$pg_superuser")
      fi

      if ! [[ $exists == *"1"* ]]; then
        echo -e "${RED}错误: 用户 $user_name 不存在${NC}"
        read -p "按回车键继续..." temp
        return
      fi

      # 检查关联的数据库
      if [ "$has_psql" = true ]; then
        associated_db=$(docker exec $pg_container psql -U $pg_superuser -tAc "SELECT datname FROM pg_database WHERE datdba = (SELECT oid FROM pg_roles WHERE rolname='$user_name') LIMIT 1")
      else
        associated_db=$(run_pg_command "$pg_container" "SELECT datname FROM pg_database WHERE datdba = (SELECT oid FROM pg_roles WHERE rolname='$user_name') LIMIT 1" "" "$pg_superuser")
      fi

      if [ -n "$associated_db" ]; then
        echo -e "${YELLOW}检测到关联的数据库: $associated_db${NC}"
        read -p "是否同时删除关联的数据库? (y/n): " delete_db

        if [[ $delete_db == [yY] || $delete_db == [yY][eE][sS] ]]; then
          echo -e "${BLUE}删除数据库 $associated_db...${NC}"
          if [ "$has_psql" = true ]; then
            if ! docker exec $pg_container psql -U $pg_superuser -c "DROP DATABASE $associated_db;" >/dev/null 2>&1; then
              echo -e "${RED}删除数据库失败${NC}"
              read -p "按回车键继续..." temp
              return
            fi
          else
            if ! run_pg_command "$pg_container" "DROP DATABASE $associated_db;" "" "$pg_superuser" >/dev/null 2>&1; then
              echo -e "${RED}删除数据库失败${NC}"
              read -p "按回车键继续..." temp
              return
            fi
          fi
          echo -e "${GREEN}成功${NC}"
        fi
      fi

      echo -e "${BLUE}删除用户 $user_name...${NC}"
      if [ "$has_psql" = true ]; then
        if ! docker exec $pg_container psql -U $pg_superuser -c "DROP USER $user_name;" >/dev/null 2>&1; then
          echo -e "${RED}删除用户失败${NC}"
          read -p "按回车键继续..." temp
          return
        fi
      else
        if ! run_pg_command "$pg_container" "DROP USER $user_name;" "" "$pg_superuser" >/dev/null 2>&1; then
          echo -e "${RED}删除用户失败${NC}"
          read -p "按回车键继续..." temp
          return
        fi
      fi
      echo -e "${GREEN}成功${NC}"
      ;;

    2) # 删除数据库
      echo -e "${YELLOW}当前PostgreSQL数据库列表:${NC}"
      if [ "$has_psql" = true ]; then
        docker exec $pg_container psql -U $pg_superuser -c "SELECT datname AS database_name FROM pg_database WHERE datistemplate = false AND datname != 'postgres' ORDER BY datname;"
      else
        run_pg_command "$pg_container" "SELECT datname AS database_name FROM pg_database WHERE datistemplate = false AND datname != 'postgres' ORDER BY datname;" "" "$pg_superuser"
      fi
      echo ""

      read -p "请输入要删除的数据库名: " db_name
      if [ -z "$db_name" ]; then
        echo -e "${RED}错误: 数据库名不能为空${NC}"
        read -p "按回车键继续..." temp
        return
      fi

      # 检查数据库是否存在
      if [ "$has_psql" = true ]; then
        exists=$(docker exec $pg_container psql -U $pg_superuser -tAc "SELECT 1 FROM pg_database WHERE datname='$db_name'")
      else
        exists=$(run_pg_command "$pg_container" "SELECT 1 FROM pg_database WHERE datname='$db_name'" "" "$pg_superuser")
      fi

      if ! [[ $exists == *"1"* ]]; then
        echo -e "${RED}错误: 数据库 $db_name 不存在${NC}"
        read -p "按回车键继续..." temp
        return
      fi

      # 检查拥有该数据库的用户
      if [ "$has_psql" = true ]; then
        owner=$(docker exec $pg_container psql -U $pg_superuser -tAc "SELECT rolname FROM pg_roles WHERE oid = (SELECT datdba FROM pg_database WHERE datname='$db_name')")
      else
        owner=$(run_pg_command "$pg_container" "SELECT rolname FROM pg_roles WHERE oid = (SELECT datdba FROM pg_database WHERE datname='$db_name')" "" "$pg_superuser")
      fi

      if [ "$owner" != "$pg_superuser" ]; then
        echo -e "${YELLOW}检测到数据库所有者: $owner${NC}"
        read -p "是否同时删除数据库所有者? (y/n): " delete_owner

        if [[ $delete_owner == [yY] || $delete_owner == [yY][eE][sS] ]]; then
          # 先删数据库再删用户
          delete_owner_later=true
        fi
      fi

      echo -e "${BLUE}删除数据库 $db_name...${NC}"
      if [ "$has_psql" = true ]; then
        if ! docker exec $pg_container psql -U $pg_superuser -c "DROP DATABASE $db_name;" >/dev/null 2>&1; then
          echo -e "${RED}删除数据库失败${NC}"
          read -p "按回车键继续..." temp
          return
        fi
      else
        if ! run_pg_command "$pg_container" "DROP DATABASE $db_name;" "" "$pg_superuser" >/dev/null 2>&1; then
          echo -e "${RED}删除数据库失败${NC}"
          read -p "按回车键继续..." temp
          return
        fi
      fi
      echo -e "${GREEN}成功${NC}"

      if [ "$delete_owner_later" = true ]; then
        echo -e "${BLUE}删除用户 $owner...${NC}"
        if [ "$has_psql" = true ]; then
          if ! docker exec $pg_container psql -U $pg_superuser -c "DROP USER $owner;" >/dev/null 2>&1; then
            echo -e "${RED}删除用户失败${NC}"
            read -p "按回车键继续..." temp
            return
          fi
        else
          if ! run_pg_command "$pg_container" "DROP USER $owner;" "" "$pg_superuser" >/dev/null 2>&1; then
            echo -e "${RED}删除用户失败${NC}"
            read -p "按回车键继续..." temp
            return
          fi
        fi
        echo -e "${GREEN}成功${NC}"
      fi
      ;;

    3) return ;;
    *) echo -e "${RED}无效选择,请重试${NC}" 
       sleep 1
       delete_postgres_user_db
       ;;
  esac

  echo -e "${GREEN}操作完成!${NC}"
  read -p "按回车键继续..." temp
}

# PostgreSQL功能:开启PGVector插件
enable_pgvector() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "        开启PostgreSQL PGVector插件"
  echo -e "========================================${NC}"
  echo ""

  echo -e "${YELLOW}可用的数据库列表:${NC}"
  if [ "$has_psql" = true ]; then
    docker exec $pg_container psql -U $pg_superuser -c "SELECT datname AS database_name FROM pg_database WHERE datistemplate = false AND datname != 'postgres' ORDER BY datname;"
  else
    run_pg_command "$pg_container" "SELECT datname AS database_name FROM pg_database WHERE datistemplate = false AND datname != 'postgres' ORDER BY datname;" "" "$pg_superuser"
  fi
  echo ""

  read -p "请输入要开启PGVector插件的数据库名: " db_name
  if [ -z "$db_name" ]; then
    echo -e "${RED}错误: 数据库名不能为空${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  # 检查数据库是否存在
  if [ "$has_psql" = true ]; then
    exists=$(docker exec $pg_container psql -U $pg_superuser -tAc "SELECT 1 FROM pg_database WHERE datname='$db_name'")
  else
    exists=$(run_pg_command "$pg_container" "SELECT 1 FROM pg_database WHERE datname='$db_name'" "" "$pg_superuser")
  fi

  if ! [[ $exists == *"1"* ]]; then
    echo -e "${RED}错误: 数据库 $db_name 不存在${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  echo -e "${BLUE}在数据库 $db_name 中开启PGVector插件...${NC}"
  if [ "$has_psql" = true ]; then
    if ! docker exec $pg_container psql -U $pg_superuser -d $db_name -c "CREATE EXTENSION IF NOT EXISTS vector;" >/dev/null 2>&1; then
      echo -e "${RED}执行CREATE EXTENSION命令失败${NC}"
      read -p "按回车键继续..." temp
      return
    fi
    # 验证是否启用成功
    vector_enabled=$(docker exec $pg_container psql -U $pg_superuser -d $db_name -tAc "SELECT 1 FROM pg_extension WHERE extname='vector'")
    if [[ $vector_enabled == *"1"* ]]; then
      vector_version=$(docker exec $pg_container psql -U $pg_superuser -d $db_name -tAc "SELECT extversion FROM pg_extension WHERE extname='vector'")
      echo -e "${GREEN}PGVector 插件已成功启用 (版本: $vector_version)${NC}"
    else
      echo -e "${RED}PGVector 插件未能启用,请检查容器配置${NC}"
      read -p "按回车键继续..." temp
      return
    fi
  else
    if ! run_pg_command "$pg_container" "CREATE EXTENSION IF NOT EXISTS vector;" "$db_name" "$pg_superuser" >/dev/null 2>&1; then
      echo -e "${RED}执行CREATE EXTENSION命令失败${NC}"
      read -p "按回车键继续..." temp
      return
    fi
    # 验证是否启用成功
    vector_enabled=$(run_pg_command "$pg_container" "SELECT 1 FROM pg_extension WHERE extname='vector'" "$db_name" "$pg_superuser")
    if [[ $vector_enabled == *"1"* ]]; then
      vector_version=$(run_pg_command "$pg_container" "SELECT extversion FROM pg_extension WHERE extname='vector'" "$db_name" "$pg_superuser")
      echo -e "${GREEN}PGVector 插件已成功启用 (版本: $vector_version)${NC}"
    else
      echo -e "${RED}PGVector 插件未能启用,请检查容器配置${NC}"
      read -p "按回车键继续..." temp
      return
    fi
  fi

  echo -e "${GREEN}操作完成!${NC}"
  read -p "按回车键继续..." temp
}

# MySQL功能:创建用户和数据库
create_mysql_user_db() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "       创建MySQL用户和数据库"
  echo -e "========================================${NC}"
  echo ""

  # 获取基础名称
  read -p "请输入基础名称 (如输入lobe将创建lobe_user和lobe_db): " base_name
  if [ -z "$base_name" ]; then
    echo -e "${RED}错误: 名称不能为空${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  # 检查名称格式
  if ! [[ $base_name =~ ^[a-zA-Z0-9_]+$ ]]; then
    echo -e "${RED}错误: 名称只能包含字母、数字和下划线${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  user_name="${base_name}_user"
  db_name="${base_name}_db"

  # 检查用户名是否已存在
  if docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SELECT User FROM mysql.user WHERE User='$user_name';" 2>/dev/null | grep -q "$user_name"; then
    echo -e "${RED}错误: 用户 $user_name 已经存在${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  # 检查数据库是否已存在
  if docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SHOW DATABASES LIKE '$db_name';" 2>/dev/null | grep -q "$db_name"; then
    echo -e "${RED}错误: 数据库 $db_name 已经存在${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  # 获取密码
  read -s -p "请设置用户密码: " password
  echo ""
  read -s -p "确认密码: " password_confirm
  echo ""

  if [ "$password" != "$password_confirm" ]; then
    echo -e "${RED}错误: 两次输入的密码不匹配${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  # 检测MySQL版本
  mysql_version=$(docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SELECT VERSION();" 2>/dev/null | grep -v "VERSION()")
  mysql_major_version=$(echo $mysql_version | cut -d. -f1)

  echo -e "${BLUE}创建数据库 $db_name 并支持emoji (utf8mb4)...${NC}"
  if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "CREATE DATABASE $db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" >/dev/null 2>&1; then
    echo -e "${RED}创建数据库失败${NC}"
    read -p "按回车键继续..." temp
    return
  fi
  echo -e "${GREEN}成功${NC}"

  echo -e "${BLUE}创建用户 $user_name...${NC}"
  if [ "$mysql_major_version" -ge "8" ]; then
    # MySQL 8.0+ 语法
    if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "CREATE USER '$user_name'@'%' IDENTIFIED BY '$password';" >/dev/null 2>&1; then
      echo -e "${RED}创建用户失败${NC}"
      echo -e "${YELLOW}正在回滚,删除已创建的数据库...${NC}"
      docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "DROP DATABASE IF EXISTS $db_name;" >/dev/null 2>&1
      read -p "按回车键继续..." temp
      return
    fi
  else
    # MySQL 5.7 语法
    if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "CREATE USER '$user_name'@'%' IDENTIFIED BY '$password';" >/dev/null 2>&1; then
      echo -e "${RED}创建用户失败${NC}"
      echo -e "${YELLOW}正在回滚,删除已创建的数据库...${NC}"
      docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "DROP DATABASE IF EXISTS $db_name;" >/dev/null 2>&1
      read -p "按回车键继续..." temp
      return
    fi
  fi
  echo -e "${GREEN}成功${NC}"

  echo -e "${BLUE}授予用户 $user_name 对数据库 $db_name 的全部权限...${NC}"
  if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "GRANT ALL PRIVILEGES ON $db_name.* TO '$user_name'@'%';" >/dev/null 2>&1; then
    echo -e "${RED}授权失败${NC}"
    read -p "按回车键继续..." temp
    return
  fi

  echo -e "${BLUE}刷新权限...${NC}"
  if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "FLUSH PRIVILEGES;" >/dev/null 2>&1; then
    echo -e "${RED}刷新权限失败${NC}"
    read -p "按回车键继续..." temp
    return
  fi
  echo -e "${GREEN}成功${NC}"

  echo -e "${GREEN}操作完成!${NC}"
  read -p "按回车键继续..." temp
}

# MySQL功能:查询所有用户和数据库
list_mysql_users_dbs() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "      MySQL 用户和数据库列表"
  echo -e "========================================${NC}"
  echo ""

  echo -e "${YELLOW}数据库列表:${NC}"
  docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SELECT table_schema AS database_name, ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb FROM information_schema.tables GROUP BY table_schema ORDER BY table_schema;"
  echo ""

  echo -e "${YELLOW}用户列表:${NC}"
  docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SELECT User, Host FROM mysql.user ORDER BY User;"
  echo ""

  echo -e "${YELLOW}用户权限:${NC}"
  docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SELECT User, Host, Db, Select_priv, Insert_priv, Update_priv, Delete_priv FROM mysql.db ORDER BY User, Db;"

  read -p "按回车键继续..." temp
}

# MySQL功能:删除用户或数据库
delete_mysql_user_db() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "        删除MySQL用户或数据库"
  echo -e "========================================${NC}"
  echo ""

  echo -e "请选择要删除的对象:"
  echo -e "${GREEN}1) 用户${NC}"
  echo -e "${GREEN}2) 数据库${NC}"
  echo -e "${YELLOW}3) 返回上级菜单${NC}"
  echo ""
  read -p "请输入选择 [1-3]: " delete_choice

  case $delete_choice in
    1) # 删除用户
      echo -e "${YELLOW}当前MySQL用户列表:${NC}"
      docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SELECT User, Host FROM mysql.user WHERE User NOT IN ('root', 'mysql.sys', 'mysql.session', 'mysql.infoschema') ORDER BY User;"
      echo ""

      read -p "请输入要删除的用户名: " user_name
      if [ -z "$user_name" ]; then
        echo -e "${RED}错误: 用户名不能为空${NC}"
        read -p "按回车键继续..." temp
        return
      fi

      # 检查用户是否存在
      if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SELECT User FROM mysql.user WHERE User='$user_name';" 2>/dev/null | grep -q "$user_name"; then
        echo -e "${RED}错误: 用户 $user_name 不存在${NC}"
        read -p "按回车键继续..." temp
        return
      fi

      # 检查关联的数据库
      associated_db=$(docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SELECT Db FROM mysql.db WHERE User='$user_name' LIMIT 1;" 2>/dev/null | grep -v "Db")

      if [ -n "$associated_db" ]; then
        echo -e "${YELLOW}检测到关联的数据库: $associated_db${NC}"
        read -p "是否同时删除关联的数据库? (y/n): " delete_db

        if [[ $delete_db == [yY] || $delete_db == [yY][eE][sS] ]]; then
          echo -e "${BLUE}删除数据库 $associated_db...${NC}"
          if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "DROP DATABASE $associated_db;" >/dev/null 2>&1; then
            echo -e "${RED}删除数据库失败${NC}"
            read -p "按回车键继续..." temp
            return
          fi
          echo -e "${GREEN}成功${NC}"
        fi
      fi

      echo -e "${BLUE}删除用户 $user_name...${NC}"
      if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "DROP USER '$user_name'@'%';" >/dev/null 2>&1; then
        echo -e "${RED}删除用户失败${NC}"
        read -p "按回车键继续..." temp
        return
      fi
      echo -e "${GREEN}成功${NC}"

      echo -e "${BLUE}刷新权限...${NC}"
      docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "FLUSH PRIVILEGES;" >/dev/null 2>&1
      echo -e "${GREEN}成功${NC}"
      ;;

    2) # 删除数据库
      echo -e "${YELLOW}当前MySQL数据库列表:${NC}"
      docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SHOW DATABASES WHERE \`Database\` NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys');"
      echo ""

      read -p "请输入要删除的数据库名: " db_name
      if [ -z "$db_name" ]; then
        echo -e "${RED}错误: 数据库名不能为空${NC}"
        read -p "按回车键继续..." temp
        return
      fi

      # 检查数据库是否存在
      if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SHOW DATABASES LIKE '$db_name';" 2>/dev/null | grep -q "$db_name"; then
        echo -e "${RED}错误: 数据库 $db_name 不存在${NC}"
        read -p "按回车键继续..." temp
        return
      fi

      # 检查拥有该数据库权限的用户
      users_with_access=$(docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "SELECT User FROM mysql.db WHERE Db='$db_name';" 2>/dev/null | grep -v "User")

      if [ -n "$users_with_access" ]; then
        echo -e "${YELLOW}检测到以下用户拥有该数据库的权限:${NC}"
        echo "$users_with_access"
        read -p "是否同时删除这些用户? (y/n): " delete_users

        if [[ $delete_users == [yY] || $delete_users == [yY][eE][sS] ]]; then
          # 先删数据库再删用户
          delete_users_later=true
        fi
      fi

      echo -e "${BLUE}删除数据库 $db_name...${NC}"
      if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "DROP DATABASE $db_name;" >/dev/null 2>&1; then
        echo -e "${RED}删除数据库失败${NC}"
        read -p "按回车键继续..." temp
        return
      fi
      echo -e "${GREEN}成功${NC}"

      if [ "$delete_users_later" = true ]; then
        for user in $users_with_access; do
          echo -e "${BLUE}删除用户 $user...${NC}"
          if ! docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "DROP USER '$user'@'%';" >/dev/null 2>&1; then
            echo -e "${RED}删除用户 $user 失败${NC}"
          else
            echo -e "${GREEN}成功${NC}"
          fi
        done

        echo -e "${BLUE}刷新权限...${NC}"
        docker exec $mysql_container mysql -u root -p"$mysql_root_password" -e "FLUSH PRIVILEGES;" >/dev/null 2>&1
        echo -e "${GREEN}成功${NC}"
      fi
      ;;

    3) return ;;
    *) echo -e "${RED}无效选择,请重试${NC}" 
       sleep 1
       delete_mysql_user_db
       ;;
  esac

  echo -e "${GREEN}操作完成!${NC}"
  read -p "按回车键继续..." temp
}

# Redis功能:查看Redis信息
show_redis_info() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "           Redis 服务器信息"
  echo -e "========================================${NC}"
  echo ""

  echo -e "${YELLOW}Redis服务器信息:${NC}"
  if [ -n "$redis_password" ]; then
    docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning info server | grep -v "#"
  else
    docker exec $redis_container redis-cli info server | grep -v "#"
  fi
  echo ""

  echo -e "${YELLOW}Redis客户端连接信息:${NC}"
  if [ -n "$redis_password" ]; then
    docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning info clients | grep -v "#"
  else
    docker exec $redis_container redis-cli info clients | grep -v "#"
  fi
  echo ""

  echo -e "${YELLOW}Redis统计信息:${NC}"
  if [ -n "$redis_password" ]; then
    docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning info stats | grep -v "#" | head -15
  else
    docker exec $redis_container redis-cli info stats | grep -v "#" | head -15
  fi
  echo ""

  echo -e "${YELLOW}Redis持久化信息:${NC}"
  if [ -n "$redis_password" ]; then
    docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning info persistence | grep -v "#"
  else
    docker exec $redis_container redis-cli info persistence | grep -v "#"
  fi

  read -p "按回车键继续..." temp
}

# Redis功能:查看内存使用
show_redis_memory() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "           Redis 内存使用情况"
  echo -e "========================================${NC}"
  echo ""

  echo -e "${YELLOW}内存使用概览:${NC}"
  if [ -n "$redis_password" ]; then
    docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning info memory | grep -v "#"
  else
    docker exec $redis_container redis-cli info memory | grep -v "#"
  fi
  echo ""

  echo -e "${YELLOW}内存使用详情:${NC}"
  if [ -n "$redis_password" ]; then
    docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning memory stats | head -20
  else
    docker exec $redis_container redis-cli memory stats | head -20
  fi
  echo ""

  echo -e "${YELLOW}数据库键值统计:${NC}"
  if [ -n "$redis_password" ]; then
    docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning info keyspace | grep -v "#"
  else
    docker exec $redis_container redis-cli info keyspace | grep -v "#"
  fi

  read -p "按回车键继续..." temp
}

# Redis功能:查看键值统计
show_redis_keys() {
  if [ "$CLEAR_SCREEN" = true ]; then
    clear
  else
    echo ""
    echo -e "${BLUE}----------------------------------------${NC}"
    echo ""
  fi

  echo -e "${CYAN}========================================"
  echo -e "           Redis 键值统计"
  echo -e "========================================${NC}"
  echo ""

  echo -e "${YELLOW}数据库键值统计:${NC}"
  if [ -n "$redis_password" ]; then
    docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning info keyspace | grep -v "#"
  else
    docker exec $redis_container redis-cli info keyspace | grep -v "#"
  fi
  echo ""

  echo -e "${YELLOW}键值类型分布:${NC}"
  if [ -n "$redis_password" ]; then
    # 获取所有数据库
    dbs=$(docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning info keyspace | grep -v "#" | grep "^db" | cut -d: -f1)

    if [ -z "$dbs" ]; then
      echo -e "${YELLOW}没有找到任何数据库或键值${NC}"
    else
      for db in $dbs; do
        echo -e "${BLUE}数据库 $db:${NC}"
        # 选择数据库并统计键类型
        docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning -n ${db#db} info keyspace | grep -v "#"
        # 使用 SCAN 命令统计部分键的类型(避免 KEYS 命令对大数据库的影响)
        echo -e "${GREEN}键类型样本统计 (前100个键):${NC}"
        docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning -n ${db#db} --scan --count 100 | while read -r key; do
          type=$(docker exec $redis_container redis-cli -a "$redis_password" --no-auth-warning -n ${db#db} type "$key")
          echo "键: $key -> 类型: $type"
        done | sort | uniq -c | sort -nr
      done
    fi
  else
    dbs=$(docker exec $redis_container redis-cli info keyspace | grep -v "#" | grep "^db" | cut -d: -f1)

    if [ -z "$dbs" ]; then
      echo -e "${YELLOW}没有找到任何数据库或键值${NC}"
    else
      for db in $dbs; do
        echo -e "${BLUE}数据库 $db:${NC}"
        docker exec $redis_container redis-cli -n ${db#db} info keyspace | grep -v "#"
        echo -e "${GREEN}键类型样本统计 (前100个键):${NC}"
        docker exec $redis_container redis-cli -n ${db#db} --scan --count 100 | while read -r key; do
          type=$(docker exec $redis_container redis-cli -n ${db#db} type "$key")
          echo "键: $key -> 类型: $type"
        done | sort | uniq -c | sort -nr
      done
    fi
  fi

  read -p "按回车键继续..." temp
}

# 主循环
main() {
  check_docker
  while true; do
    find_containers
    show_main_menu

    if [ -z "$main_choice" ] || ! [[ "$main_choice" =~ ^[0-9]+$ ]]; then
      echo -e "${RED}无效选择,请重试${NC}"
      sleep 1
      continue
    fi

    if [ "$main_choice" -eq "$exit_option" ]; then
      echo -e "${GREEN}感谢使用容器数据库管理工具,再见!${NC}"
      exit 0
    elif [ "$main_choice" -eq "$settings_option" ]; then
      show_settings_menu
    elif [ "$main_choice" -le "$pg_count" ] && [ "$main_choice" -ge 1 ]; then
      show_postgres_menu
    elif [ "$main_choice" -eq "$mysql_option" ] && [ -n "$mysql_container" ]; then
      show_mysql_menu
    elif [ "$main_choice" -eq "$redis_option" ] && [ -n "$redis_container" ]; then
      show_redis_menu
    else
      echo -e "${RED}无效选择,请重试${NC}"
      sleep 1
    fi
  done
}

# 启动脚本
main
南风大叔
这个人很懒,什么都没有留下~

0

  1. This post has no comment yet

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

使用Docker Compose部署PostgreSQL
使用Docker Compose部署PostgreSQL
使用Docker Compose部署Zitadel
使用Docker Compose部署Zitadel
使用Docker Compose部署LobeChat数据库版
使用Docker Compose部署LobeChat数据库版
阿里云安装Docker和Tailscale及遇到的问题
阿里云安装Docker和Tailscale及遇到的问题
Grafana & Prometheus
Grafana & Prometheus
Prometheus: mysqld_exporter
Prometheus: mysqld_exporter
© 2025 南风大叔