#!/bin/bash # ============================================================================= # New-API 一键部署脚本 # 用于快速部署更新后的 New-API 到生产服务器 # ============================================================================= set -e # 遇到错误立即退出 # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 日志函数 log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # 检查命令是否存在 check_command() { if ! command -v $1 &> /dev/null; then log_error "$1 未安装,请先安装" exit 1 fi } # 检查环境 check_environment() { log_info "检查部署环境..." check_command "git" check_command "docker" check_command "docker-compose" # 检查Docker服务状态 if ! docker info &> /dev/null; then log_error "Docker 服务未运行,请启动 Docker" exit 1 fi log_success "环境检查通过" } # 备份当前配置 backup_current() { log_info "备份当前配置..." BACKUP_DIR="backups/$(date +%Y%m%d-%H%M%S)" mkdir -p "$BACKUP_DIR" # 备份配置文件 if [ -f "docker-compose-custom.yml" ]; then cp docker-compose-custom.yml "$BACKUP_DIR/" fi if [ -f ".env" ]; then cp .env "$BACKUP_DIR/" fi # 备份数据库(如果本地) if docker ps | grep -q "mysql\|postgres"; then log_info "检测到数据库容器,建议手动备份数据库" fi log_success "备份完成:$BACKUP_DIR" } # 拉取最新代码 pull_latest_code() { log_info "拉取最新代码..." # 检查是否有未提交的更改 if ! git diff --quiet || ! git diff --cached --quiet; then log_warning "检测到未提交的更改" read -p "是否要stash这些更改? (y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then git stash log_info "已stash本地更改" fi fi git pull origin main log_success "代码更新完成" } # 构建和部署 build_and_deploy() { log_info "开始构建和部署..." # 选择配置文件 COMPOSE_FILE="" if [ -f "docker-compose-custom.yml" ]; then COMPOSE_FILE="docker-compose-custom.yml" elif [ -f "docker-compose-tq.yml" ]; then COMPOSE_FILE="docker-compose-tq.yml" else COMPOSE_FILE="docker-compose.yml" fi log_info "使用配置文件: $COMPOSE_FILE" # 停止现有服务 log_info "停止现有服务..." docker-compose -f "$COMPOSE_FILE" down # 构建新镜像 log_info "构建新镜像..." docker-compose -f "$COMPOSE_FILE" build --no-cache # 启动服务 log_info "启动服务..." docker-compose -f "$COMPOSE_FILE" up -d log_success "部署完成" } # 健康检查 health_check() { log_info "执行健康检查..." # 等待服务启动 sleep 10 # 检查容器状态 if docker-compose ps | grep -q "Exit\|unhealthy"; then log_error "检测到容器异常" docker-compose logs --tail=50 exit 1 fi # 检查HTTP响应 local max_attempts=30 local attempt=1 while [ $attempt -le $max_attempts ]; do if curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 | grep -q "200\|302"; then log_success "服务健康检查通过" return 0 fi log_info "等待服务启动... ($attempt/$max_attempts)" sleep 5 attempt=$((attempt + 1)) done log_error "健康检查失败" docker-compose logs --tail=50 exit 1 } # 显示部署信息 show_deploy_info() { echo log_success "🎉 部署成功完成!" echo echo "=================== 部署信息 ===================" echo "部署时间: $(date)" echo "Git 提交: $(git rev-parse --short HEAD)" echo "服务地址: http://localhost:3000" echo "==============================================" echo echo "🔧 常用命令:" echo " 查看日志: docker-compose logs -f" echo " 重启服务: docker-compose restart" echo " 停止服务: docker-compose down" echo " 查看状态: docker-compose ps" echo echo "📖 更多信息请查看: temp/DEPLOY_GUIDE.md" } # 主函数 main() { echo "===============================================" echo "🚀 New-API 自动部署脚本" echo "===============================================" # 检查是否在正确目录 if [ ! -f "main.go" ] || [ ! -d "web" ]; then log_error "请在 New-API 项目根目录运行此脚本" exit 1 fi # 确认部署 read -p "确认要部署到生产环境吗? (y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then log_info "部署已取消" exit 0 fi # 执行部署步骤 check_environment backup_current pull_latest_code build_and_deploy health_check show_deploy_info } # 错误处理 trap 'log_error "部署过程中发生错误,请检查上面的日志信息"' ERR # 执行主函数 main "$@"