| |
| 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 |
|
|
| 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: |
| |
| 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 |
|
|
| 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 = "." |
| 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() |