#!/bin/bash # Flask 提示词大师 - 自动化部署脚本 # 支持测试环境和生产环境部署 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" } # 显示帮助信息 show_help() { echo "Flask 提示词大师 - 自动化部署脚本" echo "" echo "用法: $0 [选项]" echo "" echo "选项:" echo " -e, --environment ENV 部署环境 (test|production)" echo " -s, --server SERVER 服务器地址" echo " -u, --user USER 用户名" echo " -k, --key KEY_PATH SSH密钥路径" echo " -b, --branch BRANCH 代码分支 (默认: main)" echo " -c, --config CONFIG 配置文件路径" echo " -h, --help 显示此帮助信息" echo "" echo "示例:" echo " $0 -e test -s test.example.com -u deploy -k ~/.ssh/id_rsa" echo " $0 -e production -s prod.example.com -u deploy -k ~/.ssh/id_rsa" } # 解析命令行参数 parse_args() { ENVIRONMENT="" SERVER="" USER="" KEY_PATH="" BRANCH="main" CONFIG_PATH="" while [[ $# -gt 0 ]]; do case $1 in -e|--environment) ENVIRONMENT="$2" shift 2 ;; -s|--server) SERVER="$2" shift 2 ;; -u|--user) USER="$2" shift 2 ;; -k|--key) KEY_PATH="$2" shift 2 ;; -b|--branch) BRANCH="$2" shift 2 ;; -c|--config) CONFIG_PATH="$2" shift 2 ;; -h|--help) show_help exit 0 ;; *) log_error "未知参数: $1" show_help exit 1 ;; esac done # 验证必需参数 if [[ -z "$ENVIRONMENT" ]]; then log_error "请指定部署环境 (-e 或 --environment)" exit 1 fi if [[ -z "$SERVER" ]]; then log_error "请指定服务器地址 (-s 或 --server)" exit 1 fi if [[ -z "$USER" ]]; then log_error "请指定用户名 (-u 或 --user)" exit 1 fi } # 检查依赖 check_dependencies() { log_info "检查部署依赖..." # 检查SSH if ! command -v ssh &> /dev/null; then log_error "SSH 未安装" exit 1 fi # 检查Docker if ! command -v docker &> /dev/null; then log_warning "Docker 未安装,将使用传统部署方式" fi # 检查Git if ! command -v git &> /dev/null; then log_error "Git 未安装" exit 1 fi log_success "依赖检查完成" } # 准备部署包 prepare_deployment() { log_info "准备部署包..." # 创建临时目录 TEMP_DIR=$(mktemp -d) DEPLOY_DIR="$TEMP_DIR/flask-prompt-master" # 复制项目文件 cp -r . "$DEPLOY_DIR" # 清理不需要的文件 cd "$DEPLOY_DIR" rm -rf .git .github .venv __pycache__ *.pyc .pytest_cache # 创建部署包 tar -czf "../flask-prompt-master-$ENVIRONMENT.tar.gz" . log_success "部署包准备完成: flask-prompt-master-$ENVIRONMENT.tar.gz" } # 部署到服务器 deploy_to_server() { log_info "开始部署到服务器: $SERVER" # 构建SSH命令 SSH_CMD="ssh" if [[ -n "$KEY_PATH" ]]; then SSH_CMD="$SSH_CMD -i $KEY_PATH" fi SSH_CMD="$SSH_CMD -o StrictHostKeyChecking=no $USER@$SERVER" # 创建远程部署脚本 cat > remote_deploy.sh << 'EOF' #!/bin/bash set -e # 远程部署脚本 ENVIRONMENT="$1" DEPLOY_PATH="/opt/flask-prompt-master" BACKUP_PATH="/opt/backups/flask-prompt-master" echo "开始远程部署..." # 创建备份 if [ -d "$DEPLOY_PATH" ]; then echo "创建备份..." mkdir -p "$BACKUP_PATH" cp -r "$DEPLOY_PATH" "$BACKUP_PATH/$(date +%Y%m%d_%H%M%S)" fi # 停止现有服务 echo "停止现有服务..." if systemctl is-active --quiet flask-prompt-master; then systemctl stop flask-prompt-master fi # 清理旧文件 echo "清理旧文件..." rm -rf "$DEPLOY_PATH" # 解压新文件 echo "解压新文件..." mkdir -p "$DEPLOY_PATH" tar -xzf flask-prompt-master.tar.gz -C "$DEPLOY_PATH" # 设置权限 echo "设置权限..." chown -R www-data:www-data "$DEPLOY_PATH" chmod +x "$DEPLOY_PATH"/*.sh # 安装依赖 echo "安装依赖..." cd "$DEPLOY_PATH" python3 -m venv venv source venv/bin/activate pip install -r requirements.txt # 配置环境 echo "配置环境..." if [ "$ENVIRONMENT" = "production" ]; then cp env.production .env else cp env.test .env fi # 数据库迁移 echo "执行数据库迁移..." flask db upgrade # 启动服务 echo "启动服务..." systemctl start flask-prompt-master systemctl enable flask-prompt-master # 部署监控系统 echo "部署监控系统..." if [ -f "simple_monitor.py" ]; then # 创建监控服务 cat > /etc/systemd/system/flask-monitor.service << 'MONITOR_EOF' [Unit] Description=Flask Prompt Master Monitor After=network.target [Service] Type=simple User=www-data WorkingDirectory=/opt/flask-prompt-master ExecStart=/opt/flask-prompt-master/venv/bin/python simple_monitor.py Restart=always RestartSec=10 [Install] WantedBy=multi-user.target MONITOR_EOF systemctl daemon-reload systemctl enable flask-monitor systemctl start flask-monitor fi echo "部署完成!" EOF # 上传文件到服务器 log_info "上传部署包到服务器..." scp -i "$KEY_PATH" -o StrictHostKeyChecking=no \ "flask-prompt-master-$ENVIRONMENT.tar.gz" \ "remote_deploy.sh" \ "$USER@$SERVER:/tmp/" # 执行远程部署 log_info "执行远程部署..." $SSH_CMD "chmod +x /tmp/remote_deploy.sh && /tmp/remote_deploy.sh $ENVIRONMENT" log_success "部署完成" } # 验证部署 verify_deployment() { log_info "验证部署..." # 等待服务启动 sleep 10 # 测试健康检查 HEALTH_URL="http://$SERVER/health" if [[ "$ENVIRONMENT" = "production" ]]; then HEALTH_URL="https://$SERVER/health" fi for i in {1..30}; do if curl -f "$HEALTH_URL" > /dev/null 2>&1; then log_success "服务健康检查通过" break else log_warning "等待服务启动... ($i/30)" sleep 2 fi done if ! curl -f "$HEALTH_URL" > /dev/null 2>&1; then log_error "服务健康检查失败" exit 1 fi # 测试主要功能 log_info "测试主要功能..." # 测试主页 if curl -f "http://$SERVER/" > /dev/null 2>&1; then log_success "主页访问正常" else log_error "主页访问失败" exit 1 fi # 测试API API_RESPONSE=$(curl -s -X POST "http://$SERVER/api/wx/templates/intent" \ -H "Content-Type: application/json" \ -d '{"text": "测试文本"}') if echo "$API_RESPONSE" | grep -q "code.*200"; then log_success "API功能正常" else log_error "API功能异常" exit 1 fi log_success "部署验证完成" } # 清理临时文件 cleanup() { log_info "清理临时文件..." rm -rf "$TEMP_DIR" rm -f remote_deploy.sh log_success "清理完成" } # 主函数 main() { log_info "开始自动化部署..." parse_args "$@" check_dependencies prepare_deployment deploy_to_server verify_deployment cleanup log_success "自动化部署完成!" log_info "应用地址: http://$SERVER" log_info "健康检查: http://$SERVER/health" } # 执行主函数 main "$@"