Buckets:
| set -euo pipefail | |
| if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then | |
| echo "用法:bash restore.sh [目录] [--dry-run]" | |
| echo "默认目录:脚本所在目录;默认 bucket:ACCC1380/molab-checkpoints" | |
| echo "可通过 HF_BUCKET 指定其他 bucket;HF_TOKEN 或目录中的 .env 提供认证。" | |
| echo "--dry-run 只预览,不传输文件。" | |
| exit 0 | |
| fi | |
| script_root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" | |
| transfer_python="${SYSTEM_PYTHON:-/usr/local/bin/python}" | |
| if ! env -u PYTHONPATH "$transfer_python" -c 'from huggingface_hub import sync_bucket' >/dev/null 2>&1; then | |
| env -u PYTHONPATH "$transfer_python" -m pip install 'huggingface_hub>=1.9,<2' | |
| fi | |
| env -u PYTHONPATH "$transfer_python" - restore "$script_root" "$@" <<'BUCKET_PY' | |
| import argparse | |
| import os | |
| import re | |
| import stat | |
| import sys | |
| from pathlib import Path | |
| from huggingface_hub import HfApi, get_token, sync_bucket | |
| mode, default_root = sys.argv[1:3] | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("directory", nargs="?", default=default_root) | |
| parser.add_argument("--dry-run", action="store_true") | |
| args = parser.parse_args(sys.argv[3:]) | |
| root = Path(args.directory).expanduser().resolve() | |
| if mode == "backup" and not root.is_dir(): | |
| parser.error(f"备份目录不存在:{root}") | |
| bucket = os.environ.get("HF_BUCKET", "ACCC1380/molab-checkpoints") | |
| bucket = bucket.removeprefix("hf://buckets/").removeprefix("buckets/").rstrip("/") | |
| if len(bucket.split("/")) != 2: | |
| parser.error("HF_BUCKET 格式必须为 namespace/bucket") | |
| uri = "hf://buckets/" + bucket | |
| # Read credentials without executing .env as shell code or printing the token. | |
| token = get_token() | |
| if not token and (root / ".env").is_file(): | |
| for line in (root / ".env").read_text().splitlines(): | |
| match = re.match(r"(?:export\s+)?(?:HF_TOKEN|HUGGING_FACE_HUB_TOKEN)\s*=\s*['\"]?(hf_[A-Za-z0-9]+)", line.strip()) | |
| if match: | |
| token = match.group(1) | |
| break | |
| api = HfApi(token=token) | |
| # Check access before deleting any local generated files. | |
| api.bucket_info(bucket) | |
| if mode == "backup": | |
| if not token: | |
| raise SystemExit("上传需要认证:设置 HF_TOKEN,或在目录 .env 中设置 HF_TOKEN。") | |
| api.whoami() | |
| exclude = [ | |
| "codex-oneclick-kaggle.sh", "**/codex-oneclick-kaggle.sh", | |
| # Authentication state is recreated on the restored machine. | |
| "ComfyUI/login", "ComfyUI/login/**", | |
| "PASSWORD", "**/PASSWORD", "PASSWORD.*", "**/PASSWORD.*", | |
| ".secret-key.txt", "**/.secret-key.txt", ".secret-key.txt.*", "**/.secret-key.txt.*", | |
| "login.txt", "**/login.txt", "credentials.txt", "**/credentials.txt", | |
| "credentials.json", "**/credentials.json", | |
| "comfyui-login", "comfyui-login/**", "**/comfyui-login", "**/comfyui-login/**", | |
| "comfyui-admin", "comfyui-admin/**", "**/comfyui-admin", "**/comfyui-admin/**", | |
| ".ssh", ".ssh/**", "**/.ssh", "**/.ssh/**", | |
| ".git", ".git/**", "**/.git", "**/.git/**", | |
| "ComfyUI/input/**", "ComfyUI/output/**", "comfyui-output/**", | |
| "notebook.py", "**/notebook.py", | |
| "comfyui.log", "comfyui.pid", "comfyui-install.log", "qwen-download.log", | |
| "ComfyUI/temp/**", "ComfyUI/user/*.db*", "ComfyUI/user/*.log", | |
| ".env", ".env.*", "**/.env", "**/.env.*", | |
| "**/__pycache__/**", "__pycache__/**", "__marimo__/**", | |
| "**/.ipynb_checkpoints/**", ".ipynb_checkpoints/**", | |
| ".venv/**", "venv/**", "**/.venv/**", "**/venv/**", | |
| ".cache/**", "**/.cache/**", "*.part", "**/*.part", | |
| "sd-webui-forge-neo/cache/**", | |
| "sd-webui-forge-neo/extensions/sd-webui-infinite-image-browsing/iib.db*", | |
| "sd-webui-forge-neo/tmp/**", "sd-webui-forge-neo/output/**", | |
| "sd-webui-forge-neo/outputs/**", | |
| ] | |
| source, dest = (str(root), uri) if mode == "backup" else (uri, str(root)) | |
| print(f"{source} -> {dest}", flush=True) | |
| result = sync_bucket(source, dest, token=token, exclude=exclude, dry_run=args.dry_run) | |
| print(result.summary(), flush=True) | |
| if args.dry_run: | |
| print("预览完成;未传输文件。") | |
| raise SystemExit(0) | |
| if mode == "restore": | |
| models = root / "sd-webui-forge-neo" / "models" | |
| models.mkdir(parents=True, exist_ok=True) | |
| for kind in ("Stable-diffusion", "Lora"): | |
| link = models / kind | |
| if link.is_symlink(): | |
| link.unlink() | |
| if link.is_dir() and not any(link.iterdir()): | |
| link.rmdir() | |
| if not link.exists(): | |
| link.symlink_to("../../" + kind, target_is_directory=True) | |
| else: | |
| print(f"保留已有目录:{link}") | |
| for relative in ("backup.sh", "restore.sh", "restore-model-links.sh", "start.sh", "comfyui.sh", | |
| "sd-webui-forge-neo/start.sh", | |
| "sd-webui-forge-neo/webui.sh", "sd-webui-forge-neo/webui-user.sh"): | |
| file = root / relative | |
| if file.is_file(): | |
| file.chmod(file.stat().st_mode | stat.S_IXUSR) | |
| print("恢复完成。先以 root 运行 bash comfyui.sh --setup-only 安装依赖并生成新登录密码,再运行 bash comfyui.sh。密码查看:sudo cat /var/lib/comfyui-admin/login.txt。") | |
| else: | |
| print("备份完成。目标中其他文件保留;.env、Forge 出图和运行缓存未上传;本地文件未删除。") | |
| BUCKET_PY | |
Xet Storage Details
- Size:
- 5.25 kB
- Xet hash:
- 6120337ffc47a35fa69a3aee6b5304822a461061300ca12158f773475955ce1b
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.