easyai/start.sh
2026-03-09 16:56:15 +08:00

297 lines
11 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# EasyAI 一键部署脚本
# 支持交互式问答配置,兼容 IP 与域名两种访问方式
# 一行命令: git clone https://git.51easyai.com/wangbo/easyai && cd easyai && chmod +x ./start.sh && ./start.sh
set -e
# 仅配置模式验证用DEPLOY_DRY_RUN=1 只生成配置文件,不执行 Docker 安装和启动
DEPLOY_DRY_RUN="${DEPLOY_DRY_RUN:-0}"
# ==================== 项目初始化 ====================
init_project_dir() {
local script_source
script_source="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
if [ -f "${script_source}/docker-compose.yml" ]; then
echo "📁 项目目录: ${script_source}"
cd "$script_source"
return 0
fi
echo "❌ 未找到 docker-compose.yml请在 easyai 项目目录下运行 start.sh"
echo " 启动命令: git clone https://git.51easyai.com/wangbo/easyai && cd easyai && chmod +x ./start.sh && ./start.sh"
exit 1
}
# ==================== 配置变量(支持环境变量非交互模式) ====================
DEPLOY_MODE="" # ip | domain
DEPLOY_IP=""
DEPLOY_DOMAIN=""
DEPLOY_HTTPS=false
prompt_or_env() {
local var_name=$1
local prompt_text=$2
local env_name=$3
local default=$4
if [ -n "${!env_name}" ]; then
eval "$var_name=\"${!env_name}\""
return
fi
if [ -n "$default" ]; then
read -r -p "${prompt_text} [$default]: " input
eval "$var_name=\"${input:-$default}\""
else
read -r -p "${prompt_text}: " input
eval "$var_name=\"$input\""
fi
}
run_deploy_questions() {
echo ""
echo "================================"
echo " EasyAI 部署配置(问答模式)"
echo "================================"
echo ""
# 非交互模式环境变量已完整设置则直接使用CI/自动化部署)
if [ -n "$DEPLOY_ACCESS" ]; then
if [ "$DEPLOY_ACCESS" = "ip" ] && [ -n "$DEPLOY_IP" ]; then
DEPLOY_MODE="ip"
echo "使用环境变量: IP 模式, IP=$DEPLOY_IP"
return
fi
if [ "$DEPLOY_ACCESS" = "domain" ] && [ -n "$DEPLOY_DOMAIN" ]; then
DEPLOY_MODE="domain"
DEPLOY_HTTPS="${DEPLOY_HTTPS_INPUT:-false}"
echo "使用环境变量: 域名模式, 域名=$DEPLOY_DOMAIN"
return
fi
fi
# 1. IP 或域名访问
if [ -z "$DEPLOY_ACCESS" ]; then
echo "1. 通过 IP 地址还是域名访问?"
echo " [1] IP 地址(需开放 3001、3002、3003 端口)"
echo " [2] 域名"
read -r -p "请选择 [1/2]: " choice
case "$choice" in
1) DEPLOY_MODE="ip" ;;
2) DEPLOY_MODE="domain" ;;
*) echo "❌ 无效选择"; exit 1 ;;
esac
else
DEPLOY_MODE="$DEPLOY_ACCESS"
fi
if [ "$DEPLOY_MODE" = "ip" ]; then
# 2. 输入服务器 IP
prompt_or_env DEPLOY_IP "2. 请输入服务器 IP 地址" "DEPLOY_IP" ""
[ -z "$DEPLOY_IP" ] && { echo "❌ IP 不能为空"; exit 1; }
echo " 请确保防火墙已放行 3001、3002、3003 端口"
else
# 3. 输入域名
prompt_or_env DEPLOY_DOMAIN "3. 请输入域名(不含 https:// 前缀,如 51easyai.com" "DEPLOY_DOMAIN" ""
[ -z "$DEPLOY_DOMAIN" ] && { echo "❌ 域名不能为空"; exit 1; }
# 3.1 是否启用 HTTPS
if [ -n "$DEPLOY_HTTPS_INPUT" ]; then
DEPLOY_HTTPS=$DEPLOY_HTTPS_INPUT
else
read -r -p "3.1 是否启用 HTTPS[y/N]: " https_choice
DEPLOY_HTTPS=false
[[ "$https_choice" =~ ^[yY] ]] && DEPLOY_HTTPS=true
fi
[ "$DEPLOY_HTTPS" = true ] && echo " 启用 HTTPS 需确保防火墙已放行 80、443 端口"
fi
}
# ==================== 生成配置文件 ====================
setup_env_files() {
echo ""
echo "📝 配置环境文件..."
# 6. 复制 .env.tools 和 .env.ASG
[ ! -f .env.tools ] && cp .env.tools.sample .env.tools && echo " ✓ .env.tools"
[ ! -f .env.ASG ] && cp .env.ASG.sample .env.ASG && echo " ✓ .env.ASG"
# 4/5. 配置 .env
if [ ! -f .env ]; then
cp .env.sample .env
fi
if [ "$DEPLOY_MODE" = "ip" ]; then
# IP 模式
sed -i.bak "s|^NUXT_PUBLIC_BASE_APIURL=.*|NUXT_PUBLIC_BASE_APIURL=http://${DEPLOY_IP}:3001|" .env
sed -i.bak "s|^NUXT_PUBLIC_BASE_SOCKETURL=.*|NUXT_PUBLIC_BASE_SOCKETURL=ws://${DEPLOY_IP}:3002|" .env
sed -i.bak "s|^NUXT_PUBLIC_SG_APIURL=.*|NUXT_PUBLIC_SG_APIURL=http://${DEPLOY_IP}:3003|" .env
echo " ✓ .env 已配置为 IP 模式 (${DEPLOY_IP})"
else
# 域名模式
sed -i.bak "s|^NUXT_PUBLIC_BASE_APIURL=.*|NUXT_PUBLIC_BASE_APIURL=/api|" .env
sed -i.bak "s|^NUXT_PUBLIC_BASE_SOCKETURL=.*|NUXT_PUBLIC_BASE_SOCKETURL=wss://${DEPLOY_DOMAIN}/socket.io|" .env
sed -i.bak "s|^NUXT_PUBLIC_SG_APIURL=.*|NUXT_PUBLIC_SG_APIURL=/asg-api|" .env
echo " ✓ .env 已配置为域名模式 (${DEPLOY_DOMAIN})"
# 7. Nginx 配置(域名模式)
PROXY_CONF="${DEPLOY_DOMAIN}.conf"
if [ ! -f "$PROXY_CONF" ]; then
sed "s/51easyai.com/${DEPLOY_DOMAIN}/g" easyai-proxy.conf.sample > "$PROXY_CONF"
echo " ✓ Nginx 配置已生成: $PROXY_CONF"
fi
fi
rm -f .env.bak
}
# ==================== Docker 安装(复用原 start.sh 逻辑) ====================
install_docker() {
echo ""
echo "================================"
echo " Docker 安装与检查"
echo "================================"
if [ -f /etc/os-release ]; then
. /etc/os-release
case "${ID:-}" in
ubuntu|debian) OS_FAMILY="Ubuntu" ;;
centos|rhel|fedora) OS_FAMILY="CentOS" ;;
*) OS_FAMILY="${ID:-Unknown}" ;;
esac
else
OS_FAMILY=$(hostnamectl 2>/dev/null | grep "Operating System" | awk '{print $3}' || echo "Unknown")
fi
OS_VERSION_ID=$(grep -oP '(?<=^VERSION_ID=")[0-9.]+' /etc/os-release 2>/dev/null | cut -d'.' -f1 || echo "0")
OS_CODENAME=""
[[ "$OS_FAMILY" == "Ubuntu" ]] && OS_CODENAME=$(lsb_release -cs 2>/dev/null || (grep VERSION_CODENAME /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d '"'))
UBUNTU_DOCKER_MIRROR_URL="https://mirrors.ustc.edu.cn/docker-ce"
UBUNTU_DOCKER_GPG_URL="https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg"
CENTOS_DOCKER_MIRROR_URL="https://mirrors.tuna.tsinghua.edu.cn/docker-ce"
check_network() {
if curl -sSf --connect-timeout 5 https://download.docker.com/ &>/dev/null; then
echo "✅ 网络连接正常"
return 0
fi
echo "⚠️ 将使用国内镜像源"
return 0
}
check_network
if command -v docker &>/dev/null; then
echo "✅ Docker 已安装"
else
if [[ "$OS_FAMILY" == "Ubuntu" ]]; then
sudo apt update -y
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL "$UBUNTU_DOCKER_GPG_URL" | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg 2>/dev/null || \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] $UBUNTU_DOCKER_MIRROR_URL/linux/ubuntu $OS_CODENAME stable" | sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
sudo apt-get update -y
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
elif [[ "$OS_FAMILY" == "CentOS" ]]; then
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo sed -i "s+https://download.docker.com+$CENTOS_DOCKER_MIRROR_URL+g" /etc/yum.repos.d/docker-ce.repo
[[ "$OS_VERSION_ID" -ge "8" ]] && sudo yum module disable -y container-tools 2>/dev/null || true
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
else
echo "❌ 不支持的操作系统: $OS_FAMILY"
exit 1
fi
sudo systemctl enable docker
sudo systemctl start docker
getent group docker | grep -qw "$USER" || sudo usermod -aG docker "$USER"
fi
if docker compose version &>/dev/null; then
echo "✅ Docker Compose 已就绪"
elif command -v docker-compose &>/dev/null; then
echo "✅ Docker Compose (兼容模式) 已就绪"
else
echo "❌ 请安装 docker-compose-plugin"
exit 1
fi
}
# ==================== 启动服务 ====================
start_services() {
echo ""
echo "🚀 启动 EasyAI 服务..."
if docker compose version &>/dev/null; then
sudo docker compose pull && sudo docker compose up -d
else
sudo docker-compose pull && sudo docker-compose up -d
fi
echo "🎉 EasyAI 应用启动成功"
}
# ==================== 执行 HTTPS 配置 ====================
run_https_setup() {
if [ "$DEPLOY_HTTPS" = true ] && [ -n "$DEPLOY_DOMAIN" ]; then
echo ""
echo "🔒 执行 HTTPS 配置(请确保服务器已放行 80、443 端口)..."
if [ -f "./https.sh" ]; then
# https.sh 依赖 easyai-proxy.conf需使用生成的域名配置文件
export EASYAI_PROXY_CONF="${DEPLOY_DOMAIN}.conf"
bash ./https.sh
else
echo "⚠️ 未找到 https.sh请手动配置 HTTPS"
fi
fi
}
# ==================== 主流程 ====================
main() {
init_project_dir
# 检查是否已有 .env 且非强制重新配置
if [ -f .env ] && [ -z "$DEPLOY_FORCE_RECONFIG" ] && [ -z "$DEPLOY_ACCESS" ]; then
echo "📁 检测到已有 .env 配置"
read -r -p "是否重新配置部署方式?[y/N]: " reconfigure
if [[ ! "$reconfigure" =~ ^[yY] ]]; then
echo "⏭️ 使用现有配置继续..."
DEPLOY_MODE="skip"
fi
fi
if [ "$DEPLOY_MODE" != "skip" ]; then
run_deploy_questions
fi
if [ "$DEPLOY_MODE" != "skip" ]; then
setup_env_files
else
[ ! -f .env.tools ] && cp .env.tools.sample .env.tools
[ ! -f .env.ASG ] && cp .env.ASG.sample .env.ASG
fi
if [ "$DEPLOY_DRY_RUN" = "1" ]; then
echo ""
echo "⚠️ dry-run 模式:跳过 Docker 安装和服务启动"
echo " 配置文件已生成,可直接运行 ./start.sh 完成部署"
else
install_docker
start_services
run_https_setup
fi
echo ""
echo "================================"
echo " 部署完成"
echo "================================"
if [ "$DEPLOY_MODE" = "ip" ] && [ -n "$DEPLOY_IP" ]; then
echo "访问地址: http://${DEPLOY_IP}:3010"
elif [ "$DEPLOY_MODE" = "domain" ] && [ -n "$DEPLOY_DOMAIN" ]; then
echo "访问地址: http://${DEPLOY_DOMAIN} (配置 Nginx 后)"
[ "$DEPLOY_HTTPS" = true ] && echo "HTTPS 已启用"
fi
echo ""
}
main "$@"