Files
2025-12-02 20:11:38 +08:00

251 lines
6.6 KiB
Bash
Executable File

#!/bin/bash
# 部署脚本 - 自动化部署流程
set -e # 遇到错误立即退出
echo "🚀 开始部署 OmniVerse Website..."
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 检查 Node.js 版本
check_node_version() {
echo "📋 检查 Node.js 版本..."
NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1)
if [ "$NODE_VERSION" -lt 18 ]; then
echo -e "${RED}❌ Node.js 版本必须 >= 18.0.0${NC}"
exit 1
fi
echo -e "${GREEN}✅ Node.js 版本检查通过${NC}"
}
# 检查并处理端口冲突
check_and_handle_ports() {
echo "🔍 检查端口占用情况..."
PORTS_TO_CHECK=(5173 3001)
CONFLICTS_FOUND=false
for PORT in "${PORTS_TO_CHECK[@]}"; do
PIDS=$(lsof -ti:$PORT 2>/dev/null)
if [ ! -z "$PIDS" ]; then
CONFLICTS_FOUND=true
echo -e "${YELLOW}⚠️ 端口 $PORT 被占用${NC}"
# 显示占用进程信息
for PID in $PIDS; do
PROCESS_INFO=$(ps -p $PID -o comm= 2>/dev/null || echo "未知进程")
echo " - PID: $PID, 进程: $PROCESS_INFO"
done
fi
done
if [ "$CONFLICTS_FOUND" = true ]; then
echo ""
echo -e "${YELLOW}发现端口冲突。需要停止这些进程才能继续部署。${NC}"
echo ""
echo "选择处理方式:"
echo "1) 自动停止冲突进程 (推荐)"
echo "2) 手动处理后继续"
echo "3) 退出部署"
read -p "请输入选项 (1/2/3): " port_choice
case $port_choice in
1)
echo "🛑 停止冲突进程..."
for PORT in "${PORTS_TO_CHECK[@]}"; do
PIDS=$(lsof -ti:$PORT 2>/dev/null)
if [ ! -z "$PIDS" ]; then
for PID in $PIDS; do
echo " 停止 PID $PID (端口 $PORT)..."
kill -15 $PID 2>/dev/null || kill -9 $PID 2>/dev/null
done
fi
done
# 等待进程完全停止
sleep 2
# 再次检查
STILL_OCCUPIED=false
for PORT in "${PORTS_TO_CHECK[@]}"; do
if lsof -ti:$PORT &>/dev/null; then
STILL_OCCUPIED=true
echo -e "${RED}❌ 端口 $PORT 仍被占用${NC}"
fi
done
if [ "$STILL_OCCUPIED" = true ]; then
echo -e "${RED}❌ 无法自动停止所有冲突进程,请手动处理${NC}"
exit 1
fi
echo -e "${GREEN}✅ 端口冲突已解决${NC}"
;;
2)
echo -e "${YELLOW}请手动停止冲突进程后按回车继续...${NC}"
read -p ""
# 再次检查
STILL_OCCUPIED=false
for PORT in "${PORTS_TO_CHECK[@]}"; do
if lsof -ti:$PORT &>/dev/null; then
STILL_OCCUPIED=true
echo -e "${RED}❌ 端口 $PORT 仍被占用${NC}"
fi
done
if [ "$STILL_OCCUPIED" = true ]; then
echo -e "${RED}❌ 仍存在端口冲突,部署终止${NC}"
exit 1
fi
;;
3)
echo -e "${YELLOW}部署已取消${NC}"
exit 0
;;
*)
echo -e "${RED}❌ 无效选项,部署终止${NC}"
exit 1
;;
esac
else
echo -e "${GREEN}✅ 端口检查通过,无冲突${NC}"
fi
}
# 拉取最新代码
pull_latest_code() {
echo "📥 拉取最新代码..."
git pull origin main
echo -e "${GREEN}✅ 代码更新完成${NC}"
}
# 安装依赖
install_dependencies() {
echo "📦 安装依赖..."
# 检查使用哪个包管理器
if [ -f "pnpm-lock.yaml" ]; then
echo "使用 pnpm 安装..."
if ! command -v pnpm &> /dev/null; then
echo "安装 pnpm..."
npm install -g pnpm
fi
pnpm install --frozen-lockfile
elif [ -f "yarn.lock" ]; then
echo "使用 yarn 安装..."
yarn install --frozen-lockfile
else
echo "使用 npm 安装..."
npm ci
fi
echo -e "${GREEN}✅ 依赖安装完成${NC}"
}
# 构建项目
build_project() {
echo "🔨 构建项目..."
npm run build
echo -e "${GREEN}✅ 构建完成${NC}"
}
# 使用 Docker 部署
deploy_with_docker() {
echo "🐳 使用 Docker 部署..."
# 检查 Docker 是否安装
if ! command -v docker &> /dev/null; then
echo -e "${YELLOW}⚠️ Docker 未安装,跳过 Docker 部署${NC}"
return
fi
# 停止旧容器
docker-compose down || true
# 构建并启动新容器
docker-compose up -d --build
echo -e "${GREEN}✅ Docker 部署完成${NC}"
}
# 使用 PM2 部署
deploy_with_pm2() {
echo "🔄 使用 PM2 部署..."
# 检查 PM2 是否安装
if ! command -v pm2 &> /dev/null; then
echo "安装 PM2..."
npm install -g pm2
fi
# 停止旧进程
pm2 stop omniverse-website || true
pm2 delete omniverse-website || true
# 启动新进程
pm2 start npm --name "omniverse-website" -- run preview -- --host 0.0.0.0
# 保存 PM2 配置
pm2 save
pm2 startup || true
echo -e "${GREEN}✅ PM2 部署完成${NC}"
}
# 健康检查
health_check() {
echo "🏥 执行健康检查..."
sleep 5
if curl -f http://localhost:5173 &> /dev/null; then
echo -e "${GREEN}✅ 服务运行正常${NC}"
else
echo -e "${RED}❌ 服务启动失败${NC}"
exit 1
fi
}
# 主流程
main() {
echo "选择部署方式:"
echo "1) Docker 部署(推荐)"
echo "2) PM2 部署"
echo "3) 仅构建"
read -p "请输入选项 (1/2/3): " choice
check_node_version
pull_latest_code
install_dependencies
build_project
case $choice in
1)
deploy_with_docker
;;
2)
deploy_with_pm2
;;
3)
echo -e "${GREEN}✅ 构建完成,请手动部署${NC}"
;;
*)
echo -e "${RED}❌ 无效选项${NC}"
exit 1
;;
esac
if [ "$choice" != "3" ]; then
health_check
fi
echo -e "${GREEN}🎉 部署成功完成!${NC}"
}
# 运行主流程
main