File size: 13,536 Bytes
7f2e1a6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 | #!/bin/bash
# OCNGX 迁移工具
# 用于在不同 HuggingFace Spaces 之间快速迁移系统
set -euo pipefail
# 配置变量
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MIGRATION_LOG="/tmp/ocngx_migration_$(date +%s).log"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$MIGRATION_LOG"
}
log_info() {
echo -e "${BLUE}[INFO]${NC} $1" | tee -a "$MIGRATION_LOG"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1" | tee -a "$MIGRATION_LOG"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1" | tee -a "$MIGRATION_LOG"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1" | tee -a "$MIGRATION_LOG"
}
# 显示帮助信息
usage() {
echo "OCNGX 迁移工具 - 在不同 HuggingFace Spaces 之间迁移系统"
echo ""
echo "用法: $0 [选项] <源Space> <目标Space>"
echo ""
echo "参数:"
echo " <源Space> 源 HuggingFace Space 名称"
echo " <目标Space> 目标 HuggingFace Space 名称"
echo ""
echo "选项:"
echo " -b, --backup-only 仅创建备份,不执行迁移"
echo " -r, --restore-only 仅恢复备份,不创建新备份"
echo " -k, --keep-backup 保留本地备份文件"
echo " -f, --force 强制覆盖目标配置"
echo " -d, --dry-run 模拟运行,不执行实际操作"
echo " -h, --help 显示帮助信息"
echo ""
echo "示例:"
echo " $0 source-space target-space"
echo " $0 --backup-only source-space"
echo " $0 --restore-only --force target-space backup.tar.gz"
echo ""
exit 1
}
# 解析命令行参数
SOURCE_SPACE=""
TARGET_SPACE=""
BACKUP_ONLY=false
RESTORE_ONLY=false
KEEP_BACKUP=false
FORCE_MODE=false
DRY_RUN=false
BACKUP_FILE=""
while [[ $# -gt 0 ]]; do
case $1 in
-b|--backup-only)
BACKUP_ONLY=true
shift
;;
-r|--restore-only)
RESTORE_ONLY=true
shift
;;
-k|--keep-backup)
KEEP_BACKUP=true
shift
;;
-f|--force)
FORCE_MODE=true
shift
;;
-d|--dry-run)
DRY_RUN=true
shift
;;
-h|--help)
usage
;;
-*)
log_error "未知选项: $1"
usage
;;
*)
if [[ -z "$SOURCE_SPACE" ]]; then
SOURCE_SPACE="$1"
elif [[ -z "$TARGET_SPACE" ]]; then
TARGET_SPACE="$1"
elif [[ -z "$BACKUP_FILE" ]]; then
BACKUP_FILE="$1"
else
log_error "参数过多"
usage
fi
shift
;;
esac
done
# 验证参数
validate_parameters() {
log_info "验证参数..."
if [[ "$RESTORE_ONLY" == true ]]; then
if [[ -z "$TARGET_SPACE" && -z "$BACKUP_FILE" ]]; then
log_error "恢复模式需要指定目标Space或备份文件"
usage
fi
else
if [[ -z "$SOURCE_SPACE" || -z "$TARGET_SPACE" ]]; then
log_error "必须指定源Space和目标Space"
usage
fi
fi
log_success "参数验证通过"
}
# 检测当前环境
detect_current_environment() {
log_info "检测当前环境..."
if [[ -n "${SPACE_ID:-}" ]]; then
CURRENT_ENV="huggingface"
CURRENT_SPACE="$SPACE_ID"
log_info "当前环境: HuggingFace Space ($CURRENT_SPACE)"
elif [[ -f /.dockerenv ]]; then
CURRENT_ENV="docker"
CURRENT_SPACE="docker-container"
log_info "当前环境: Docker 容器"
else
CURRENT_ENV="local"
CURRENT_SPACE="local-machine"
log_info "当前环境: 本地机器"
fi
}
# 检查网络连接
check_network_connectivity() {
log_info "检查网络连接..."
# 检查 HuggingFace 连通性
if curl -s --connect-timeout 10 https://huggingface.co >/dev/null 2>&1; then
log_success "HuggingFace 连接正常"
else
log_error "无法连接到 HuggingFace"
exit 1
fi
}
# 创建源Space备份
create_source_backup() {
log_info "在源Space创建备份: $SOURCE_SPACE"
if [[ "$DRY_RUN" == true ]]; then
log_warning "[DRY-RUN] 模拟在 $SOURCE_SPACE 创建备份"
return
fi
# 这里需要SSH或API方式连接到源Space
# 实际实现取决于具体的访问方式
local source_url="https://$SOURCE_SPACE.hf.space"
log_info "源Space URL: $source_url"
# 方案1: 通过SSH访问(如果支持)
# ssh user@$SOURCE_SPACE.hf.space "./backup-scripts/backup.sh"
# 方案2: 通过API触发备份
# curl -X POST "$source_url/api/backup"
# 方案3: 通过HuggingFace CLI
# huggingface-cli space create-backup $SOURCE_SPACE
# 临时方案: 假设可以SSH访问
log_warning "需要手动在源Space执行: ./backup-scripts/backup.sh"
log_info "等待用户确认备份已完成..."
read -p "确认备份已完成? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
log_success "源Space备份已确认"
else
log_error "备份未完成,终止迁移"
exit 1
fi
}
# 下载备份文件
download_backup() {
log_info "下载备份文件..."
if [[ "$DRY_RUN" == true ]]; then
log_warning "[DRY-RUN] 模拟下载备份文件"
return
fi
# 这里需要实现从源Space下载备份的逻辑
# 可能的实现方式:
# 1. 通过SCP下载
# scp user@$SOURCE_SPACE.hf.space:/var/backups/ocngx/latest.tar.gz ./
# 2. 通过HTTP下载
# wget "$source_url/download/backup/latest.tar.gz"
# 3. 通过HuggingFace API下载
# huggingface-cli space download-backup $SOURCE_SPACE
# 临时方案: 假设用户已手动下载
log_warning "需要手动从源Space下载备份文件到当前目录"
log_info "备份文件通常位于: /var/backups/ocngx/ocngx_backup_*.tar.gz"
read -p "请输入备份文件路径: " backup_path
if [[ -f "$backup_path" ]]; then
BACKUP_FILE="$backup_path"
log_success "备份文件已找到: $BACKUP_FILE"
else
log_error "备份文件不存在: $backup_path"
exit 1
fi
}
# 准备目标Space
prepare_target_space() {
log_info "准备目标Space: $TARGET_SPACE"
if [[ "$DRY_RUN" == true ]]; then
log_warning "[DRY-RUN] 模拟准备目标Space"
return
fi
# 1. 检查目标Space是否存在
local target_url="https://$TARGET_SPACE.hf.space"
log_info "目标Space URL: $target_url"
# 2. 部署基础代码到目标Space
log_info "部署基础代码到目标Space..."
# 这里需要实现部署逻辑
# 可能的实现方式:
# 1. 通过Git部署
# git clone <项目仓库> target-deploy
# cd target-deploy
# git remote set-url origin git@hf.co:spaces/$TARGET_SPACE
# git push origin main
# 2. 通过HuggingFace CLI部署
# huggingface-cli space create $TARGET_SPACE --space-type docker
# 临时方案: 假设用户已手动部署
log_warning "需要手动将项目代码部署到目标Space: $TARGET_SPACE"
log_info "步骤:"
log_info "1. 创建新的Space: https://huggingface.co/new-space"
log_info "2. 克隆当前项目代码"
log_info "3. 推送到新Space"
read -p "确认目标Space已准备完成? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
log_success "目标Space准备已确认"
else
log_error "目标Space未准备完成,终止迁移"
exit 1
fi
}
# 配置目标环境
configure_target_environment() {
log_info "配置目标环境..."
if [[ "$DRY_RUN" == true ]]; then
log_warning "[DRY-RUN] 模拟配置目标环境"
return
fi
# 这里需要在目标Space上执行环境配置
# 类似于 prepare_target_space 的逻辑
log_warning "需要手动在目标Space配置环境:"
log_info "1. SSH连接到目标Space"
log_info "2. 设置环境变量: export SPACE_ID=$TARGET_SPACE"
log_info "3. 运行: source deploy-config.sh && configure_for_deployment"
read -p "确认环境配置已完成? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
log_success "目标环境配置已确认"
else
log_error "环境配置未完成,终止迁移"
exit 1
fi
}
# 恢复数据到目标Space
restore_to_target() {
log_info "恢复数据到目标Space..."
if [[ "$DRY_RUN" == true ]]; then
log_warning "[DRY-RUN] 模拟恢复数据到目标Space"
return
fi
# 上传备份文件到目标Space
log_info "上传备份文件到目标Space..."
# 实现上传逻辑
# scp backup.tar.gz user@$TARGET_SPACE.hf.space:/tmp/
# 在目标Space执行恢复
log_info "在目标Space执行数据恢复..."
# 实现恢复逻辑
# ssh user@$TARGET_SPACE.hf.space "./backup-scripts/restore.sh --force /tmp/backup.tar.gz"
log_warning "需要手动在目标Space执行:"
log_info "1. 上传备份文件: scp $BACKUP_FILE user@$TARGET_SPACE.hf.space:/tmp/"
log_info "2. SSH连接到目标Space"
log_info "3. 运行: ./backup-scripts/restore.sh --force /tmp/$(basename $BACKUP_FILE)"
read -p "确认数据恢复已完成? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
log_success "数据恢复已确认"
else
log_error "数据恢复未完成,终止迁移"
exit 1
fi
}
# 验证迁移结果
verify_migration() {
log_info "验证迁移结果..."
local target_url="https://$TARGET_SPACE.hf.space"
# 检查目标Space健康状态
if curl -s --connect-timeout 10 "$target_url/health" >/dev/null 2>&1; then
log_success "目标Space健康检查通过"
else
log_warning "目标Space健康检查失败,请手动验证"
fi
# 检查OpenCode状态
if curl -s --connect-timeout 10 "$target_url/global/health" >/dev/null 2>&1; then
log_success "OpenCode服务状态正常"
else
log_warning "OpenCode服务状态异常,请手动检查"
fi
}
# 清理临时文件
cleanup() {
log_info "清理临时文件..."
if [[ "$KEEP_BACKUP" != true ]] && [[ -n "$BACKUP_FILE" ]] && [[ -f "$BACKUP_FILE" ]]; then
if [[ "$DRY_RUN" != true ]]; then
rm -f "$BACKUP_FILE"
log_success "已清理备份文件: $BACKUP_FILE"
fi
fi
# 清理日志文件
# rm -f "$MIGRATION_LOG"
}
# 生成迁移报告
generate_report() {
log_info "生成迁移报告..."
local report_file="migration_report_$(date +%Y%m%d_%H%M%S).txt"
cat > "$report_file" << EOF
OCNGX 迁移报告
===============
迁移时间: $(date '+%Y-%m-%d %H:%M:%S')
源Space: $SOURCE_SPACE
目标Space: $TARGET_SPACE
备份文件: $BACKUP_FILE
当前环境: $CURRENT_ENV ($CURRENT_SPACE)
迁移参数:
- 强制模式: $FORCE_MODE
- 仅备份: $BACKUP_ONLY
- 仅恢复: $RESTORE_ONLY
- 保留备份: $KEEP_BACKUP
- 模拟运行: $DRY_RUN
迁移日志:
$(cat "$MIGRATION_LOG")
后续步骤:
1. 访问目标Space: https://$TARGET_SPACE.hf.space
2. 验证所有功能正常
3. 更新DNS或代理配置(如需要)
4. 通知用户迁移完成
注意事项:
- 请保留此报告用于记录
- 建议在迁移后24小时内监控系统状态
- 如有问题,请检查迁移日志
EOF
log_success "迁移报告已生成: $report_file"
}
# 主迁移流程
execute_migration() {
log_info "开始迁移流程..."
log_info "源Space: $SOURCE_SPACE -> 目标Space: $TARGET_SPACE"
if [[ "$BACKUP_ONLY" == true ]]; then
create_source_backup
download_backup
log_success "备份完成"
return
fi
if [[ "$RESTORE_ONLY" == true ]]; then
if [[ -z "$TARGET_SPACE" ]]; then
# 本地恢复模式
log_info "本地恢复模式"
if [[ -z "$BACKUP_FILE" ]]; then
log_error "本地恢复需要指定备份文件"
exit 1
fi
./backup-scripts/restore.sh ${FORCE_MODE:+--force} "$BACKUP_FILE"
else
prepare_target_space
configure_target_environment
restore_to_target
fi
verify_migration
log_success "恢复完成"
return
fi
# 完整迁移流程
create_source_backup
download_backup
prepare_target_space
configure_target_environment
restore_to_target
verify_migration
log_success "迁移完成!"
}
# 错误处理
handle_error() {
log_error "迁移过程中发生错误"
cleanup
exit 1
}
# 主函数
main() {
echo "🚀 OCNGX 迁移工具"
echo "=================="
validate_parameters
detect_current_environment
check_network_connectivity
trap handle_error ERR
execute_migration
generate_report
cleanup
echo ""
log_success "迁移流程执行完成!"
echo "📊 迁移日志: $MIGRATION_LOG"
echo "📋 如有疑问,请查看迁移报告"
}
# 执行主函数
main "$@" |