#!/bin/bash # H3C ONU设备管理系统 - 部署脚本 # 使用方法: ./deploy.sh [环境] [操作] # 环境: dev, prod (默认: prod) # 操作: up, down, restart, logs, build (默认: up) set -e # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 默认值 ENV=${1:-prod} ACTION=${2:-up} COMPOSE_FILE="docker-compose.yml" # 根据环境选择配置文件 if [ "$ENV" = "dev" ]; then COMPOSE_FILE="docker-compose.dev.yml" echo -e "${BLUE}使用开发环境配置${NC}" elif [ "$ENV" = "prod" ]; then COMPOSE_FILE="docker-compose.yml" echo -e "${BLUE}使用生产环境配置${NC}" else echo -e "${RED}错误: 未知环境 '$ENV'${NC}" echo "可用环境: dev, prod" exit 1 fi # 检查Docker Compose文件是否存在 if [ ! -f "$COMPOSE_FILE" ]; then echo -e "${RED}错误: Docker Compose文件 '$COMPOSE_FILE' 不存在${NC}" exit 1 fi # 检查环境变量文件 if [ ! -f ".env" ]; then echo -e "${YELLOW}警告: .env 文件不存在,从 .env.example 复制${NC}" if [ -f ".env.example" ]; then cp .env.example .env echo -e "${YELLOW}请编辑 .env 文件并设置正确的配置${NC}" exit 1 else echo -e "${RED}错误: .env.example 文件也不存在${NC}" exit 1 fi fi # 加载环境变量 set -a source .env set +a # 函数:显示帮助信息 show_help() { echo "H3C ONU设备管理系统 - 部署脚本" echo "" echo "使用方法: $0 [环境] [操作]" echo "" echo "环境:" echo " dev 开发环境" echo " prod 生产环境 (默认)" echo "" echo "操作:" echo " up 启动服务 (默认)" echo " down 停止服务" echo " restart 重启服务" echo " logs 查看日志" echo " build 构建镜像" echo " ps 查看服务状态" echo " exec 进入容器" echo " backup 备份数据" echo " restore 恢复数据" echo "" echo "示例:" echo " $0 prod up # 启动生产环境" echo " $0 dev logs # 查看开发环境日志" echo " $0 prod restart # 重启生产环境" } # 函数:检查Docker是否运行 check_docker() { if ! docker info > /dev/null 2>&1; then echo -e "${RED}错误: Docker未运行或当前用户无权限${NC}" exit 1 fi } # 函数:检查Docker Compose是否安装 check_docker_compose() { if ! command -v docker-compose &> /dev/null; then echo -e "${RED}错误: Docker Compose未安装${NC}" exit 1 fi } # 函数:启动服务 start_services() { echo -e "${GREEN}启动服务...${NC}" docker-compose -f "$COMPOSE_FILE" up -d # 等待服务启动 echo -e "${BLUE}等待服务启动...${NC}" sleep 10 # 检查服务状态 check_services_status } # 函数:停止服务 stop_services() { echo -e "${YELLOW}停止服务...${NC}" docker-compose -f "$COMPOSE_FILE" down } # 函数:重启服务 restart_services() { echo -e "${YELLOW}重启服务...${NC}" docker-compose -f "$COMPOSE_FILE" restart } # 函数:查看日志 show_logs() { echo -e "${BLUE}查看日志 (Ctrl+C退出)...${NC}" docker-compose -f "$COMPOSE_FILE" logs -f } # 函数:构建镜像 build_images() { echo -e "${GREEN}构建Docker镜像...${NC}" docker-compose -f "$COMPOSE_FILE" build --no-cache # 清理未使用的镜像 echo -e "${BLUE}清理未使用的镜像...${NC}" docker image prune -f } # 函数:查看服务状态 show_status() { echo -e "${BLUE}服务状态:${NC}" docker-compose -f "$COMPOSE_FILE" ps echo -e "\n${BLUE}容器资源使用:${NC}" docker stats --no-stream $(docker-compose -f "$COMPOSE_FILE" ps -q) } # 函数:进入容器 exec_container() { echo -e "${BLUE}选择要进入的容器:${NC}" echo "1) backend (后端API)" echo "2) frontend (前端)" echo "3) celery-worker (Celery Worker)" echo "4) celery-beat (Celery Beat)" echo "5) nginx (Nginx)" echo "6) redis (Redis)" read -p "请输入数字 (1-6): " choice case $choice in 1) CONTAINER="backend" ;; 2) CONTAINER="frontend" ;; 3) CONTAINER="celery-worker" ;; 4) CONTAINER="celery-beat" ;; 5) CONTAINER="nginx" ;; 6) CONTAINER="redis" ;; *) echo -e "${RED}无效的选择${NC}" exit 1 ;; esac echo -e "${GREEN}进入 $CONTAINER 容器...${NC}" docker-compose -f "$COMPOSE_FILE" exec "$CONTAINER" sh } # 函数:备份数据 backup_data() { BACKUP_DIR="backups/$(date +%Y%m%d_%H%M%S)" mkdir -p "$BACKUP_DIR" echo -e "${GREEN}开始备份数据...${NC}" # 备份数据库 echo -e "${BLUE}备份数据库...${NC}" DB_CONTAINER=$(docker-compose -f "$COMPOSE_FILE" ps -q backend) if [ -n "$DB_CONTAINER" ]; then docker exec "$DB_CONTAINER" pg_dump "$DATABASE_URL" > "$BACKUP_DIR/database.sql" echo "数据库备份完成: $BACKUP_DIR/database.sql" else echo -e "${YELLOW}警告: 数据库容器未运行${NC}" fi # 备份Redis数据 echo -e "${BLUE}备份Redis数据...${NC}" REDIS_CONTAINER=$(docker-compose -f "$COMPOSE_FILE" ps -q redis) if [ -n "$REDIS_CONTAINER" ]; then docker exec "$REDIS_CONTAINER" redis-cli --rdb /data/dump.rdb docker cp "$REDIS_CONTAINER:/data/dump.rdb" "$BACKUP_DIR/redis.rdb" echo "Redis备份完成: $BACKUP_DIR/redis.rdb" else echo -e "${YELLOW}警告: Redis容器未运行${NC}" fi # 备份配置文件 echo -e "${BLUE}备份配置文件...${NC}" cp .env "$BACKUP_DIR/" cp "$COMPOSE_FILE" "$BACKUP_DIR/" # 创建备份信息文件 echo "备份时间: $(date)" > "$BACKUP_DIR/backup.info" echo "环境: $ENV" >> "$BACKUP_DIR/backup.info" echo "版本: $(git describe --tags 2>/dev/null || echo '未知')" >> "$BACKUP_DIR/backup.info" # 压缩备份文件 echo -e "${BLUE}压缩备份文件...${NC}" tar -czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR" rm -rf "$BACKUP_DIR" echo -e "${GREEN}备份完成: $BACKUP_DIR.tar.gz${NC}" } # 函数:恢复数据 restore_data() { echo -e "${YELLOW}警告: 恢复数据将覆盖现有数据${NC}" read -p "请输入要恢复的备份文件路径: " BACKUP_FILE if [ ! -f "$BACKUP_FILE" ]; then echo -e "${RED}错误: 备份文件不存在${NC}" exit 1 fi # 解压备份文件 BACKUP_DIR="${BACKUP_FILE%.tar.gz}" echo -e "${BLUE}解压备份文件...${NC}" tar -xzf "$BACKUP_FILE" # 停止服务 echo -e "${BLUE}停止服务...${NC}" docker-compose -f "$COMPOSE_FILE" down # 恢复数据库 if [ -f "$BACKUP_DIR/database.sql" ]; then echo -e "${BLUE}恢复数据库...${NC}" # 这里需要根据实际情况调整数据库恢复命令 # 例如: psql -d database -f backup.sql echo "数据库恢复命令需要根据实际情况配置" fi # 恢复Redis if [ -f "$BACKUP_DIR/redis.rdb" ]; then echo -e "${BLUE}恢复Redis数据...${NC}" # 这里需要根据实际情况调整Redis恢复命令 echo "Redis恢复命令需要根据实际情况配置" fi # 恢复配置文件 if [ -f "$BACKUP_DIR/.env" ]; then echo -e "${BLUE}恢复配置文件...${NC}" cp "$BACKUP_DIR/.env" . fi # 清理临时文件 rm -rf "$BACKUP_DIR" # 启动服务 echo -e "${BLUE}启动服务...${NC}" docker-compose -f "$COMPOSE_FILE" up -d echo -e "${GREEN}数据恢复完成${NC}" } # 函数:检查服务状态 check_services_status() { echo -e "${BLUE}检查服务健康状态...${NC}" # 检查后端服务 if curl -f http://localhost:8000/health > /dev/null 2>&1; then echo -e "${GREEN}✓ 后端服务运行正常${NC}" else echo -e "${RED}✗ 后端服务异常${NC}" fi # 检查前端服务 if curl -f http://localhost:8080 > /dev/null 2>&1; then echo -e "${GREEN}✓ 前端服务运行正常${NC}" else echo -e "${RED}✗ 前端服务异常${NC}" fi # 检查Redis REDIS_CONTAINER=$(docker-compose -f "$COMPOSE_FILE" ps -q redis) if [ -n "$REDIS_CONTAINER" ] && docker exec "$REDIS_CONTAINER" redis-cli ping > /dev/null 2>&1; then echo -e "${GREEN}✓ Redis服务运行正常${NC}" else echo -e "${RED}✗ Redis服务异常${NC}" fi echo -e "\n${GREEN}部署完成!${NC}" echo -e "前端访问: ${BLUE}http://localhost:8080${NC}" echo -e "API文档: ${BLUE}http://localhost:8000/docs${NC}" echo -e "健康检查: ${BLUE}http://localhost:8000/health${NC}" } # 主程序 main() { # 显示标题 echo -e "${GREEN}========================================${NC}" echo -e "${GREEN} H3C ONU设备管理系统 - 部署工具${NC}" echo -e "${GREEN}========================================${NC}" echo "" # 检查依赖 check_docker check_docker_compose # 根据操作执行相应命令 case "$ACTION" in up) start_services ;; down) stop_services ;; restart) restart_services ;; logs) show_logs ;; build) build_images ;; ps) show_status ;; exec) exec_container ;; backup) backup_data ;; restore) restore_data ;; help|--help|-h) show_help ;; *) echo -e "${RED}错误: 未知操作 '$ACTION'${NC}" show_help exit 1 ;; esac } # 执行主程序 main "$@"