openclaw / scripts /sync.py
zngw's picture
脚本bug
113c740
Raw
History Blame Contribute Delete
4.79 kB
#!/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()