配置 SSOT(TOML + .env) 统一错误契约 Auth 与事务边界 Redis / Celery 可靠性:业务 Redis(DB/0)与 Celery broker/backend(DB/1)显式拆分;连接池、sync client 可观测性(OpenTelemetry + LGTM)
229 lines
6.9 KiB
Bash
Executable File
229 lines
6.9 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# 短信验证码功能部署脚本
|
||
# 用途:自动化部署短信验证码功能
|
||
|
||
set -e # 遇到错误立即退出
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# 打印函数
|
||
print_header() {
|
||
echo -e "\n${BLUE}========================================${NC}"
|
||
echo -e "${BLUE}$1${NC}"
|
||
echo -e "${BLUE}========================================${NC}\n"
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}✓ $1${NC}"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}✗ $1${NC}"
|
||
}
|
||
|
||
print_warning() {
|
||
echo -e "${YELLOW}⚠ $1${NC}"
|
||
}
|
||
|
||
print_info() {
|
||
echo -e "${BLUE}ℹ $1${NC}"
|
||
}
|
||
|
||
# 检查命令是否存在
|
||
check_command() {
|
||
if ! command -v $1 &> /dev/null; then
|
||
print_error "$1 未安装"
|
||
return 1
|
||
fi
|
||
print_success "$1 已安装"
|
||
return 0
|
||
}
|
||
|
||
# 检查环境变量
|
||
check_env_var() {
|
||
if [ -z "${!1}" ]; then
|
||
print_error "环境变量 $1 未设置"
|
||
return 1
|
||
fi
|
||
print_success "环境变量 $1 已设置"
|
||
return 0
|
||
}
|
||
|
||
# 主函数
|
||
main() {
|
||
print_header "短信验证码功能部署脚本"
|
||
|
||
# 1. 检查前置条件
|
||
print_header "1. 检查前置条件"
|
||
|
||
check_command "python3" || exit 1
|
||
check_command "pip3" || exit 1
|
||
check_command "psql" || print_warning "psql 未安装,将跳过数据库迁移"
|
||
check_command "redis-cli" || print_warning "redis-cli 未安装,请确保Redis服务正在运行"
|
||
|
||
# 2. 检查环境变量
|
||
print_header "2. 检查环境变量"
|
||
|
||
if [ -f ".env.production" ]; then
|
||
print_success "找到 .env.production 文件"
|
||
source .env.production
|
||
else
|
||
print_error ".env.production 文件不存在"
|
||
print_info "请创建 .env.production 文件并配置必要的环境变量"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查必要的环境变量(密钥与连接串;SMS 模板等见 config/production.toml)
|
||
REQUIRED_VARS=(
|
||
"DATABASE_URL"
|
||
"REDIS_URL"
|
||
"SECRET_KEY"
|
||
"TENCENT_SECRET_ID"
|
||
"TENCENT_SECRET_KEY"
|
||
)
|
||
|
||
ALL_VARS_SET=true
|
||
for var in "${REQUIRED_VARS[@]}"; do
|
||
check_env_var "$var" || ALL_VARS_SET=false
|
||
done
|
||
|
||
if [ "$ALL_VARS_SET" = false ]; then
|
||
print_error "部分环境变量未设置,请检查 .env.production 文件"
|
||
exit 1
|
||
fi
|
||
|
||
# 3. 安装依赖
|
||
print_header "3. 安装Python依赖"
|
||
|
||
if [ -f "requirements.txt" ]; then
|
||
print_info "正在安装依赖..."
|
||
pip3 install -r requirements.txt
|
||
print_success "依赖安装完成"
|
||
else
|
||
print_error "requirements.txt 文件不存在"
|
||
exit 1
|
||
fi
|
||
|
||
# 4. 数据库迁移
|
||
print_header "4. 执行数据库迁移"
|
||
|
||
if command -v psql &> /dev/null; then
|
||
read -p "是否执行数据库迁移? (y/n): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
if [ -f "migrations/add_sms_verification.sql" ]; then
|
||
print_info "正在执行数据库迁移..."
|
||
|
||
# 从DATABASE_URL提取数据库连接信息
|
||
# 格式: postgresql://user:password@host:port/database
|
||
DB_USER=$(echo $DATABASE_URL | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
|
||
DB_NAME=$(echo $DATABASE_URL | sed -n 's/.*\/\([^?]*\).*/\1/p')
|
||
|
||
if [ -z "$DB_USER" ] || [ -z "$DB_NAME" ]; then
|
||
print_warning "无法从DATABASE_URL解析数据库信息"
|
||
print_info "请手动执行: psql -U <user> -d <database> -f migrations/add_sms_verification.sql"
|
||
else
|
||
psql -U "$DB_USER" -d "$DB_NAME" -f migrations/add_sms_verification.sql
|
||
print_success "数据库迁移完成"
|
||
fi
|
||
else
|
||
print_error "迁移脚本不存在: migrations/add_sms_verification.sql"
|
||
exit 1
|
||
fi
|
||
else
|
||
print_warning "跳过数据库迁移"
|
||
fi
|
||
else
|
||
print_warning "psql 未安装,跳过数据库迁移"
|
||
print_info "请手动执行: psql -U <user> -d <database> -f migrations/add_sms_verification.sql"
|
||
fi
|
||
|
||
# 5. 验证部署
|
||
print_header "5. 验证部署"
|
||
|
||
print_info "正在验证腾讯云SDK..."
|
||
python3 -c "from tencentcloud.sms.v20210111 import sms_client; print('腾讯云SDK验证成功')" && \
|
||
print_success "腾讯云SDK验证通过" || \
|
||
print_error "腾讯云SDK验证失败"
|
||
|
||
# 6. 测试连接
|
||
print_header "6. 测试服务连接"
|
||
|
||
read -p "是否启动服务并测试? (y/n): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
print_info "正在启动服务..."
|
||
|
||
# 在后台启动服务
|
||
python3 main.py &
|
||
SERVER_PID=$!
|
||
|
||
print_info "服务PID: $SERVER_PID"
|
||
print_info "等待服务启动..."
|
||
sleep 5
|
||
|
||
# 测试健康检查
|
||
print_info "测试健康检查..."
|
||
if curl -s http://localhost:8000/health > /dev/null; then
|
||
print_success "健康检查通过"
|
||
else
|
||
print_error "健康检查失败"
|
||
kill $SERVER_PID 2>/dev/null || true
|
||
exit 1
|
||
fi
|
||
|
||
# 测试发送验证码API
|
||
print_info "测试发送验证码API..."
|
||
read -p "请输入测试手机号 (或按Enter跳过): " TEST_PHONE
|
||
|
||
if [ -n "$TEST_PHONE" ]; then
|
||
RESPONSE=$(curl -s -X POST http://localhost:8000/api/auth/sms/send \
|
||
-H "Content-Type: application/json" \
|
||
-d "{\"phone\":\"$TEST_PHONE\",\"purpose\":\"register\"}")
|
||
|
||
if echo "$RESPONSE" | grep -q "验证码已发送"; then
|
||
print_success "验证码发送成功"
|
||
print_info "响应: $RESPONSE"
|
||
else
|
||
print_error "验证码发送失败"
|
||
print_info "响应: $RESPONSE"
|
||
fi
|
||
fi
|
||
|
||
# 停止测试服务
|
||
print_info "停止测试服务..."
|
||
kill $SERVER_PID 2>/dev/null || true
|
||
print_success "测试服务已停止"
|
||
else
|
||
print_warning "跳过服务测试"
|
||
fi
|
||
|
||
# 7. 部署完成
|
||
print_header "部署完成"
|
||
|
||
print_success "短信验证码功能部署完成!"
|
||
echo
|
||
print_info "后续步骤:"
|
||
echo " 1. 使用 Docker 部署: docker compose up -d"
|
||
echo " 2. 或使用 Systemd 部署: sudo systemctl start life-echo-api"
|
||
echo " 3. 查看日志: docker compose logs -f 或 journalctl -u life-echo-api -f"
|
||
echo " 4. 运行测试: python test_sms_verification.py"
|
||
echo " 5. 查看部署文档: docs/部署指南.md"
|
||
echo
|
||
print_warning "重要提示:"
|
||
echo " - 请确保已配置防火墙和SSL证书"
|
||
echo " - 请配置日志监控和告警"
|
||
echo " - 请设置数据库自动备份"
|
||
echo " - 请妥善保管API密钥,不要泄露"
|
||
echo
|
||
}
|
||
|
||
# 执行主函数
|
||
main
|