#!/bin/bash # 数字档案系统统一管理脚本 set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' NC='\033[0m' # No Color # 项目配置 PROJECT_NAME="digital-archive" VERSION="latest" DEFAULT_DEPLOY_DIR="/root/server/archive" DOCKERFILE="Dockerfile.stable" FAST_BUILD=false VERBOSE=false # 显示横幅 show_banner() { echo -e "${CYAN}" echo "╔══════════════════════════════════════════════════════════════════╗" echo "║ 数字档案系统管理脚本 ║" echo "║ ║" echo "║ 功能: 构建、部署、检查、管理数字档案系统 ║" echo "║ 版本: v2.0 ║" echo "╚════════════════════════════════════════════════════════════════╝" echo -e "${NC}" } # 显示帮助信息 show_help() { show_banner echo -e "${GREEN}用法: $0 <命令> [选项] [参数]${NC}" echo "" echo -e "${BLUE}命令:${NC}" echo " build 构建Docker镜像" echo " build --fast 快速构建镜像(跳过Tesseract)" echo " deploy 部署应用到指定目录" echo " check 检查环境配置" echo " start 启动服务" echo " stop 停止服务" echo " restart 重启服务" echo " logs 查看日志" echo " status 查看服务状态" echo " update 更新服务" echo " clean 清理资源" echo "" echo -e "${BLUE}选项:${NC}" echo " -h, --help 显示帮助信息" echo " -v, --verbose 详细输出" echo " -f, --force 强制执行(跳过确认)" echo " -q, --quiet 静默模式" echo "" echo -e "${BLUE}参数:${NC}" echo " 部署目录 目标部署目录 (默认: ${DEFAULT_DEPLOY_DIR})" echo "" echo -e "${YELLOW}示例:${NC}" echo " $0 build # 完整构建镜像" echo " $0 build -f # 快速构建镜像(跳过Tesseract)" echo " $0 deploy /opt/myapp # 部署到指定目录" echo " $0 check # 检查环境" echo " $0 start # 启动服务" echo " $0 stop # 停止服务" echo " $0 logs -f # 查看实时日志" echo "" } # 日志函数 log_info() { if [ "$VERBOSE" = true ]; then echo -e "${GREEN}[INFO]${NC} $1" fi } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } # 检查Docker环境 check_docker() { if ! command -v docker &> /dev/null; then log_error "Docker未安装" exit 1 fi # 检测Docker Compose命令类型 if docker compose version &> /dev/null; then COMPOSE_CMD="docker compose" elif command -v docker-compose &> /dev/null; then COMPOSE_CMD="docker-compose" else log_error "Docker Compose未安装" exit 1 fi log_info "使用命令: ${COMPOSE_CMD}" } # 检查脚本文件 check_scripts() { local scripts=("settings.xml") for script in "${scripts[@]}"; do if [ ! -f "$script" ]; then log_error "必需文件 $script 不存在" exit 1 fi done } # 构建镜像 build_image() { log_info "开始构建Docker镜像..." # 检查必需文件 check_scripts # 选择构建类型 if [ "$FAST_BUILD" = true ]; then DOCKERFILE="Dockerfile.fast" VERSION="fast" log_info "使用快速构建模式 (跳过Tesseract,预计3-5分钟)" else DOCKERFILE="Dockerfile.stable" VERSION="stable" log_info "使用完整构建模式 (包含所有功能,预计10-15分钟)" fi # 构建镜像 docker build -f ${DOCKERFILE} -t ${PROJECT_NAME}:${VERSION} . if [ $? -eq 0 ]; then log_success "镜像构建成功: ${PROJECT_NAME}:${VERSION}" # 显示镜像信息 if [ "$VERBOSE" = true ]; then echo -e "${YELLOW}镜像信息:${NC}" docker images ${PROJECT_NAME}:${VERSION} --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}" fi else log_error "镜像构建失败" exit 1 fi } # 检查环境 check_environment() { log_info "检查环境配置..." # 检查Docker网络 if ! docker network ls | grep -q proxy; then log_error "proxy网络不存在,请创建: docker network create proxy" exit 1 fi # 检查容器 local mysql_container=$(docker network inspect proxy --format '{{range .Containers}}{{.Name}} {{end}}' 2>/dev/null | tr ' ' '\n' | grep -i mysql | head -1 || true) local redis_container=$(docker network inspect proxy --format '{{range .Containers}}{{.Name}} {{end}}' 2>/dev/null | tr ' ' '\n' | grep -i redis | head -1 || true) local es_container=$(docker network inspect proxy --format '{{range .Containers}}{{.Name}} {{end}}' 2>/dev/null | tr ' ' ' ' | grep -w "es" | head -1 || true) if [ -z "$mysql_container" ]; then log_error "proxy网络中未找到MySQL容器" exit 1 fi if [ -z "$redis_container" ]; then log_error "proxy网络中未找到Redis容器" exit 1 fi if [ -z "$es_container" ]; then log_warn "proxy网络中未找到Elasticsearch容器(可选)" fi log_success "环境检查完成" log_info "MySQL: $mysql_container" log_info "Redis: $redis_container" [ ! -z "$es_container" ] && log_info "Elasticsearch: $es_container" } # 部署应用 deploy_app() { local deploy_dir=${1:-$DEFAULT_DEPLOY_DIR} log_info "部署应用到: $deploy_dir" # 确定要使用的镜像版本 if [ "$FAST_BUILD" = true ]; then VERSION="fast" log_info "使用快速构建版本: ${PROJECT_NAME}:fast" else VERSION="stable" log_info "使用完整构建版本: ${PROJECT_NAME}:stable" fi # 检查镜像 if ! docker images | grep -q "${PROJECT_NAME}:${VERSION}"; then log_error "镜像 ${PROJECT_NAME}:${VERSION} 不存在,请先构建: $0 build" if [ "$FAST_BUILD" = true ]; then log_error "或使用: $0 build -f" fi exit 1 fi # 创建部署目录 mkdir -p "$deploy_dir"/{data/{upload,temp,unzip,images,reports,elasticsearch},logs,nginx} # 动态生成 docker-compose.yml 文件 cat > "$deploy_dir/docker-compose.yml" << EOF version: '3.8' services: # 主应用服务 app: image: ${PROJECT_NAME}:${VERSION} container_name: digital-archive-app ports: - "9081:9081" volumes: - ./data/upload:/app/data/upload - ./data/temp:/app/data/temp - ./data/unzip:/app/data/unzip - ./data/images:/app/data/images - ./data/reports:/app/data/reports - ./logs:/app/logs environment: - SPRING_PROFILES_ACTIVE=prod - SERVER_PORT=9081 # MySQL数据库配置 - DB_HOST=mysql - DB_PORT=3306 - DB_NAME=enterprise_digital_archives - DB_USERNAME=root - DB_PASSWORD=Abc@123456 - DB_DRIVER=com.mysql.jdbc.Driver # Redis配置 - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=Abc123456 # Elasticsearch配置 - 使用已有的 "es" 容器 - ELASTICSEARCH_HOST=es - ELASTICSEARCH_PORT=9200 - ELASTICSEARCH_SCHEME=http # OCR配置 - TESS_PATH=/usr/bin/tesseract # 其他配置 - SWAGGER_SHOW=false - LOG_ROOT_LEVEL=info - LOG_APP_LEVEL=info networks: - proxy restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9081/point-strategy/actuator/health"] interval: 30s timeout: 10s retries: 3 start_period: 60s # Elasticsearch - 使用已有的 "es" 容器 # 注意:确保已有的 "es" 容器已连接到 proxy 网络 networks: proxy: external: true EOF # 创建环境配置 cat > "$deploy_dir/.env" << EOF COMPOSE_PROJECT_NAME=digital-archive # 服务配置 SERVER_PORT=9081 SERVER_CONTEXT_PATH=/point-strategy # MySQL数据库配置 DB_HOST=mysql DB_PORT=3306 DB_NAME=enterprise_digital_archives DB_USERNAME=root DB_PASSWORD=Abc@123456 DB_DRIVER=com.mysql.jdbc.Driver # Redis配置 REDIS_HOST=redis REDIS_PORT=6379 REDIS_PASSWORD=Abc123456 # Elasticsearch配置 - 使用已有的 "es" 容器 ELASTICSEARCH_HOST=es ELASTICSEARCH_PORT=9200 ELASTICSEARCH_SCHEME=http # OCR配置 TESS_PATH=/usr/bin/tesseract # 其他配置 SWAGGER_SHOW=false LOG_ROOT_LEVEL=info LOG_APP_LEVEL=info JAVA_OPTS=-Xmx2g -Xms1g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 EOF # 创建管理脚本 cat > "$deploy_dir/start.sh" << 'EOF' #!/bin/bash echo "启动数字档案系统..." # 检测Docker Compose命令类型 if docker compose version &> /dev/null; then COMPOSE_CMD="docker compose" else COMPOSE_CMD="docker-compose" fi ${COMPOSE_CMD} up -d echo "等待服务启动..." sleep 30 echo "检查服务状态..." ${COMPOSE_CMD} ps echo "服务启动完成!" EOF cat > "$deploy_dir/stop.sh" << 'EOF' #!/bin/bash echo "停止数字档案系统..." # 检测Docker Compose命令类型 if docker compose version &> /dev/null; then COMPOSE_CMD="docker compose" else COMPOSE_CMD="docker-compose" fi ${COMPOSE_CMD} down echo "清理未使用的镜像和容器..." docker system prune -f EOF cat > "$deploy_dir/update.sh" << 'EOF' #!/bin/bash echo "更新数字档案系统..." # 检测Docker Compose命令类型 if docker compose version &> /dev/null; then COMPOSE_CMD="docker compose" else COMPOSE_CMD="docker-compose" fi echo "停止服务..." ${COMPOSE_CMD} down echo "拉取最新镜像..." ${COMPOSE_CMD} pull echo "启动服务..." ${COMPOSE_CMD} up -d echo "清理旧镜像..." docker image prune -f EOF # 设置执行权限 chmod +x "$deploy_dir"/{start.sh,stop.sh,update.sh} log_success "应用部署完成: $deploy_dir" log_info "管理命令:" echo " 启动: cd $deploy_dir && ./start.sh" echo " 停止: cd $deploy_dir && ./stop.sh" echo " 更新: cd $deploy_dir && ./update.sh" } # 启动服务 start_services() { local deploy_dir=${1:-$DEFAULT_DEPLOY_DIR} if [ ! -d "$deploy_dir" ]; then log_error "部署目录不存在: $deploy_dir" exit 1 fi cd "$deploy_dir" if [ ! -f "start.sh" ]; then log_error "启动脚本不存在,请先部署: $0 deploy $deploy_dir" exit 1 fi ./start.sh log_success "服务启动完成" if [ "$VERBOSE" = true ]; then echo -e "${YELLOW}访问地址: http://localhost:9081/point-strategy${NC}" fi } # 停止服务 stop_services() { local deploy_dir=${1:-$DEFAULT_DEPLOY_DIR} if [ ! -d "$deploy_dir" ]; then log_error "部署目录不存在: $deploy_dir" exit 1 fi cd "$deploy_dir" if [ -f "stop.sh" ]; then ./stop.sh log_success "服务停止完成" else log_warn "停止脚本不存在,尝试使用Docker Compose" if docker compose version &> /dev/null; then docker compose down else docker-compose down fi fi } # 重启服务 restart_services() { local deploy_dir=${1:-$DEFAULT_DEPLOY_DIR} log_info "重启服务..." stop_services "$deploy_dir" sleep 2 start_services "$deploy_dir" log_success "服务重启完成" } # 查看日志 show_logs() { local deploy_dir=${1:-$DEFAULT_DEPLOY_DIR} local follow=$2 if [ ! -d "$deploy_dir" ]; then log_error "部署目录不存在: $deploy_dir" exit 1 fi cd "$deploy_dir" if [ "$follow" = "-f" ]; then if docker compose version &> /dev/null; then docker compose logs -f app else docker-compose logs -f app fi else if docker compose version &> /dev/null; then docker compose logs --tail=100 app else docker-compose logs --tail=100 app fi fi } # 查看状态 show_status() { local deploy_dir=${1:-$DEFAULT_DEPLOY_DIR} if [ ! -d "$deploy_dir" ]; then log_error "部署目录不存在: $deploy_dir" exit 1 fi cd "$deploy_dir" echo -e "${CYAN}=== 数字档案系统服务状态 ===${NC}" if docker compose version &> /dev/null; then docker compose ps else docker-compose ps fi echo "" echo -e "${CYAN}=== 容器资源使用情况 ===${NC}" docker stats --no-stream } # 更新服务 update_services() { local deploy_dir=${1:-$DEFAULT_DEPLOY_DIR} if [ ! -d "$deploy_dir" ]; then log_error "部署目录不存在: $deploy_dir" exit 1 fi cd "$deploy_dir" if [ -f "update.sh" ]; then ./update.sh log_success "服务更新完成" else log_warn "更新脚本不存在,请先部署: $0 deploy $deploy_dir" fi } # 清理资源 clean_resources() { log_info "清理Docker资源..." # 清理停止的容器 docker container prune -f # 清理未使用的镜像 docker image prune -f # 清理未使用的网络 docker network prune -f # 清理未使用的卷 docker volume prune -f log_success "资源清理完成" } # 主函数 main() { # 解析命令行参数 COMMAND="" VERBOSE=false FORCE=false while [[ $# -gt 0 ]]; do case $1 in build|deploy|check|start|stop|restart|logs|status|update|clean) COMMAND=$1 shift ;; -h|--help) show_help exit 0 ;; -v|--verbose) VERBOSE=true shift ;; -f|--fast) FAST_BUILD=true shift ;; --force) FORCE=true shift ;; -q|--quiet) # 重定向输出到/dev/null exec 1>/dev/null 2>&1 ;; -*) log_error "未知选项: $1" show_help exit 1 ;; *) # 参数传递给具体命令 break ;; esac done # 如果没有命令,显示帮助 if [ -z "$COMMAND" ]; then show_help exit 0 fi # 显示横幅 if [ "$VERBOSE" = true ]; then show_banner fi # 检查Docker环境 check_docker # 执行对应命令 case $COMMAND in build) build_image ;; deploy) deploy_app "$@" ;; check) check_environment ;; start) start_services "$@" ;; stop) stop_services "$@" ;; restart) restart_services "$@" ;; logs) show_logs "$@" ;; status) show_status "$@" ;; update) update_services "$@" ;; clean) clean_resources ;; *) log_error "未知命令: $COMMAND" show_help exit 1 ;; esac } # 执行主函数 main "$@"