Prechádzať zdrojové kódy

chore: 添加Web版本更新脚本

- 新增 update-client-for-web.sh 脚本,用于从 web-releases 目录更新H5应用
- 与原有 update-client.sh 功能相同,仅修改拉取源目录为 web-releases
- 独立的锁文件和日志文件,避免与原脚本冲突

改动文件:
- update-client-for-web.sh(新增)
dengdx 2 dní pred
rodič
commit
f3d6b1aa0b
1 zmenil súbory, kde vykonal 627 pridanie a 0 odobranie
  1. 627 0
      update-client-for-web.sh

+ 627 - 0
update-client-for-web.sh

@@ -0,0 +1,627 @@
+#!/usr/bin/env bash
+
+################################################################################
+# H5 应用更新客户端脚本(Web版本)
+# 
+# 功能:从版本服务器的 web-releases 目录下载并更新 H5 应用
+# 版本:1.0.0
+# 作者:自动生成
+################################################################################
+
+set -euo pipefail  # 严格模式:遇到错误立即退出
+
+# ============================================================================
+# 颜色定义
+# ============================================================================
+readonly RED='\033[0;31m'
+readonly GREEN='\033[0;32m'
+readonly YELLOW='\033[1;33m'
+readonly BLUE='\033[0;34m'
+readonly NC='\033[0m' # No Color
+
+# ============================================================================
+# 全局变量
+# ============================================================================
+readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+readonly LOCK_FILE="/tmp/update-client-for-web-${USER}.lock"
+readonly SERVER="dros.overs.games"
+readonly DEFAULT_USER="deploy"
+readonly DEFAULT_DIR="./h5"
+readonly LOG_DIR="./logs"
+
+# 用户输入变量
+USERNAME=""
+PASSWORD=""
+DOWNLOAD_DIR=""
+VERSION=""
+SILENT_MODE=false
+SKIP_CONFIRM=false
+INCLUDE_STATIC=false  # 是否包含 static 文件夹
+
+# 日志文件
+LOG_FILE=""
+
+# ============================================================================
+# 工具函数
+# ============================================================================
+
+# 打印信息
+log_info() {
+    echo -e "${GREEN}[INFO]${NC} $*" | tee -a "$LOG_FILE"
+}
+
+# 打印警告
+log_warn() {
+    echo -e "${YELLOW}[WARN]${NC} $*" | tee -a "$LOG_FILE"
+}
+
+# 打印错误
+log_error() {
+    echo -e "${RED}[ERROR]${NC} $*" | tee -a "$LOG_FILE" >&2
+}
+
+# 打印成功
+log_success() {
+    echo -e "${GREEN}[✓]${NC} $*" | tee -a "$LOG_FILE"
+}
+
+# 清理函数
+cleanup() {
+    if [ -f "$LOCK_FILE" ]; then
+        rm -f "$LOCK_FILE"
+    fi
+}
+
+# 设置清理陷阱
+trap cleanup EXIT INT TERM
+
+# ============================================================================
+# 帮助信息
+# ============================================================================
+show_help() {
+    cat << EOF
+H5 应用更新客户端(Web版本)
+
+用法: $0 [选项]
+
+选项:
+  -u, --user USERNAME       指定用户名(默认: $DEFAULT_USER)
+  -p, --password PASS       指定密码
+  -d, --dir DIRECTORY       指定下载目录(默认: $DEFAULT_DIR)
+  -v, --version VERSION     指定版本号(默认: latest)
+  -i, --include-static      包含 static 文件夹更新(默认: 不包含)
+  -y, --yes                 跳过确认提示
+  -s, --silent              静默模式(最小输出)
+  -h, --help                显示此帮助信息
+
+示例:
+  # 交互模式
+  $0
+
+  # 非交互模式(不包含 static)
+  $0 -u deploy -p mypassword -d ./h5 -v latest -y
+
+  # 包含 static 文件夹
+  $0 -u deploy -p mypassword -d ./h5 -v latest -y --include-static
+
+  # 静默模式
+  $0 -u deploy -p mypassword -v v1.1.5-20251129-062104 -y -s
+
+EOF
+}
+
+# ============================================================================
+# 检查依赖工具
+# ============================================================================
+check_dependencies() {
+    log_info "检查依赖工具..."
+    
+    local missing_tools=()
+    
+    for tool in curl wget tar; do
+        if ! command -v "$tool" &> /dev/null; then
+            missing_tools+=("$tool")
+        fi
+    done
+    
+    if [ ${#missing_tools[@]} -gt 0 ]; then
+        log_error "缺少必需工具: ${missing_tools[*]}"
+        log_error "请安装缺少的工具后重试"
+        exit 1
+    fi
+    
+    log_success "依赖工具检查通过"
+}
+
+# ============================================================================
+# 检查并发执行
+# ============================================================================
+check_lock() {
+    if [ -f "$LOCK_FILE" ]; then
+        log_error "更新脚本已在运行中(锁文件: $LOCK_FILE)"
+        log_error "如确认没有其他实例运行,请删除锁文件后重试"
+        exit 1
+    fi
+    
+    touch "$LOCK_FILE"
+    log_info "已创建锁文件"
+}
+
+# ============================================================================
+# 初始化日志
+# ============================================================================
+init_log() {
+    mkdir -p "$LOG_DIR"
+    LOG_FILE="$LOG_DIR/update_web_$(date +%Y%m%d_%H%M%S).log"
+    log_info "日志文件: $LOG_FILE"
+}
+
+# ============================================================================
+# 验证用户名格式
+# ============================================================================
+validate_username() {
+    local username=$1
+    
+    if [[ ! $username =~ ^[a-zA-Z0-9_]+$ ]]; then
+        log_error "用户名格式错误(仅允许字母、数字和下划线)"
+        return 1
+    fi
+    
+    return 0
+}
+
+# ============================================================================
+# 验证密码
+# ============================================================================
+validate_password() {
+    local password=$1
+    
+    if [ -z "$password" ]; then
+        log_error "密码不能为空"
+        return 1
+    fi
+    
+    if [ ${#password} -lt 6 ]; then
+        log_error "密码长度至少6位"
+        return 1
+    fi
+    
+    return 0
+}
+
+# ============================================================================
+# 获取用户输入
+# ============================================================================
+get_user_input() {
+    # 用户名
+    if [ -z "$USERNAME" ]; then
+        read -p "请输入用户名 [默认: $DEFAULT_USER]: " USERNAME
+        USERNAME=${USERNAME:-$DEFAULT_USER}
+    fi
+    
+    if ! validate_username "$USERNAME"; then
+        exit 1
+    fi
+    
+    log_info "用户名: $USERNAME"
+    
+    # 密码
+    if [ -z "$PASSWORD" ]; then
+        while true; do
+            read -s -p "请输入密码: " PASSWORD
+            echo
+            
+            if validate_password "$PASSWORD"; then
+                break
+            fi
+        done
+    fi
+    
+    log_info "密码已设置(已脱敏)"
+    
+    # 下载目录
+    if [ -z "$DOWNLOAD_DIR" ]; then
+        read -p "请输入下载目录 [默认: $DEFAULT_DIR]: " DOWNLOAD_DIR
+        DOWNLOAD_DIR=${DOWNLOAD_DIR:-$DEFAULT_DIR}
+    fi
+    
+    log_info "下载目录: $DOWNLOAD_DIR"
+    
+    # 询问是否更新 static 文件夹(仅在交互模式且未通过参数指定时询问)
+    if [ "$INCLUDE_STATIC" = "false" ]; then
+        read -p "是否需要更新 static 文件夹? [y/N]: " include_static
+        if [[ $include_static =~ ^[Yy]$ ]]; then
+            INCLUDE_STATIC=true
+            log_info "static 文件夹: 将包含在更新中"
+        else
+            INCLUDE_STATIC=false
+            log_info "static 文件夹: 将跳过更新"
+        fi
+    fi
+}
+
+# ============================================================================
+# 验证路径权限
+# ============================================================================
+validate_path() {
+    local dir=$1
+    
+    # 检查路径是否存在
+    if [ ! -d "$dir" ]; then
+        log_warn "目录不存在: $dir"
+        
+        if [ "$SKIP_CONFIRM" = false ]; then
+            read -p "是否创建该目录? [y/N]: " confirm
+            if [[ ! $confirm =~ ^[Yy]$ ]]; then
+                log_error "用户取消操作"
+                exit 1
+            fi
+        fi
+        
+        mkdir -p "$dir"
+        log_success "已创建目录: $dir"
+    fi
+    
+    # 检查写入权限
+    if [ ! -w "$dir" ]; then
+        log_error "无写入权限: $dir"
+        exit 1
+    fi
+    
+    log_success "路径验证通过"
+}
+
+# ============================================================================
+# 测试服务器连接
+# ============================================================================
+test_server_connection() {
+    log_info "测试服务器连接: https://$SERVER"
+    
+    if ! curl -k -s --max-time 10 --user "$USERNAME:$PASSWORD" \
+         "https://$SERVER/web-releases/" > /dev/null 2>&1; then
+        log_error "无法连接到服务器"
+        log_error "请检查网络连接、用户名和密码"
+        exit 1
+    fi
+    
+    log_success "服务器连接成功"
+}
+
+# ============================================================================
+# 获取版本列表
+# ============================================================================
+get_version_list() {
+    log_info "正在获取版本列表..."
+    
+    local versions
+    versions=$(curl -k -s --user "$USERNAME:$PASSWORD" \
+        "https://$SERVER/web-releases/" | \
+        grep -oP 'v\d+\.\d+\.\d+-\d{8}-\d{6}' | \
+        sort -Vr | \
+        head -10)
+    
+    if [ -z "$versions" ]; then
+        log_error "无法获取版本列表"
+        exit 1
+    fi
+    
+    echo "$versions"
+}
+
+# ============================================================================
+# 显示版本列表并选择
+# ============================================================================
+select_version() {
+    if [ -n "$VERSION" ]; then
+        log_info "使用指定版本: $VERSION"
+        return
+    fi
+    
+    log_info "获取可用版本..."
+    local versions
+    versions=$(get_version_list)
+    
+    echo
+    echo "可用版本列表(最新10个):"
+    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
+    echo "  0. latest (最新版本)"
+    
+    local i=1
+    while IFS= read -r version; do
+        echo "  $i. $version"
+        ((i++))
+    done <<< "$versions"
+    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
+    echo
+    
+    # 用户选择
+    while true; do
+        read -p "请选择版本 [0-$((i-1)),默认: 0]: " choice
+        choice=${choice:-0}
+        
+        if [[ $choice =~ ^[0-9]+$ ]]; then
+            if [ "$choice" -eq 0 ]; then
+                VERSION="latest"
+                break
+            elif [ "$choice" -lt "$i" ]; then
+                VERSION=$(echo "$versions" | sed -n "${choice}p")
+                break
+            fi
+        fi
+        
+        log_error "无效选择,请重新输入"
+    done
+    
+    log_info "已选择版本: $VERSION"
+}
+
+# ============================================================================
+# 验证版本是否存在
+# ============================================================================
+verify_version_exists() {
+    local version=$1
+    
+    log_info "验证版本: $version"
+    
+    if ! curl -k -s --fail --head --user "$USERNAME:$PASSWORD" \
+         "https://$SERVER/web-releases/$version/" > /dev/null 2>&1; then
+        log_error "版本不存在: $version"
+        exit 1
+    fi
+    
+    log_success "版本验证通过"
+}
+
+# ============================================================================
+# 备份当前版本
+# ============================================================================
+backup_current_version() {
+    local dir=$1
+    
+    if [ ! -d "$dir" ] || [ -z "$(ls -A "$dir" 2>/dev/null)" ]; then
+        log_info "无需备份(目录为空或不存在)"
+        return
+    fi
+    
+    local backup_name="${dir}_backup_$(date +%Y%m%d_%H%M%S)"
+    
+    log_info "备份当前版本到: $backup_name"
+    
+    if ! mv "$dir" "$backup_name"; then
+        log_error "备份失败"
+        exit 1
+    fi
+    
+    log_success "备份完成: $backup_name"
+}
+
+# ============================================================================
+# 下载并更新
+# ============================================================================
+download_and_update() {
+    local version=$1
+    local target_dir=$2
+    
+    log_info "开始下载版本: $version"
+    log_info "目标目录: $target_dir"
+    
+    mkdir -p "$target_dir"
+    
+    # 使用 wget 下载(显示进度)
+    local wget_opts=(
+        "--user=$USERNAME"
+        "--password=$PASSWORD"
+        "--no-check-certificate"
+        "--recursive"
+        "--no-parent"
+        "--no-host-directories"
+        "--cut-dirs=2"
+        "--level=inf"
+        "-N"
+        "-P"
+        "$target_dir"
+    )
+    
+    # 如果不包含 static,添加排除参数
+    if [ "$INCLUDE_STATIC" = "false" ]; then
+        wget_opts+=("-X" "static")
+        wget_opts+=("--reject-regex" ".*/static/.*")
+        log_info "static 文件夹: 跳过下载(使用排除参数)"
+    else
+        log_info "static 文件夹: 包含在更新中"
+    fi
+    
+    if [ "$SILENT_MODE" = true ]; then
+        wget_opts+=("-q")
+    fi
+    
+    if ! wget "${wget_opts[@]}" "https://$SERVER/web-releases/$version/"; then
+        log_error "下载失败"
+        exit 1
+    fi
+    
+    log_success "下载完成"
+}
+
+# ============================================================================
+# 验证文件完整性(如果存在校验文件)
+# ============================================================================
+verify_integrity() {
+    local dir=$1
+    
+    # 检查是否存在 MD5 校验文件
+    if [ -f "$dir/checksum.md5" ]; then
+        log_info "验证文件完整性(MD5)..."
+        
+        cd "$dir" || exit 1
+        if md5sum -c checksum.md5 > /dev/null 2>&1; then
+            log_success "文件完整性验证通过"
+        else
+            log_error "文件完整性验证失败"
+            exit 1
+        fi
+        cd - > /dev/null || exit 1
+    elif [ -f "$dir/checksum.sha256" ]; then
+        log_info "验证文件完整性(SHA256)..."
+        
+        cd "$dir" || exit 1
+        if sha256sum -c checksum.sha256 > /dev/null 2>&1; then
+            log_success "文件完整性验证通过"
+        else
+            log_error "文件完整性验证失败"
+            exit 1
+        fi
+        cd - > /dev/null || exit 1
+    else
+        log_warn "未找到校验文件,跳过完整性验证"
+    fi
+}
+
+# ============================================================================
+# 显示更新摘要
+# ============================================================================
+show_update_summary() {
+    local static_status
+    if [ "$INCLUDE_STATIC" = "true" ]; then
+        static_status="包含"
+    else
+        static_status="跳过"
+    fi
+    
+    echo
+    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
+    echo "  更新摘要(Web版本)"
+    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
+    echo "  服务器: $SERVER"
+    echo "  用户名: $USERNAME"
+    echo "  目标目录: $DOWNLOAD_DIR"
+    echo "  版本: $VERSION"
+    echo "  static 文件夹: $static_status"
+    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
+    echo
+}
+
+# ============================================================================
+# 确认更新
+# ============================================================================
+confirm_update() {
+    if [ "$SKIP_CONFIRM" = true ]; then
+        return
+    fi
+    
+    read -p "确认执行更新? [y/N]: " confirm
+    if [[ ! $confirm =~ ^[Yy]$ ]]; then
+        log_info "用户取消更新"
+        exit 0
+    fi
+}
+
+# ============================================================================
+# 解析命令行参数
+# ============================================================================
+parse_args() {
+    while [[ $# -gt 0 ]]; do
+        case $1 in
+            -u|--user)
+                USERNAME="$2"
+                shift 2
+                ;;
+            -p|--password)
+                PASSWORD="$2"
+                shift 2
+                ;;
+            -d|--dir)
+                DOWNLOAD_DIR="$2"
+                shift 2
+                ;;
+            -v|--version)
+                VERSION="$2"
+                shift 2
+                ;;
+            -i|--include-static)
+                INCLUDE_STATIC=true
+                shift
+                ;;
+            -y|--yes)
+                SKIP_CONFIRM=true
+                shift
+                ;;
+            -s|--silent)
+                SILENT_MODE=true
+                shift
+                ;;
+            -h|--help)
+                show_help
+                exit 0
+                ;;
+            *)
+                log_error "未知选项: $1"
+                show_help
+                exit 1
+                ;;
+        esac
+    done
+}
+
+# ============================================================================
+# 主函数
+# ============================================================================
+main() {
+    # 解析命令行参数
+    parse_args "$@"
+    
+    # 初始化日志
+    init_log
+    
+    # 检查依赖
+    check_dependencies
+    
+    # 检查并发
+    check_lock
+    
+    # 获取用户输入
+    get_user_input
+    
+    # 验证路径
+    validate_path "$DOWNLOAD_DIR"
+    
+    # 测试服务器连接
+    test_server_connection
+    
+    # 选择版本
+    select_version
+    
+    # 验证版本存在
+    verify_version_exists "$VERSION"
+    
+    # 显示摘要
+    show_update_summary
+    
+    # 确认更新
+    confirm_update
+    
+    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
+    log_info "开始更新流程"
+    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
+    
+    # 备份当前版本
+    backup_current_version "$DOWNLOAD_DIR"
+    
+    # 下载并更新
+    download_and_update "$VERSION" "$DOWNLOAD_DIR"
+    
+    # 验证完整性
+    verify_integrity "$DOWNLOAD_DIR"
+    
+    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
+    log_success "更新完成!"
+    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
+    log_info "目标目录: $DOWNLOAD_DIR"
+    log_info "版本: $VERSION"
+    log_info "日志文件: $LOG_FILE"
+    
+    exit 0
+}
+
+# 运行主函数
+main "$@"