
Byted Tos Openclaw Backup
- 34 installs
- 411 repo stars
- Updated August 4, 2026
- bytedance/agentkit-samples
byted-tos-openclaw-backup is a Claude skill that automatically backs up OpenClaw config, skills, and memory to a mounted TOS network drive in date-stamped directories.
About
This skill automatically backs up OpenClaw core config, skill files, and memory data to a mounted TOS network drive, organized into date-stamped directories. A developer uses it to create or restore environment backups while automatically skipping dependency directories and large executables. It provides backup, list, and restore scripts and a dry-run preview for restores.
- Backs up OpenClaw config, skill source, and memory to a mounted TOS drive
- Stores date-stamped backups and skips dependency dirs and binaries
- Supports restore with a --dry-run preview
Byted Tos Openclaw Backup by the numbers
- 34 all-time installs (skills.sh)
- Ranked #849 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
byted-tos-openclaw-backup capabilities & compatibility
Free; requires a TOS drive mounted in the OpenClaw workspace
- Capabilities
- backup · restore · config management
- Use cases
- devops
- Pricing
- Free
What byted-tos-openclaw-backup says it does
自动备份OpenClaw核心配置、技能文件和记忆数据到挂载的TOS网盘,按日期分类存储,自动跳过依赖目录和可执行文件。
每次备份自动创建新的日期目录,不会覆盖历史备份
npx skills add https://github.com/bytedance/agentkit-samples --skill byted-tos-openclaw-backupAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 34 |
|---|---|
| repo stars | ★ 411 |
| Last updated | August 4, 2026 |
| Repository | bytedance/agentkit-samples ↗ |
What it does
Back up and restore OpenClaw config, skills, and memory to a mounted TOS drive in date-stamped directories.
When should I use this skill?
You need to back up or restore OpenClaw config, skill source, or memory data to a mounted TOS drive.
What you get
Creates date-stamped backups of config, skills, and memory on a TOS drive and restores them on demand.
- backup_summary.txt
- backup_manifest.txt
By the numbers
- Provides 4 scripts (backup, config, list, restore)
- Backs up 4 content categories: config, system config, skills, memory
Files
OpenClaw 自动备份技能
此技能帮助你自动备份OpenClaw的核心配置、技能源码和记忆数据到挂载的TOS网盘,按日期创建备份目录,自动跳过依赖目录和大体积可执行文件。
何时使用
当用户要求执行以下操作时使用此技能:
- "备份OpenClaw配置"
- "备份技能文件"
- "备份到网盘"
- "创建系统备份"
- "定期备份"
备份策略
备份内容
1. 核心配置文件:工作区根目录下所有MD文档(AGENTS.md, SOUL.md, USER.md等) 2. 系统配置:/root/.openclaw/config/目录下的JSON/YAML/ENV/conf等配置文件,跳过二进制文件 3. 技能文件:扩展技能和工作区技能的源码文件(JS/TS/PY/MD/JSON/YAML/SH),自动跳过以下目录:
node_modules/venv/__pycache__/dist/build/
4. 记忆数据:/root/.openclaw/workspace/memory/目录下的所有记忆文件
存储结构
my-bucket/
└── openclaw_backup/
├── 2026-03-11/
│ ├── *.md # 核心配置文件
│ ├── config/ # 系统配置
│ ├── skills/
│ │ ├── extensions/ # 扩展技能源码
│ │ └── workspace/ # 工作区技能源码
│ ├── memory/ # 记忆数据
│ ├── backup_summary.txt # 备份统计信息
│ └── backup_manifest.txt # 完整文件清单
└── 2026-03-12/
└── ...指令
1. 执行完整备份
运行备份脚本自动完成所有备份操作:
scripts/backup.sh输出示例:
🔍 检测可用网盘...
✅ 自动选择存储桶: my-bucket (/root/.openclaw/workspace/my-bucket)
ℹ️ 所有可用存储桶:
- my-bucket: /root/.openclaw/workspace/my-bucket
💡 如需固定使用某个存储桶,请运行: bash scripts/config.sh <存储桶名称>
📂 创建备份目录: /root/.openclaw/workspace/my-bucket/openclaw_backup/2026-03-11
📝 备份核心配置文件 (MD文档)...
✅ 核心配置文件备份完成 (7 个文件)
⚙️ 备份系统配置 (仅配置文件,跳过二进制)...
🔍 扫描系统配置子目录...
✅ 备份目录: agents (大小: 228K, 文件数: 5)
✅ 备份目录: canvas (大小: 8.0K, 文件数: 1)
✅ 备份目录: completions (大小: 460K, 文件数: 4)
✅ 备份目录: cron (大小: 12K, 文件数: 2)
⚠️ 跳过目录: extensions (大小: 2.4G, 文件数: 67554 - 超过阈值)
✅ 备份目录: identity (大小: 8.0K, 文件数: 1)
⚠️ 跳过目录: logs (排除列表)
✅ 备份目录: memory (大小: 44K, 文件数: 5)
⚠️ 跳过目录: workspace (排除列表)
✅ 系统配置备份完成 (21 个文件)
🔧 备份技能文件 (仅源码文件,跳过node_modules等依赖目录)...
✅ 技能文件备份完成
🧠 备份记忆数据...
ℹ️ 记忆目录不存在,跳过记忆数据备份
✅ 记忆数据备份完成
📊 生成备份统计...
✅ 备份完成!
📦 备份桶: my-bucket
📂 备份路径: openclaw_backup/2026-03-11
📄 备份文件数: 463
💾 总大小: 3.6M
📋 备份摘要已保存到: backup_summary.txt
📑 完整文件清单已保存到: backup_manifest.txt2. 配置默认存储桶
固定使用某个存储桶进行备份:
scripts/config.sh <存储桶名称>示例:
scripts/config.sh my-bucket3. 检查备份历史
列出所有已创建的备份:
scripts/list_backups.sh输出示例:
📋 现有备份列表 (存储桶: my-bucket):
=====================================
📅 2026-03-11 (463 files, 3.6M)
📅 2026-03-10 (452 files, 3.4M)
📅 2026-03-09 (441 files, 3.2M)4. 恢复备份
从指定日期的备份恢复系统:
scripts/restore.sh <备份日期>预览恢复(不实际修改文件):
scripts/restore.sh 2026-03-11 --dry-run输出示例:
✅ 自动选择存储桶: my-bucket (/root/.openclaw/workspace/my-bucket)
📂 准备恢复备份: 2026-03-11
📦 存储桶: my-bucket
📂 备份路径: /root/.openclaw/workspace/my-bucket/openclaw_backup/2026-03-11
⚠️ 恢复操作会覆盖现有文件,确定要继续吗? (y/N) y
🔄 开始恢复...
📝 恢复核心配置文件...
⚙️ 恢复系统配置...
✅ 系统配置恢复完成
🔧 恢复技能文件...
✅ 技能文件恢复完成
🧠 恢复记忆数据...
✅ 记忆数据恢复完成
✅ 恢复完成!
📅 恢复的备份日期: 2026-03-11
⚠️ 建议重启OpenClaw服务以应用所有配置3. 反馈格式
向用户反馈备份结果时使用以下格式:
"✅ 备份已成功完成!
>
### 📦 备份详情
- 存储桶: my-bucket
- 备份路径: openclaw_backup/2026-03-11/- 备份文件数: 15,076 个
- 总大小: 922 MB
>
### 📋 备份内容包含:
1. 核心配置文件(工作区所有MD文档)
2. 系统配置(JSON/YAML/ENV等配置文件,跳过二进制文件)
3. 技能源码(JS/TS/PY/MD等源码文件,自动跳过依赖目录)
4. 记忆数据"
注意事项
1. 自动检测挂载的网盘,默认使用第一个检测到的存储桶 2. 如果未检测到网盘,提示用户在arkClaw界面配置TOS存储桶 3. 自动跳过可执行文件、依赖目录和大体积二进制文件 4. 每次备份自动创建新的日期目录,不会覆盖历史备份
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
#!/bin/bash
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# OpenClaw 自动备份脚本
# 功能:备份核心配置、技能文件和记忆数据到TOS网盘,按日期分类存储
set -euo pipefail
# 配置项
WORKSPACE_DIR="/root/.openclaw/workspace"
CONFIG_DIR="/root/.openclaw"
EXTENSIONS_DIR="/root/.openclaw/extensions"
SKILLS_DIR="/root/.openclaw/workspace/skills"
MEMORY_DIR="/root/.openclaw/workspace/memory"
BACKUP_ROOT="openclaw_backup"
DATE=$(date +%Y-%m-%d)
# 检测挂载的网盘
echo "🔍 检测可用网盘..."
MOUNT_ROOT="/root/.openclaw/workspace"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="$SCRIPT_DIR/../.config"
# 读取配置文件(如果存在)
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
if [ -n "${DEFAULT_BUCKET:-}" ] && [ -n "${MOUNT_POINT:-}" ]; then
# 验证配置的挂载点是否仍然有效
if df -P | grep -q "^.* $MOUNT_POINT$"; then
BUCKET_NAME="$DEFAULT_BUCKET"
echo "✅ 使用配置的默认存储桶: $BUCKET_NAME ($MOUNT_POINT)"
else
echo "⚠️ 配置的存储桶 $DEFAULT_BUCKET 已失效,重新检测可用存储桶"
unset DEFAULT_BUCKET
unset MOUNT_POINT
fi
fi
fi
# 如果没有有效的配置,自动检测
if [ -z "${MOUNT_POINT:-}" ]; then
# 检测所有挂载的网盘
mounts=$(df -P | grep "$MOUNT_ROOT" | awk '{print $NF}')
if [ -z "$mounts" ]; then
echo "❌ 未检测到挂载的网盘,请先在arkClaw界面配置TOS存储桶"
exit 1
fi
# 选择第一个可用的挂载点
MOUNT_POINT=$(echo "$mounts" | head -n 1)
BUCKET_NAME=$(basename "$MOUNT_POINT")
echo "✅ 自动选择存储桶: $BUCKET_NAME ($MOUNT_POINT)"
echo "ℹ️ 所有可用存储桶:"
echo "$mounts" | while read -r mp; do
echo " - $(basename "$mp"): $mp"
done
echo "💡 如需固定使用某个存储桶,请运行: bash scripts/config.sh <存储桶名称>"
fi
BACKUP_DIR="$MOUNT_POINT/$BACKUP_ROOT/$DATE"
# 创建备份目录
echo -e "\n📂 创建备份目录: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
# 备份核心配置文件
echo -e "\n📝 备份核心配置文件 (MD文档)..."
shopt -s nullglob
md_files=("$WORKSPACE_DIR"/*.md)
if [ ${#md_files[@]} -gt 0 ]; then
cp "${md_files[@]}" "$BACKUP_DIR/"
echo "✅ 核心配置文件备份完成 (${#md_files[@]} 个文件)"
else
echo "ℹ️ 无核心配置文件需要备份"
fi
shopt -u nullglob
# 备份系统配置
echo -e "\n⚙️ 备份系统配置 (仅配置文件,跳过二进制)..."
mkdir -p "$BACKUP_DIR/config"
if [ -d "$CONFIG_DIR" ]; then
config_count=0
mkdir -p "$BACKUP_DIR/config"
# 备份根目录配置文件
root_configs=$(find "$CONFIG_DIR" -maxdepth 1 -type f \( -name "*.json" -o -name "*.yaml" -o -name "*.yml" -o -name "*.conf" -o -name "*.env" -o -name "*.ini" -o -name "*.md" \))
root_count=$(echo "$root_configs" | grep -v '^$' | wc -l)
if [ "$root_count" -gt 0 ]; then
echo "$root_configs" | xargs cp -t "$BACKUP_DIR/config/"
config_count=$((config_count + root_count))
fi
# 遍历所有子目录,智能备份
echo "🔍 扫描系统配置子目录..."
for dir in "$CONFIG_DIR"/*/; do
dir_name=$(basename "$dir")
# 跳过不需要备份的大体积目录
if [[ "$dir_name" == "node_modules" || "$dir_name" == "venv" || "$dir_name" == "__pycache__" || "$dir_name" == "dist" || "$dir_name" == "build" || "$dir_name" == "logs" || "$dir_name" == "workspace" ]]; then
echo "⚠️ 跳过目录: $dir_name (排除列表)"
continue
fi
# 计算目录大小和文件数
dir_size=$(du -sh "$dir" | cut -f1)
file_count=$(find "$dir" -type f | wc -l)
# 智能判断是否备份:小于100MB且文件数少于1000个
size_num=$(echo "$dir_size" | sed 's/[MKG]//')
size_unit=$(echo "$dir_size" | sed 's/[0-9.]//g')
skip=false
if [[ "$size_unit" == "G" ]]; then
skip=true
elif [[ "$size_unit" == "M" && $(echo "$size_num > 100" | bc -l) -eq 1 ]]; then
skip=true
elif [[ "$file_count" -gt 1000 ]]; then
skip=true
fi
if [ "$skip" = true ]; then
echo "⚠️ 跳过目录: $dir_name (大小: $dir_size, 文件数: $file_count - 超过阈值)"
continue
fi
# 备份目录
echo "✅ 备份目录: $dir_name (大小: $dir_size, 文件数: $file_count)"
mkdir -p "$BACKUP_DIR/config/$dir_name"
cp -r "$dir"/* "$BACKUP_DIR/config/$dir_name/" 2>/dev/null
config_count=$((config_count + file_count))
done
if [ "$config_count" -gt 0 ]; then
echo "✅ 系统配置备份完成 ($config_count 个文件)"
else
echo "ℹ️ 无系统配置文件需要备份"
fi
else
echo "ℹ️ 系统配置目录不存在,跳过系统配置备份"
fi
# 备份技能文件
echo -e "\n🔧 备份技能文件 (仅源码文件,跳过node_modules等依赖目录)..."
mkdir -p "$BACKUP_DIR/skills/extensions"
mkdir -p "$BACKUP_DIR/skills/workspace"
# 备份扩展技能
find "$EXTENSIONS_DIR" -type f \( -name "*.js" -o -name "*.ts" -o -name "*.py" -o -name "*.md" -o -name "*.json" -o -name "*.yaml" -o -name "*.yml" -o -name "*.sh" -o -name "*.html" -o -name "*.css" \) \
-not -path "*/node_modules/*" \
-not -path "*/venv/*" \
-not -path "*/__pycache__/*" \
-not -path "*/dist/*" \
-not -path "*/build/*" \
-not -path "*/.git/*" \
-exec cp --parents {} "$BACKUP_DIR/skills/extensions/" \; 2>/dev/null
# 备份工作区技能
find "$SKILLS_DIR" -type f \( -name "*.js" -o -name "*.ts" -o -name "*.py" -o -name "*.md" -o -name "*.json" -o -name "*.yaml" -o -name "*.yml" -o -name "*.sh" -o -name "*.html" -o -name "*.css" \) \
-not -path "*/node_modules/*" \
-not -path "*/venv/*" \
-not -path "*/__pycache__/*" \
-not -path "*/dist/*" \
-not -path "*/build/*" \
-not -path "*/.git/*" \
-exec cp --parents {} "$BACKUP_DIR/skills/workspace/" \; 2>/dev/null
echo "✅ 技能文件备份完成"
# 备份记忆数据
echo -e "\n🧠 备份记忆数据..."
mkdir -p "$BACKUP_DIR/memory"
if [ -d "$MEMORY_DIR" ]; then
cp -r "$MEMORY_DIR"/* "$BACKUP_DIR/memory/" 2>/dev/null || echo "ℹ️ 无记忆数据需要备份"
else
echo "ℹ️ 记忆目录不存在,跳过记忆数据备份"
fi
echo "✅ 记忆数据备份完成"
# 生成备份统计
echo -e "\n📊 生成备份统计..."
BACKUP_SIZE=$(du -sh "$BACKUP_DIR" 2>/dev/null | cut -f1 || echo "计算中")
FILE_COUNT=$(find "$BACKUP_DIR" -type f 2>/dev/null | wc -l || echo "0")
# 生成备份摘要
SUMMARY_PATH="$BACKUP_DIR/backup_summary.txt"
cat > "$SUMMARY_PATH" << EOF
✅ 备份完成!
📦 备份桶: $BUCKET_NAME
📂 备份路径: $BACKUP_ROOT/$DATE
📄 备份文件数: $FILE_COUNT
💾 总大小: $BACKUP_SIZE
📅 备份时间: $(date '+%Y-%m-%d %H:%M:%S')
EOF
# 生成完整文件清单
MANIFEST_PATH="$BACKUP_DIR/backup_manifest.txt"
find "$BACKUP_DIR" -type f -exec ls -lh {} \; > "$MANIFEST_PATH" 2>/dev/null || true
# 输出结果
echo -e "\n✅ 备份完成!"
echo "📦 备份桶: $BUCKET_NAME"
echo "📂 备份路径: $BACKUP_ROOT/$DATE"
echo "📄 备份文件数: $FILE_COUNT"
echo "💾 总大小: $BACKUP_SIZE"
echo -e "\n📋 备份摘要已保存到: backup_summary.txt"
echo "📑 完整文件清单已保存到: backup_manifest.txt"
#!/bin/bash
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# 配置备份存储桶
# 用法: bash scripts/config.sh <存储桶名称>
set -euo pipefail
MOUNT_ROOT="/root/.openclaw/workspace"
CONFIG_FILE="$(dirname "$0")/../.config"
if [ $# -ne 1 ]; then
echo "用法: bash scripts/config.sh <存储桶名称>"
echo ""
echo "可用存储桶:"
df -P | grep "$MOUNT_ROOT" | awk '{print " - " $NF}' | xargs basename
exit 1
fi
TARGET_BUCKET="$1"
# 检查存储桶是否存在
MOUNT_POINT=$(df -P | grep "$MOUNT_ROOT" | awk '{print $NF}' | grep -E "/$TARGET_BUCKET$" | head -n 1)
if [ -z "$MOUNT_POINT" ]; then
echo "❌ 存储桶 '$TARGET_BUCKET' 不存在或未挂载"
echo "可用存储桶:"
df -P | grep "$MOUNT_ROOT" | awk '{print " - " $NF}' | xargs basename
exit 1
fi
# 保存配置
echo "DEFAULT_BUCKET=\"$TARGET_BUCKET\"" > "$CONFIG_FILE"
echo "MOUNT_POINT=\"$MOUNT_POINT\"" >> "$CONFIG_FILE"
echo "✅ 备份存储桶已配置为: $TARGET_BUCKET"
echo "📂 挂载路径: $MOUNT_POINT"
echo "ℹ️ 后续备份将自动使用此存储桶"
#!/bin/bash
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# 列出所有备份记录
set -e
WORKSPACE_DIR="/root/.openclaw/workspace"
BACKUP_ROOT="openclaw_backup"
# 检测挂载的网盘
MOUNT_ROOT="/root/.openclaw/workspace"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="$SCRIPT_DIR/../.config"
# 读取配置文件(如果存在)
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
if [ -n "${DEFAULT_BUCKET:-}" ] && [ -n "${MOUNT_POINT:-}" ]; then
# 验证配置的挂载点是否仍然有效
if df -P | grep -q "^.* $MOUNT_POINT$"; then
BUCKET_NAME="$DEFAULT_BUCKET"
echo "✅ 使用配置的默认存储桶: $BUCKET_NAME ($MOUNT_POINT)"
else
echo "⚠️ 配置的存储桶 $DEFAULT_BUCKET 已失效,重新检测可用存储桶"
unset DEFAULT_BUCKET
unset MOUNT_POINT
fi
fi
fi
# 如果没有有效的配置,自动检测
if [ -z "${MOUNT_POINT:-}" ]; then
# 检测所有挂载的网盘
mounts=$(df -P | grep "$MOUNT_ROOT" | awk '{print $NF}')
if [ -z "$mounts" ]; then
echo "❌ 未检测到挂载的网盘,请先在arkClaw界面配置TOS存储桶"
exit 1
fi
# 选择第一个可用的挂载点
MOUNT_POINT=$(echo "$mounts" | head -n 1)
BUCKET_NAME=$(basename "$MOUNT_POINT")
fi
BACKUP_BASE="$MOUNT_POINT/$BACKUP_ROOT"
if [ ! -d "$BACKUP_BASE" ]; then
echo "ℹ️ 暂无备份记录"
exit 0
fi
echo "📋 现有备份列表 (存储桶: $BUCKET_NAME):"
echo "====================================="
for backup_dir in "$BACKUP_BASE"/*/; do
if [ -d "$backup_dir" ]; then
date_name=$(basename "$backup_dir")
if [ -f "$backup_dir/backup_summary.txt" ]; then
file_count=$(grep "备份文件数" "$backup_dir/backup_summary.txt" | awk '{print $4}')
size=$(grep "总大小" "$backup_dir/backup_summary.txt" | awk '{print $4}')
echo "📅 $date_name ($file_count files, $size)"
else
file_count=$(find "$backup_dir" -type f | wc -l)
size=$(du -sh "$backup_dir" | cut -f1)
echo "📅 $date_name ($file_count files, $size)"
fi
fi
done
#!/bin/bash
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# 恢复备份脚本
# 用法: bash scripts/restore.sh <备份日期> [--dry-run]
set -euo pipefail
MOUNT_ROOT="/root/.openclaw/workspace"
BACKUP_ROOT="openclaw_backup"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="$SCRIPT_DIR/../.config"
DRY_RUN=false
if [ $# -lt 1 ]; then
echo "用法: bash scripts/restore.sh <备份日期> [--dry-run]"
echo ""
echo "示例:"
echo " bash scripts/restore.sh 2026-03-11 # 恢复2026-03-11的备份"
echo " bash scripts/restore.sh 2026-03-11 --dry-run # 预览恢复操作,不实际执行"
echo ""
echo "可用备份:"
bash "$SCRIPT_DIR/list_backups.sh"
exit 1
fi
BACKUP_DATE="$1"
if [ $# -eq 2 ] && [ "$2" = "--dry-run" ]; then
DRY_RUN=true
echo "🔍 预览模式:不会实际修改文件"
fi
# 读取配置文件(如果存在)
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
if [ -n "${DEFAULT_BUCKET:-}" ] && [ -n "${MOUNT_POINT:-}" ]; then
# 验证配置的挂载点是否仍然有效
if df -P | grep -q "^.* $MOUNT_POINT$"; then
BUCKET_NAME="$DEFAULT_BUCKET"
echo "✅ 使用配置的默认存储桶: $BUCKET_NAME ($MOUNT_POINT)"
else
echo "⚠️ 配置的存储桶 $DEFAULT_BUCKET 已失效,重新检测可用存储桶"
unset DEFAULT_BUCKET
unset MOUNT_POINT
fi
fi
fi
# 如果没有有效的配置,自动检测
if [ -z "${MOUNT_POINT:-}" ]; then
# 检测所有挂载的网盘
mounts=$(df -P | grep "$MOUNT_ROOT" | awk '{print $NF}')
if [ -z "$mounts" ]; then
echo "❌ 未检测到挂载的网盘,请先在arkClaw界面配置TOS存储桶"
exit 1
fi
# 选择第一个可用的挂载点
MOUNT_POINT=$(echo "$mounts" | head -n 1)
BUCKET_NAME=$(basename "$MOUNT_POINT")
echo "✅ 自动选择存储桶: $BUCKET_NAME ($MOUNT_POINT)"
fi
BACKUP_DIR="$MOUNT_POINT/$BACKUP_ROOT/$BACKUP_DATE"
if [ ! -d "$BACKUP_DIR" ]; then
echo "❌ 备份 $BACKUP_DATE 不存在"
echo "可用备份:"
bash "$SCRIPT_DIR/list_backups.sh"
exit 1
fi
echo "📂 准备恢复备份: $BACKUP_DATE"
echo "📦 存储桶: $BUCKET_NAME"
echo "📂 备份路径: $BACKUP_DIR"
if [ "$DRY_RUN" = true ]; then
echo ""
echo "🔍 预览恢复操作:"
echo " - 恢复核心配置文件到: /root/.openclaw/workspace/"
echo " - 恢复系统配置到: /root/.openclaw/"
echo " - 恢复技能文件到: /root/.openclaw/extensions/ 和 /root/.openclaw/workspace/skills/"
echo " - 恢复记忆数据到: /root/.openclaw/workspace/memory/"
echo ""
echo "📋 备份内容摘要:"
cat "$BACKUP_DIR/backup_summary.txt" 2>/dev/null || echo " 无摘要信息"
exit 0
fi
read -p "⚠️ 恢复操作会覆盖现有文件,确定要继续吗? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "❌ 已取消恢复"
exit 1
fi
echo ""
echo "🔄 开始恢复..."
# 恢复核心配置文件
echo "📝 恢复核心配置文件..."
cp "$BACKUP_DIR"/*.md /root/.openclaw/workspace/ 2>/dev/null || echo "ℹ️ 无核心配置文件需要恢复"
# 恢复系统配置
echo "⚙️ 恢复系统配置..."
if [ -d "$BACKUP_DIR/config" ]; then
cp -r "$BACKUP_DIR/config"/* /root/.openclaw/ 2>/dev/null
echo "✅ 系统配置恢复完成"
else
echo "ℹ️ 无系统配置需要恢复"
fi
# 恢复技能文件
echo "🔧 恢复技能文件..."
if [ -d "$BACKUP_DIR/skills/extensions" ]; then
cp -r "$BACKUP_DIR/skills/extensions/"* /root/.openclaw/extensions/ 2>/dev/null
fi
if [ -d "$BACKUP_DIR/skills/workspace" ]; then
cp -r "$BACKUP_DIR/skills/workspace/"* /root/.openclaw/workspace/skills/ 2>/dev/null
fi
echo "✅ 技能文件恢复完成"
# 恢复记忆数据
echo "🧠 恢复记忆数据..."
if [ -d "$BACKUP_DIR/memory" ]; then
mkdir -p /root/.openclaw/workspace/memory
cp -r "$BACKUP_DIR/memory"/* /root/.openclaw/workspace/memory/ 2>/dev/null
echo "✅ 记忆数据恢复完成"
else
echo "ℹ️ 无记忆数据需要恢复"
fi
echo ""
echo "✅ 恢复完成!"
echo "📅 恢复的备份日期: $BACKUP_DATE"
echo "⚠️ 建议重启OpenClaw服务以应用所有配置"