#!/bin/bash # 后台迁移最近 N 天的图片/语音到腾讯云 COS # 用法:在服务器上执行 nohup ./migrate-all-to-cos.sh > /tmp/migrate-cos.log 2>&1 & set -u BATCH_ENDPOINT="http://localhost:8082/api/v1/archive/cos-config/migrate-batch" STATUS_ENDPOINT="http://localhost:8082/api/v1/archive/cos-config/migrate-status" BATCH_SIZE=10 RECENT_DAYS=3 SLEEP_SECONDS=0 LOG_EVERY=50 echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始迁移最近 ${RECENT_DAYS} 天的图片/语音到 COS,批次大小 ${BATCH_SIZE}" # 先获取当前未迁移总数(最近 N 天) status=$(curl -s --max-time 30 "${STATUS_ENDPOINT}?recentDays=${RECENT_DAYS}") unmapped=$(echo "${status}" | grep -oP '"unmapped":\s*\K[0-9]+' || echo "0") echo "[$(date '+%Y-%m-%d %H:%M:%S')] 当前未迁移图片/语音(最近 ${RECENT_DAYS} 天):${unmapped}" if [ "${unmapped}" -eq 0 ]; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] 没有需要迁移的数据,退出" exit 0 fi # 计算需要扫描的最大偏移量 maxOffset=$(( (unmapped / BATCH_SIZE + 5) * BATCH_SIZE )) pass=0 totalMigrated=0 while true; do pass=$((pass + 1)) passMigrated=0 round=0 echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始第 ${pass} 轮扫描(最近 ${RECENT_DAYS} 天),maxOffset=${maxOffset}" for offset in $(seq 0 ${BATCH_SIZE} ${maxOffset}); do round=$((round + 1)) result=$(curl -s -X POST --max-time 60 "${BATCH_ENDPOINT}?offset=${offset}&batchSize=${BATCH_SIZE}&recentDays=${RECENT_DAYS}") code=$(echo "${result}" | grep -oP '"code":\s*\K[0-9]+' || echo "") count=$(echo "${result}" | grep -oP '"count":\s*\K[0-9]+' || echo "") if [ "${code}" != "0" ] || [ -z "${count}" ]; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] 第 ${pass} 轮第 ${round} 批(offset=${offset})调用失败: ${result}" else passMigrated=$((passMigrated + count)) totalMigrated=$((totalMigrated + count)) if [ "${count}" -gt 0 ]; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] 第 ${pass} 轮 offset=${offset} 迁移 ${count} 个,本轮累计 ${passMigrated},总累计 ${totalMigrated}" fi fi # 每 LOG_EVERY 批输出一次进度,避免日志看起来卡住 if [ $((round % LOG_EVERY)) -eq 0 ]; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] 第 ${pass} 轮进度:已处理 ${round} 批,当前 offset=${offset},本轮迁移 ${passMigrated} 个,总累计 ${totalMigrated} 个" fi sleep "${SLEEP_SECONDS}" done echo "[$(date '+%Y-%m-%d %H:%M:%S')] 第 ${pass} 轮扫描结束,本轮迁移 ${passMigrated} 个,总累计 ${totalMigrated} 个" # 本轮没有成功,结束任务 if [ "${passMigrated}" -eq 0 ]; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] 本轮无新增迁移,任务结束" break fi done # 最终状态 status=$(curl -s --max-time 30 "${STATUS_ENDPOINT}?recentDays=${RECENT_DAYS}") mapped=$(echo "${status}" | grep -oP '"mapped":\s*\K[0-9]+' || echo "0") unmapped=$(echo "${status}" | grep -oP '"unmapped":\s*\K[0-9]+' || echo "0") echo "[$(date '+%Y-%m-%d %H:%M:%S')] 最终状态:已映射 ${mapped},最近 ${RECENT_DAYS} 天未映射 ${unmapped}"