diff --git a/scripts/backup.sh b/scripts/backup.sh index 601009e..1140641 100755 --- a/scripts/backup.sh +++ b/scripts/backup.sh @@ -1,130 +1,56 @@ #!/bin/bash -# ====== 织忆备份脚本 ====== -# 备份到 server Gitea(http://192.168.123.11:3000) -# 用法:./backup.sh [commit_message] -# 自动:每天 03:00(见 cron 配置) +# 织忆每日备份脚本(由 cronjob 每天 04:00 调用) +# 直接执行备份,不走 Go HTTP API set -e -DATE=$(date +%Y%m%d_%H%M%S) -LOG_FILE="${HOME}/.hermes/logs/backup.log" +API_KEY="zhiyi-dev-key-2026" +BACKUP_ROOT="/home/muc/backups/memoryweave" +DATA_DIR="/var/lib/memoryweave" +TIMESTAMP=$(date +%Y%m%d-%H%M%S) +BACKUP_DIR="$BACKUP_ROOT/$TIMESTAMP" -# 项目根目录(backup.sh 同级) -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +echo "[$TIMESTAMP] 织忆备份开始..." -# 备份临时目录 -BACKUP_DIR="/tmp/zhiyi_backup_${DATE}" -CONFIG_DIR="/tmp/zhiyi_config_${DATE}" +# 1. 创建备份目录 +mkdir -p "$BACKUP_DIR" -# 日志 -log() { - echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" -} - -log "===== 备份开始: ${DATE} =====" - -# 1. 备份数据文件 -log "[1/6] 备份数据文件..." -mkdir -p "${BACKUP_DIR}" -sudo rsync -a /var/lib/memoryweave/ "${BACKUP_DIR}/memoryweave/" --quiet -DATA_SIZE=$(du -sh "${BACKUP_DIR}" | cut -f1) -log " 数据备份完成: ${DATA_SIZE}" - -# 2. 打包 -log "[2/6] 打包数据..." -cd /tmp -tar -czf "zhiyi_backup_${DATE}.tar.gz" "zhiyi_backup_${DATE}/" -rm -rf "zhiyi_backup_${DATE}" -ARCHIVE_SIZE=$(du -sh "/tmp/zhiyi_backup_${DATE}.tar.gz" | cut -f1) -log " 打包完成: ${ARCHIVE_SIZE}" - -# 3. 备份 Hermes 配置 -log "[3/6] 备份 Hermes 配置..." -mkdir -p "${CONFIG_DIR}" - -# 核心人格文件 -rsync -a "${HOME}/.hermes/SOUL.md" "${CONFIG_DIR}/" 2>/dev/null || true -rsync -a "${HOME}/.hermes/AGENTS.md" "${CONFIG_DIR}/" 2>/dev/null || true -rsync -a "${HOME}/.hermes/MEMORY.md" "${CONFIG_DIR}/" 2>/dev/null || true -rsync -a "${HOME}/.hermes/USER.md" "${CONFIG_DIR}/" 2>/dev/null || true - -# 配置文件 -rsync -a "${HOME}/.hermes/config.yaml" "${CONFIG_DIR}/" 2>/dev/null || true -rsync -a "${HOME}/.hermes/.env" "${CONFIG_DIR}/" 2>/dev/null || true -rsync -a "${HOME}/.hermes/auth.json" "${CONFIG_DIR}/" 2>/dev/null || true - -# skills / cron / kanban -[ -d "${HOME}/.hermes/skills" ] && rsync -a "${HOME}/.hermes/skills/" "${CONFIG_DIR}/skills/" --quiet -[ -d "${HOME}/.hermes/cron" ] && rsync -a "${HOME}/.hermes/cron/" "${CONFIG_DIR}/cron/" --quiet -[ -f "${HOME}/.hermes/kanban.db" ] && rsync -a "${HOME}/.hermes/kanban.db" "${CONFIG_DIR}/" 2>/dev/null || true - -# memories / sessions(可选,较大) -if [ -d "${HOME}/.hermes/memories" ] && [ "$(du -sm "${HOME}/.hermes/memories" 2>/dev/null | cut -f1)" -lt 500 ]; then - rsync -a "${HOME}/.hermes/memories/" "${CONFIG_DIR}/memories/" --quiet -fi -if [ -d "${HOME}/.hermes/sessions" ] && [ "$(du -sm "${HOME}/.hermes/sessions" 2>/dev/null | cut -f1)" -lt 200 ]; then - rsync -a "${HOME}/.hermes/sessions/" "${CONFIG_DIR}/sessions/" --quiet +# 2. SQLite graph.db 备份 +echo "[$TIMESTAMP] 备份 graph.db..." +if ! sqlite3 "$DATA_DIR/graph.db" ".backup $BACKUP_DIR/graph.db"; then + echo "[$TIMESTAMP] ERROR: graph.db 备份失败" + exit 1 fi -CONFIG_SIZE=$(du -sh "${CONFIG_DIR}" | cut -f1) -log " 配置备份完成: ${CONFIG_SIZE}" - -# 4. 推送到 Gitea -log "[4/6] 推送到 Gitea..." - -# 确保 git 仓库存在 -if [ ! -d "${PROJECT_ROOT}/.git" ]; then - log " WARM: ${PROJECT_ROOT} 不是 git 仓库,初始化..." - cd "${PROJECT_ROOT}" - git init - git remote add origin "http://192.168.123.11:3000/xiaoxue_admin/zhiyi-config.git" 2>/dev/null || true +# 3. SQLite memoryweave.db 备份 +echo "[$TIMESTAMP] 备份 memoryweave.db..." +if ! sqlite3 "$DATA_DIR/memoryweave.db" ".backup $BACKUP_DIR/memoryweave.db"; then + echo "[$TIMESTAMP] ERROR: memoryweave.db 备份失败" + exit 1 fi -cd "${PROJECT_ROOT}" +# 4. Redis 异步保存 +echo "[$TIMESTAMP] 触发 Redis BGSAVE..." +redis-cli BGSAVE 2>/dev/null || true -# 确保 data 目录存在 -mkdir -p data - -# 移动备份到 data 目录 -mv "/tmp/zhiyi_backup_${DATE}.tar.gz" data/ - -# 把数据仓库也 clone/update -if [ ! -d "${PROJECT_ROOT}/zhiyi-backup" ]; then - git clone "http://192.168.123.11:3000/xiaoxue_admin/zhiyi-backup.git" "${PROJECT_ROOT}/zhiyi-backup" 2>/dev/null || { - # 如果仓库不存在,跳过数据备份 - log " WARN: zhiyi-backup 仓库不存在或无法访问,跳过数据推送" - } +# 5. LanceDB 目录 tar 打包(最多等 300s) +echo "[$TIMESTAMP] 打包 LanceDB 数据(可能需要 1-2 分钟)..." +if ! timeout 300 tar czf "$BACKUP_DIR/lance-data.tar.gz" \ + -C "$DATA_DIR" episodes.lance memories.lance tombstones.lance; then + echo "[$TIMESTAMP] ERROR: LanceDB 打包超时或失败" + exit 1 fi -if [ -d "${PROJECT_ROOT}/zhiyi-backup" ]; then - cd "${PROJECT_ROOT}/zhiyi-backup" - # 移动 archive - if [ -f "${PROJECT_ROOT}/data/zhiyi_backup_${DATE}.tar.gz" ]; then - cp "${PROJECT_ROOT}/data/zhiyi_backup_${DATE}.tar.gz" . - git add "zhiyi_backup_${DATE}.tar.gz" - git commit -m "Backup data ${DATE}" 2>/dev/null || true - git push origin main 2>/dev/null || log " WARN: 数据推送失败(可能需要 token)" - rm -f "zhiyi_backup_${DATE}.tar.gz" +# 6. 验证 +echo "[$TIMESTAMP] 验证备份..." +for f in graph.db memoryweave.db lance-data.tar.gz; do + if [ ! -s "$BACKUP_DIR/$f" ]; then + echo "[$TIMESTAMP] ERROR: $f 为空或不存在" + exit 1 fi - cd "${PROJECT_ROOT}" -fi +done -# 推送配置 -git add data/zhiyi_backup_${DATE}.tar.gz -git add config/ 2>/dev/null || true -git add -A -COMMIT_MSG="${1:-Backup ${DATE}}" -git commit -m "${COMMIT_MSG}" 2>/dev/null || log " WARN: 没有新内容需要提交" - -git push origin main 2>/dev/null || log " WARN: 配置推送失败(可能需要 token)" - -# 5. 清理 -log "[5/6] 清理临时文件..." -rm -rf "${BACKUP_DIR}" "${CONFIG_DIR}" -log " 清理完成" - -# 6. 完成 -log "[6/6] 备份完成" -log "===== 备份结束: ${DATE} =====" -echo "" \ No newline at end of file +# 7. 打印结果 +SIZE=$(du -sh "$BACKUP_DIR" | cut -f1) +echo "[$TIMESTAMP] 备份成功 | 路径: $BACKUP_DIR | 大小: $SIZE" +echo "[$TIMESTAMP] 织忆备份结果: OK | 路径: $BACKUP_DIR | 时间戳: $TIMESTAMP" > "$HOME/projects/memoryweave/backups/backup-$TIMESTAMP.log" \ No newline at end of file