Spaces:
Runtime error
Runtime error
File size: 4,785 Bytes
8bf79eb 162d054 8bf79eb 162d054 8bf79eb 162d054 113c740 162d054 8bf79eb 162d054 8bf79eb 162d054 8bf79eb 162d054 8bf79eb 162d054 8bf79eb 162d054 8bf79eb 162d054 8bf79eb 162d054 8bf79eb 162d054 8bf79eb 162d054 8bf79eb cb13021 162d054 8bf79eb 162d054 8bf79eb | 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 | #!/usr/bin/env python3
import os
import sys
import tarfile
from huggingface_hub import HfApi, hf_hub_download
# 配置常量
BACKUP_DIR = "/root/.openclaw"
BACKUP_FILENAME = "backup.tar.gz"
def restore():
repo_id = os.getenv("HF_DATASET")
token = os.getenv("HF_TOKEN")
if not repo_id or not token:
print("--- [SYNC] 跳过恢复: 未配置 HF_DATASET 或 HF_TOKEN ---")
return True # 返回 True 表示流程继续,只是没恢复数据
try:
print(f"--- [SYNC] 启动恢复流程, 目标仓库: {repo_id} ---")
api = HfApi()
# 获取文件列表
files = api.list_repo_files(repo_id=repo_id, repo_type="dataset", token=token)
if BACKUP_FILENAME in files:
print(f"--- [SYNC] 发现备份文件: {BACKUP_FILENAME}, 正在下载... ---")
# 下载到本地临时位置
downloaded_path = hf_hub_download(
repo_id=repo_id,
filename=BACKUP_FILENAME,
repo_type="dataset",
token=token,
force_download=True # 确保每次都是最新的
)
extract_path = BACKUP_DIR
print(f"--- [SYNC] 正在解压至 {extract_path} ... ---")
with tarfile.open(downloaded_path, "r:gz") as tar:
# 安全解压逻辑 (兼容旧版本 Python)
def is_within_directory(directory, target):
abs_directory = os.path.abspath(directory)
abs_target = os.path.abspath(target)
prefix = os.path.commonprefix([abs_directory, abs_target])
return prefix == abs_directory
for member in tar.getmembers():
member_path = os.path.join(extract_path, member.name)
if not is_within_directory(extract_path, member_path):
raise Exception(f"尝试跳出目录的攻击行为: {member.name}")
tar.extractall(path=extract_path)
print(f"--- [SYNC] 恢复成功! 数据已覆盖至 {extract_path} ---")
return True
else:
# 修正日志:不再谎称检查了时间
print("--- [SYNC] 未在仓库中找到备份文件,将使用空状态启动 ---")
return True
except Exception as e:
print(f"--- [SYNC] 恢复异常: {e} ---")
import traceback
traceback.print_exc()
return True # 即使失败也返回 True,避免阻塞启动
def backup():
repo_id = os.getenv("HF_DATASET")
token = os.getenv("HF_TOKEN")
if not repo_id or not token:
print("--- [SYNC] 跳过备份: 未配置 HF_DATASET 或 HF_TOKEN ---")
return
try:
print(f"--- [SYNC] 正在执行全量备份: {BACKUP_FILENAME} ---")
base_path = BACKUP_DIR
if not os.path.exists(base_path):
print(f"--- [SYNC] 警告: 备份目录 {base_path} 不存在,跳过打包 ---")
# 即使目录不存在,也可以上传一个空的标记文件或者直接返回,这里选择返回
return
# 创建临时压缩包
with tarfile.open(BACKUP_FILENAME, "w:gz") as tar:
# 修复点:将 arcname 设置为 '.',这样解压后直接是 .openclaw 的内容,
# 或者设置为 os.path.basename(base_path) 保留文件夹名。
# 通常为了还原方便,我们希望在 .openclaw 目录下直接看到内容,所以用 '.'
# 如果希望解压出来是 /root/.openclaw/.openclaw/... 则用 basename
arcname = "."
tar.add(base_path, arcname=arcname)
print(f"--- [SYNC] 本地打包完成,大小: {os.path.getsize(BACKUP_FILENAME) / 1024 / 1024:.2f} MB ---")
api = HfApi()
print(f"--- [SYNC] 正在上传至 Hugging Face ({repo_id}) ... ---")
api.upload_file(
path_or_fileobj=BACKUP_FILENAME,
path_in_repo=BACKUP_FILENAME,
repo_id=repo_id,
repo_type="dataset",
token=token
)
print(f"--- [SYNC] 备份上传成功! ---")
# 清理本地临时备份文件以节省空间
if os.path.exists(BACKUP_FILENAME):
os.remove(BACKUP_FILENAME)
print("--- [SYNC] 本地临时文件已清理 ---")
except Exception as e:
print(f"--- [SYNC] 备份失败: {e} ---")
import traceback
traceback.print_exc()
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == "backup":
backup()
else:
restore() |