251 lines
6.6 KiB
Bash
Executable File
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 |