Spaces:
Sleeping
Sleeping
File size: 5,090 Bytes
fbd4b19 d26f1f4 3dc1e5c fbd4b19 d67c3c1 d26f1f4 1c86b45 3dc1e5c d26f1f4 1c86b45 d26f1f4 1c86b45 d26f1f4 1c86b45 d26f1f4 3dc1e5c fbd4b19 d26f1f4 fbd4b19 d26f1f4 fbd4b19 1c86b45 fbd4b19 d26f1f4 fbd4b19 1c86b45 d26f1f4 fbd4b19 1c86b45 fbd4b19 d26f1f4 fbd4b19 d26f1f4 fbd4b19 d26f1f4 fbd4b19 | 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 | #!/usr/bin/env python3
import os
import sys
import shutil
import json
import sqlite3
import tarfile
import tempfile
import subprocess
import datetime
from huggingface_hub import HfApi, login, hf_hub_download
DB_TARGET = "/app/server/data/freeapi.db"
DATASET_REPO = "lydgs/freellm-backup"
CONFIG_PREFIX = "config_export"
BACKUP_PREFIX = "freeapi_backup"
def import_json_to_db(json_dir, db_path):
"""从 JSON 文件目录重建数据库"""
if not os.path.exists(json_dir):
return False
os.makedirs(os.path.dirname(db_path), exist_ok=True)
if os.path.exists(db_path):
os.remove(db_path)
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
for json_file in os.listdir(json_dir):
if not json_file.endswith('.json'):
continue
table_name = json_file[:-5]
with open(os.path.join(json_dir, json_file), 'r', encoding='utf-8') as f:
data = json.load(f)
if not data:
continue
# 获取列名
columns = list(data[0].keys())
# 创建表
cursor.execute(f"DROP TABLE IF EXISTS {table_name}")
cursor.execute(f"CREATE TABLE {table_name} ({', '.join(columns)})")
# 插入数据
placeholders = ', '.join('?' for _ in columns)
for row in data:
values = [row[col] for col in columns]
cursor.execute(f"INSERT INTO {table_name} VALUES ({placeholders})", values)
conn.commit()
conn.close()
return True
def restore_from_json():
"""优先尝试从 JSON 包恢复,成功返回 True"""
token = os.getenv("HF_TOKEN")
if not token:
return False
login(token=token)
api = HfApi()
try:
files = api.list_repo_files(repo_id=DATASET_REPO, repo_type="dataset")
config_files = [f for f in files if f.startswith(CONFIG_PREFIX) and f.endswith('.tar.gz')]
if not config_files:
return False
config_files.sort(reverse=True)
latest_config = config_files[0]
print(f"🔄 发现 JSON 配置包: {latest_config},重建数据库...")
with tempfile.TemporaryDirectory() as tmpdir:
downloaded = hf_hub_download(
repo_id=DATASET_REPO,
filename=latest_config,
repo_type="dataset",
local_dir=tmpdir
)
extract_dir = os.path.join(tmpdir, "extract")
os.makedirs(extract_dir, exist_ok=True)
with tarfile.open(downloaded, "r:gz") as tar:
tar.extractall(extract_dir)
if import_json_to_db(extract_dir, DB_TARGET):
print(f"✅ 数据库从 JSON 配置重建成功: {DB_TARGET}")
return True
else:
print("⚠️ JSON 导入失败")
return False
except Exception as e:
print(f"⚠️ JSON 恢复出错: {e}")
return False
def restore_from_binary():
"""回退:从二进制 .db 文件恢复"""
token = os.getenv("HF_TOKEN")
if not token:
return False
login(token=token)
api = HfApi()
try:
files = api.list_repo_files(repo_id=DATASET_REPO, repo_type="dataset")
db_files = [f for f in files if f.endswith(".db") and f.startswith(BACKUP_PREFIX)]
if not db_files:
return False
db_files.sort()
latest = db_files[-1]
print(f"🔄 使用二进制备份恢复: {latest}")
downloaded = hf_hub_download(
repo_id=DATASET_REPO,
filename=latest,
repo_type="dataset",
local_dir="/tmp"
)
os.makedirs(os.path.dirname(DB_TARGET), exist_ok=True)
shutil.copy(downloaded, DB_TARGET)
print(f"✅ 数据库从二进制备份恢复成功: {DB_TARGET}")
os.remove(downloaded)
return True
except Exception as e:
print(f"❌ 二进制恢复失败: {e}")
return False
def create_full_backup():
"""调用备份脚本,生成完整的 .db 和 JSON 包"""
backup_script = "/app/scripts/backup_to_dataset.py"
if not os.path.exists(backup_script):
print("⚠️ 备份脚本不存在,无法创建初始备份")
return False
try:
subprocess.run(["python3", backup_script], check=True)
print("✅ 已执行完整备份(包括 JSON 包)")
return True
except subprocess.CalledProcessError as e:
print(f"❌ 执行备份脚本失败: {e}")
return False
def restore_latest_backup():
# 1. 优先尝试 JSON 恢复
if restore_from_json():
return
# 2. 回退到二进制恢复
if restore_from_binary():
return
# 3. 完全无备份,但本地数据库存在 -> 创建完整备份
if os.path.exists(DB_TARGET):
print("🔄 无任何备份,检测到本地数据库,将创建完整备份(包括 JSON 包)...")
create_full_backup()
else:
print("ℹ️ 本地数据库也不存在,跳过恢复")
if __name__ == "__main__":
restore_latest_backup() |