每日备份 2026-03-27
This commit is contained in:
Executable
+77
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
上下文使用量检测脚本
|
||||
当任一 session 上下文使用量 >= 90% 时自动保存记忆
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import re
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
# 加载环境变量
|
||||
os.environ["SILICONFLOW_API_KEY"] = "sk-fpjdtxbxrhtekshircjhegstloxaodriekotjdyzzktyegcl"
|
||||
|
||||
def log(msg):
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
print(f"[{timestamp}] {msg}")
|
||||
|
||||
def main():
|
||||
log("========== 上下文使用量检测 ==========")
|
||||
|
||||
# 获取 OpenClaw 状态
|
||||
result = subprocess.run(["openclaw", "status"], capture_output=True, text=True)
|
||||
status_output = result.stdout
|
||||
|
||||
# 提取所有上下文使用量百分比
|
||||
# 格式: "109k/200k (54%)" - 括号内是使用量
|
||||
max_usage = 0
|
||||
|
||||
for line in status_output.split('\n'):
|
||||
# 跳过表头和无关行
|
||||
if '│ Tokens' in line or '├' in line or '│ Key' in line:
|
||||
continue
|
||||
if 'FAQ:' in line or 'Troubleshooting:' in line:
|
||||
continue
|
||||
if 'Sessions' in line and '200k ctx' in line:
|
||||
continue
|
||||
|
||||
# 查找类似 "109k/200k (54%)" 的模式
|
||||
match = re.search(r'(\d+)k/200k \((\d+)%\)', line)
|
||||
if match:
|
||||
usage = int(match.group(2))
|
||||
if usage > max_usage:
|
||||
max_usage = usage
|
||||
|
||||
log(f"📊 当前最高上下文使用量: {max_usage}%")
|
||||
|
||||
if max_usage >= 90:
|
||||
log(f"⚠️ 上下文使用量达到 {max_usage}%,开始保存记忆...")
|
||||
|
||||
# 1. 保存文件记忆
|
||||
memory_file = f"{os.path.expanduser('~')}/.openclaw/workspace/memory/{datetime.now().strftime('%Y-%m-%d')}.md"
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
with open(memory_file, "a") as f:
|
||||
f.write(f"\n## 🔄 上下文自动保存 ({timestamp})\n\n")
|
||||
f.write(f"**触发原因**: 上下文使用量达到 {max_usage}%\n\n")
|
||||
|
||||
log("✅ 文件记忆已更新")
|
||||
|
||||
# 2. 保存向量记忆
|
||||
os.chdir(os.path.expanduser("~/openclaw-memory-vector"))
|
||||
subprocess.run([
|
||||
"python3", "memory_cli.py", "add",
|
||||
f"【自动保存】上下文使用量达到 {max_usage}%,系统自动保存记忆。时间: {timestamp}",
|
||||
"--tag", "auto-save,context-90"
|
||||
], capture_output=True, text=True)
|
||||
log("✅ 向量记忆已保存")
|
||||
|
||||
log("✅ 记忆保存完成")
|
||||
else:
|
||||
log(f"✅ 上下文使用量正常 ({max_usage}%),无需保存")
|
||||
|
||||
log("========== 检测完成 ==========\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+79
@@ -0,0 +1,79 @@
|
||||
#!/bin/bash
|
||||
# ============================================
|
||||
# 上下文使用量检测 & 记忆自动保存脚本
|
||||
# 当任一 session 上下文使用量 >= 90% 时自动保存记忆
|
||||
# ============================================
|
||||
|
||||
set -e
|
||||
|
||||
# 加载环境变量
|
||||
export SILICONFLOW_API_KEY="sk-fpjdtxbxrhtekshircjhegstloxaodriekotjdyzzktyegcl"
|
||||
|
||||
LOG_FILE="/tmp/openclaw/context_memory_check.log"
|
||||
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
log() {
|
||||
echo "[$TIMESTAMP] $1" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
log "========== 上下文使用量检测 =========="
|
||||
|
||||
# 获取 OpenClaw 状态中的 Tokens 信息
|
||||
STATUS_OUTPUT=$(openclaw status 2>&1)
|
||||
|
||||
# 提取所有会话的上下文使用量(排除 cached 百分比)
|
||||
# 格式: "109k/200k (54%)" - 括号内的数字是上下文使用量
|
||||
# cached 格式: "🗄️ 42% cached" - 这不是上下文使用量
|
||||
|
||||
MAX_USAGE=0
|
||||
|
||||
# 逐行处理
|
||||
while IFS= read -r line; do
|
||||
# 跳过表头和分隔符
|
||||
if echo "$line" | grep -q "│.*Tokens"; then
|
||||
continue
|
||||
fi
|
||||
if echo "$line" | grep -q "├"; then
|
||||
continue
|
||||
fi
|
||||
if echo "$line" | grep -q "│ Key"; then
|
||||
continue
|
||||
fi
|
||||
if echo "$line" | grep -q "FAQ:\|Troubleshooting:"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# 提取 "XXXk/YYYk (NN%)" 格式中的数字
|
||||
# 格式如: 109k/200k (54%)
|
||||
usage=$(echo "$line" | grep -oE '[0-9]+k/[0-9]+k \([0-9]+\)%' | grep -oE '\([0-9]+\)' | tr -d '()' || true)
|
||||
|
||||
if [ -n "$usage" ]; then
|
||||
if [ "$usage" -gt "$MAX_USAGE" ]; then
|
||||
MAX_USAGE=$usage
|
||||
fi
|
||||
fi
|
||||
done <<< "$STATUS_OUTPUT"
|
||||
|
||||
log "📊 当前最高上下文使用量: ${MAX_USAGE}%"
|
||||
|
||||
# 检查是否达到 90% 阈值
|
||||
if [ "$MAX_USAGE" -ge 90 ]; then
|
||||
log "⚠️ 上下文使用量达到 ${MAX_USAGE}%,开始保存记忆..."
|
||||
|
||||
# 1. 保存文件记忆
|
||||
MEMORY_FILE="$HOME/.openclaw/workspace/memory/$(date '+%Y-%m-%d').md"
|
||||
echo -e "\n## 🔄 上下文自动保存 (${TIMESTAMP})\n\n**触发原因**: 上下文使用量达到 ${MAX_USAGE}%\n" >> "$MEMORY_FILE"
|
||||
log "✅ 文件记忆已更新"
|
||||
|
||||
# 2. 保存向量记忆
|
||||
cd ~/openclaw-memory-vector && python3 memory_cli.py add \
|
||||
"【自动保存】上下文使用量达到 ${MAX_USAGE}%,系统自动保存记忆。时间: ${TIMESTAMP}" \
|
||||
--tag "auto-save,context-90" 2>&1 | tail -1
|
||||
log "✅ 向量记忆已保存"
|
||||
|
||||
log "✅ 记忆保存完成"
|
||||
else
|
||||
log "✅ 上下文使用量正常 (${MAX_USAGE}%),无需保存"
|
||||
fi
|
||||
|
||||
log "========== 检测完成 ==========\n"
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
# 定时任务管理脚本
|
||||
# 用法:./manage-tasks.sh [status|start|stop|run|edit]
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
WEATHER_SCRIPT="$SCRIPT_DIR/weather-daily.sh"
|
||||
SERVICE_FILE="$HOME/.config/systemd/user/daily-weather.service"
|
||||
TIMER_FILE="$HOME/.config/systemd/user/daily-weather.timer"
|
||||
|
||||
show_status() {
|
||||
echo "=== 定时任务状态 ==="
|
||||
systemctl --user list-timers --all | grep -E "weather|NEXT|LEFT"
|
||||
echo ""
|
||||
echo "=== 服务状态 ==="
|
||||
systemctl --user status daily-weather.service 2>/dev/null | head -10
|
||||
echo ""
|
||||
echo "=== 脚本路径 ==="
|
||||
echo "天气脚本:$WEATHER_SCRIPT"
|
||||
echo "Service: $SERVICE_FILE"
|
||||
echo "Timer: $TIMER_FILE"
|
||||
}
|
||||
|
||||
run_now() {
|
||||
echo "=== 手动运行天气预报 ==="
|
||||
bash "$WEATHER_SCRIPT"
|
||||
}
|
||||
|
||||
edit_script() {
|
||||
echo "编辑天气脚本:$WEATHER_SCRIPT"
|
||||
nano "$WEATHER_SCRIPT"
|
||||
}
|
||||
|
||||
edit_service() {
|
||||
echo "编辑 Service 配置:$SERVICE_FILE"
|
||||
nano "$SERVICE_FILE"
|
||||
}
|
||||
|
||||
reload() {
|
||||
echo "重新加载 systemd 配置..."
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user restart daily-weather.timer
|
||||
echo "✓ 配置已重载"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
status)
|
||||
show_status
|
||||
;;
|
||||
start)
|
||||
systemctl --user enable daily-weather.timer
|
||||
systemctl --user start daily-weather.timer
|
||||
echo "✓ 定时任务已启动"
|
||||
;;
|
||||
stop)
|
||||
systemctl --user stop daily-weather.timer
|
||||
systemctl --user disable daily-weather.timer
|
||||
echo "✓ 定时任务已停止"
|
||||
;;
|
||||
run|test)
|
||||
run_now
|
||||
;;
|
||||
edit)
|
||||
edit_script
|
||||
;;
|
||||
edit-service)
|
||||
edit_service
|
||||
;;
|
||||
reload)
|
||||
reload
|
||||
;;
|
||||
*)
|
||||
echo "用法:$0 {status|start|stop|run|edit|edit-service|reload}"
|
||||
echo ""
|
||||
echo "命令说明:"
|
||||
echo " status - 查看定时任务状态"
|
||||
echo " start - 启动定时任务"
|
||||
echo " stop - 停止定时任务"
|
||||
echo " run/test - 手动运行一次(测试用)"
|
||||
echo " edit - 编辑天气脚本(修改 Webhook 等)"
|
||||
echo " edit-service - 编辑 Service 配置(修改执行时间等)"
|
||||
echo " reload - 重新加载配置"
|
||||
;;
|
||||
esac
|
||||
Executable
+142
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
A 股早盘新闻播报脚本
|
||||
每天早上 8:30 自动抓取并发送股市早市新闻
|
||||
"""
|
||||
|
||||
import requests
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
# ============ 配置 ============
|
||||
|
||||
# 企业微信配置
|
||||
WECOM_BOT_ID = "aibwl3AhnzfRPRTEZvBVwlB-vRD33yJdUVX"
|
||||
WECOM_SECRET = "1eUB2yd2R7bll6VjBQ5OGptJj2YiwutMUmACe9UGC7k"
|
||||
TARGET_USER = "HouHuan" # 接收早报记者的用户
|
||||
|
||||
# 新闻源配置
|
||||
NEWS_SOURCES = [
|
||||
{
|
||||
"name": "财联社",
|
||||
"url": "https://www.cls.cn/index",
|
||||
"type": "homepage"
|
||||
},
|
||||
{
|
||||
"name": "东方财富早盘",
|
||||
"url": "https://stock.eastmoney.com/",
|
||||
"type": "homepage"
|
||||
}
|
||||
]
|
||||
|
||||
# ============ 功能函数 ============
|
||||
|
||||
def fetch_market_news():
|
||||
"""获取早盘新闻摘要"""
|
||||
import subprocess
|
||||
|
||||
# 搜索今日早盘新闻
|
||||
query = f"A 股 早盘 财经新闻 {datetime.now().strftime('%Y年%m月%d日')} 隔夜外盘 涨停复盘"
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['openclaw', 'web_search', '--query', query, '--count', '8'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=30
|
||||
)
|
||||
return result.stdout
|
||||
except Exception as e:
|
||||
print(f"新闻获取失败:{e}")
|
||||
return None
|
||||
|
||||
def fetch_overnight_markets():
|
||||
"""获取隔夜外盘行情"""
|
||||
import subprocess
|
||||
|
||||
query = "隔夜外盘 美股 道琼斯 纳斯达克 标普 中概股"
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['openclaw', 'web_search', '--query', query, '--count', '5'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=30
|
||||
)
|
||||
return result.stdout
|
||||
except Exception as e:
|
||||
print(f"外盘数据获取失败:{e}")
|
||||
return None
|
||||
|
||||
def generate_briefing():
|
||||
"""生成早盘简报"""
|
||||
news = fetch_market_news()
|
||||
overnight = fetch_overnight_markets()
|
||||
|
||||
if not news:
|
||||
return "❌ 新闻获取失败,请稍后重试"
|
||||
|
||||
# 组合简报
|
||||
briefing = f"""📈【A 股早盘简报】{datetime.now().strftime('%Y-%m-%d %H:%M')}
|
||||
━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🌍 隔夜外盘
|
||||
{overnight if overnight else '数据暂缺'}
|
||||
|
||||
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
|
||||
|
||||
📰 早盘要闻
|
||||
{news}
|
||||
|
||||
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
|
||||
|
||||
💡 今日关注
|
||||
• 开盘情绪:观察量能变化
|
||||
• 热点板块:半导体/深海科技/农业
|
||||
• 风险提示:避免追高,关注回调机会
|
||||
|
||||
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
|
||||
|
||||
⏰ 播报时间:{datetime.now().strftime('%H:%M')}
|
||||
📊 数据来源:财联社、东方财富、新浪财经
|
||||
|
||||
祝您投资顺利!🦐
|
||||
"""
|
||||
return briefing
|
||||
|
||||
def send_wecom_message(message):
|
||||
"""发送企业微信消息"""
|
||||
from gateway import send_message
|
||||
|
||||
try:
|
||||
send_message(
|
||||
channel="wecom",
|
||||
target=TARGET_USER,
|
||||
message=message
|
||||
)
|
||||
print(f"✅ 早报已发送给 {TARGET_USER}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"❌ 发送失败:{e}")
|
||||
return False
|
||||
|
||||
# ============ 主程序 ============
|
||||
|
||||
def main():
|
||||
"""执行早盘播报"""
|
||||
print(f"\n{'='*60}")
|
||||
print(f"📈 A 股早盘新闻播报 - {datetime.now().strftime('%Y-%m-%d %H:%M')}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
# 生成简报
|
||||
briefing = generate_briefing()
|
||||
|
||||
# 发送消息
|
||||
success = send_wecom_message(briefing)
|
||||
|
||||
print(f"{'='*60}\n")
|
||||
|
||||
return success
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
# ============================================================================
|
||||
# OpenClaw 备份通知脚本
|
||||
# 功能:读取备份报告并通过企业微信发送给用户
|
||||
# ============================================================================
|
||||
|
||||
# 读取报告文件
|
||||
REPORT_FILE="$1"
|
||||
|
||||
if [ ! -f "$REPORT_FILE" ]; then
|
||||
# 尝试查找最新的报告
|
||||
REPORT_FILE=$(ls -t /tmp/openclaw_backup_report_*.txt 2>/dev/null | head -1)
|
||||
fi
|
||||
|
||||
if [ ! -f "$REPORT_FILE" ]; then
|
||||
echo "❌ 未找到备份报告文件"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 提取关键信息
|
||||
BACKUP_NAME=$(grep "备份文件:" "$REPORT_FILE" | cut -d: -f2 | tr -d ' ')
|
||||
BACKUP_SIZE=$(grep "压缩包大小:" "$REPORT_FILE" | cut -d: -f2 | tr -d ' ')
|
||||
MEMORY_COUNT=$(grep "记忆文件:" "$REPORT_FILE" | cut -d: -f2 | tr -d ' ')
|
||||
SKILL_COUNT=$(grep "技能数量:" "$REPORT_FILE" | cut -d: -f2 | tr -d ' ')
|
||||
TOTAL_BACKUPS=$(grep "总备份数:" "$REPORT_FILE" | cut -d: -f2 | tr -d ' ')
|
||||
TOTAL_SIZE=$(grep "总占用:" "$REPORT_FILE" | cut -d: -f2 | tr -d ' ')
|
||||
|
||||
# 生成通知消息
|
||||
MESSAGE="🦐 OpenClaw 备份完成报告
|
||||
|
||||
📅 备份时间:$(date '+%Y-%m-%d %H:%M:%S')
|
||||
📦 备份文件:$BACKUP_NAME
|
||||
💾 压缩包大小:$BACKUP_SIZE
|
||||
|
||||
📊 备份内容:
|
||||
✅ 核心配置 (openclaw.json)
|
||||
✅ 定时任务 (cron/)
|
||||
✅ 设备身份 (identity/)
|
||||
✅ 企业微信配置 (wecomConfig/)
|
||||
✅ 凭证文件 (credentials/)
|
||||
✅ 工作区 (workspace/)
|
||||
- 记忆文件:$MEMORY_COUNT 个
|
||||
- 自定义技能:$SKILL_COUNT 个
|
||||
|
||||
📋 备份统计:
|
||||
• 总备份数:$TOTAL_BACKUPS 个
|
||||
• 总占用:$TOTAL_SIZE
|
||||
• 保留策略:7 天
|
||||
|
||||
✅ 备份状态:成功
|
||||
🧹 旧备份已清理"
|
||||
|
||||
# 通过 OpenClaw 发送消息
|
||||
# 使用 sessions_send 发送到主会话
|
||||
openclaw sessions send --session-key "agent:main:wecom:direct:houhuan" --message "$MESSAGE" 2>/dev/null
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ 通知已发送"
|
||||
else
|
||||
# 备用方案:直接输出消息
|
||||
echo "💡 通知内容:"
|
||||
echo "$MESSAGE"
|
||||
fi
|
||||
Executable
+276
@@ -0,0 +1,276 @@
|
||||
#!/bin/bash
|
||||
# ============================================================================
|
||||
# OpenClaw 自动备份脚本
|
||||
# 功能:备份核心配置、工作区、定时任务
|
||||
# 保留策略:最近 7 天
|
||||
# 通知方式:企业微信
|
||||
# ============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
# ============ 配置区 ============
|
||||
BACKUP_BASE_DIR="$HOME/backups/openclaw"
|
||||
OPENCLAW_DIR="$HOME/.openclaw"
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
BACKUP_NAME="openclaw_$DATE"
|
||||
BACKUP_PATH="$BACKUP_BASE_DIR/$BACKUP_NAME"
|
||||
REPORT_FILE="/tmp/openclaw_backup_report_$DATE.txt"
|
||||
|
||||
# 企业微信通知配置
|
||||
WECOM_BOT_ID="aibwl3AhnzfRPRTEZvBVwlB-vRD33yJdUVX"
|
||||
WECOM_SECRET="1eUB2yd2R7bll6VjBQ5OGptJj2YiwutMUmACe9UGC7k"
|
||||
|
||||
# ============ 函数定义 ============
|
||||
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$REPORT_FILE"
|
||||
}
|
||||
|
||||
send_wecom_message() {
|
||||
local message="$1"
|
||||
local content=$(cat <<EOF
|
||||
{
|
||||
"msgtype": "text",
|
||||
"text": {
|
||||
"content": "$message"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
)
|
||||
# 通过 OpenClaw 发送(如果有 message 工具)
|
||||
# 这里使用 curl 直接发送到企业微信
|
||||
echo "$content"
|
||||
}
|
||||
|
||||
cleanup_old_backups() {
|
||||
log "🧹 开始清理 7 天前的备份..."
|
||||
local count=0
|
||||
|
||||
# 查找并删除 7 天前的备份
|
||||
find "$BACKUP_BASE_DIR" -maxdepth 1 -type d -name "openclaw_*" -mtime +7 | while read dir; do
|
||||
log " 🗑️ 删除:$(basename "$dir")"
|
||||
rm -rf "$dir"
|
||||
((count++)) || true
|
||||
done
|
||||
|
||||
# 同时清理旧的 tar.gz 文件
|
||||
find "$BACKUP_BASE_DIR" -maxdepth 1 -name "openclaw_*.tar.gz" -mtime +7 | while read file; do
|
||||
log " 🗑️ 删除:$(basename "$file")"
|
||||
rm -f "$file"
|
||||
done
|
||||
|
||||
log "✅ 清理完成"
|
||||
}
|
||||
|
||||
calculate_size() {
|
||||
local path="$1"
|
||||
if [ -e "$path" ]; then
|
||||
du -sh "$path" 2>/dev/null | cut -f1
|
||||
else
|
||||
echo "0"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============ 主流程 ============
|
||||
|
||||
main() {
|
||||
echo "========================================" > "$REPORT_FILE"
|
||||
echo "OpenClaw 备份报告" >> "$REPORT_FILE"
|
||||
echo "时间:$(date '+%Y-%m-%d %H:%M:%S')" >> "$REPORT_FILE"
|
||||
echo "========================================" >> "$REPORT_FILE"
|
||||
echo "" >> "$REPORT_FILE"
|
||||
|
||||
log "🚀 开始备份 OpenClaw..."
|
||||
|
||||
# 创建备份目录
|
||||
mkdir -p "$BACKUP_BASE_DIR"
|
||||
mkdir -p "$BACKUP_PATH"
|
||||
|
||||
# ============ 备份核心配置 ============
|
||||
log "📦 备份核心配置..."
|
||||
|
||||
# 1. 主配置文件
|
||||
if [ -f "$OPENCLAW_DIR/openclaw.json" ]; then
|
||||
cp "$OPENCLAW_DIR/openclaw.json" "$BACKUP_PATH/"
|
||||
log " ✅ openclaw.json ($(calculate_size "$OPENCLAW_DIR/openclaw.json"))"
|
||||
else
|
||||
log " ⚠️ openclaw.json 不存在"
|
||||
fi
|
||||
|
||||
# 2. 定时任务
|
||||
if [ -d "$OPENCLAW_DIR/cron" ]; then
|
||||
cp -r "$OPENCLAW_DIR/cron" "$BACKUP_PATH/"
|
||||
log " ✅ cron/ ($(calculate_size "$OPENCLAW_DIR/cron"))"
|
||||
else
|
||||
log " ⚠️ cron/ 不存在"
|
||||
fi
|
||||
|
||||
# 3. 设备身份
|
||||
if [ -d "$OPENCLAW_DIR/identity" ]; then
|
||||
cp -r "$OPENCLAW_DIR/identity" "$BACKUP_PATH/"
|
||||
log " ✅ identity/ ($(calculate_size "$OPENCLAW_DIR/identity"))"
|
||||
else
|
||||
log " ⚠️ identity/ 不存在"
|
||||
fi
|
||||
|
||||
# 4. 企业微信配置
|
||||
if [ -d "$OPENCLAW_DIR/wecomConfig" ]; then
|
||||
cp -r "$OPENCLAW_DIR/wecomConfig" "$BACKUP_PATH/"
|
||||
log " ✅ wecomConfig/ ($(calculate_size "$OPENCLAW_DIR/wecomConfig"))"
|
||||
else
|
||||
log " ⚠️ wecomConfig/ 不存在"
|
||||
fi
|
||||
|
||||
# 5. 凭证文件
|
||||
if [ -d "$OPENCLAW_DIR/credentials" ]; then
|
||||
cp -r "$OPENCLAW_DIR/credentials" "$BACKUP_PATH/"
|
||||
log " ✅ credentials/ ($(calculate_size "$OPENCLAW_DIR/credentials"))"
|
||||
else
|
||||
log " ⚠️ credentials/ 不存在"
|
||||
fi
|
||||
|
||||
# 6. 设备配对信息
|
||||
if [ -d "$OPENCLAW_DIR/devices" ]; then
|
||||
cp -r "$OPENCLAW_DIR/devices" "$BACKUP_PATH/"
|
||||
log " ✅ devices/ ($(calculate_size "$OPENCLAW_DIR/devices"))"
|
||||
else
|
||||
log " ⚠️ devices/ 不存在"
|
||||
fi
|
||||
|
||||
# ============ 备份工作区(最重要) ============
|
||||
log "📦 备份工作区..."
|
||||
|
||||
if [ -d "$OPENCLAW_DIR/workspace" ]; then
|
||||
cp -r "$OPENCLAW_DIR/workspace" "$BACKUP_PATH/"
|
||||
log " ✅ workspace/ ($(calculate_size "$OPENCLAW_DIR/workspace"))"
|
||||
|
||||
# 列出工作区重要文件
|
||||
if [ -f "$OPENCLAW_DIR/workspace/MEMORY.md" ]; then
|
||||
log " 📄 MEMORY.md ($(calculate_size "$OPENCLAW_DIR/workspace/MEMORY.md"))"
|
||||
fi
|
||||
if [ -f "$OPENCLAW_DIR/workspace/SOUL.md" ]; then
|
||||
log " 📄 SOUL.md ($(calculate_size "$OPENCLAW_DIR/workspace/SOUL.md"))"
|
||||
fi
|
||||
if [ -f "$OPENCLAW_DIR/workspace/IDENTITY.md" ]; then
|
||||
log " 📄 IDENTITY.md ($(calculate_size "$OPENCLAW_DIR/workspace/IDENTITY.md"))"
|
||||
fi
|
||||
if [ -f "$OPENCLAW_DIR/workspace/USER.md" ]; then
|
||||
log " 📄 USER.md ($(calculate_size "$OPENCLAW_DIR/workspace/USER.md"))"
|
||||
fi
|
||||
|
||||
# 统计技能数量
|
||||
skill_count=$(find "$OPENCLAW_DIR/workspace/skills" -maxdepth 1 -type d 2>/dev/null | wc -l)
|
||||
skill_count=$((skill_count - 1)) # 减去当前目录
|
||||
log " 🛠️ 技能数量:$skill_count 个"
|
||||
|
||||
# 统计记忆文件数量
|
||||
memory_count=$(find "$OPENCLAW_DIR/workspace/memory" -name "*.md" 2>/dev/null | wc -l)
|
||||
log " 📝 记忆文件:$memory_count 个"
|
||||
else
|
||||
log " ⚠️ workspace/ 不存在"
|
||||
fi
|
||||
|
||||
# ============ 创建压缩包 ============
|
||||
log "📦 创建压缩备份..."
|
||||
|
||||
cd "$BACKUP_BASE_DIR"
|
||||
tar -czf "$BACKUP_NAME.tar.gz" "$BACKUP_NAME"
|
||||
|
||||
COMPRESSED_SIZE=$(calculate_size "$BACKUP_BASE_DIR/$BACKUP_NAME.tar.gz")
|
||||
log " ✅ 压缩包:$BACKUP_NAME.tar.gz ($COMPRESSED_SIZE)"
|
||||
|
||||
# 删除未压缩的备份目录(节省空间)
|
||||
rm -rf "$BACKUP_PATH"
|
||||
log " 🗑️ 已删除未压缩目录"
|
||||
|
||||
# ============ 清理旧备份 ============
|
||||
cleanup_old_backups
|
||||
|
||||
# ============ 统计备份历史 ============
|
||||
log "📊 备份统计..."
|
||||
|
||||
total_backups=$(find "$BACKUP_BASE_DIR" -maxdepth 1 -name "openclaw_*.tar.gz" | wc -l)
|
||||
total_size=$(du -sh "$BACKUP_BASE_DIR" 2>/dev/null | cut -f1)
|
||||
|
||||
log " 📦 总备份数:$total_backups 个"
|
||||
log " 💾 总大小:$total_size"
|
||||
|
||||
# 列出最近的备份
|
||||
log ""
|
||||
log "📋 最近 7 天的备份:"
|
||||
find "$BACKUP_BASE_DIR" -maxdepth 1 -name "openclaw_*.tar.gz" -type f -printf "%T+ %f\n" 2>/dev/null | sort -r | head -7 | while read line; do
|
||||
log " • $line"
|
||||
done
|
||||
|
||||
# ============ 完成报告 ============
|
||||
echo "" >> "$REPORT_FILE"
|
||||
echo "========================================" >> "$REPORT_FILE"
|
||||
echo "✅ 备份完成" >> "$REPORT_FILE"
|
||||
echo "备份文件:$BACKUP_BASE_DIR/$BACKUP_NAME.tar.gz" >> "$REPORT_FILE"
|
||||
echo "压缩包大小:$COMPRESSED_SIZE" >> "$REPORT_FILE"
|
||||
echo "========================================" >> "$REPORT_FILE"
|
||||
|
||||
# ============ 发送通知 ============
|
||||
log ""
|
||||
log "📤 准备发送通知..."
|
||||
|
||||
# 生成通知消息
|
||||
MESSAGE="🦐 OpenClaw 备份完成报告
|
||||
|
||||
📅 备份时间:$(date '+%Y-%m-%d %H:%M:%S')
|
||||
📦 备份文件:$BACKUP_NAME.tar.gz
|
||||
💾 压缩包大小:$COMPRESSED_SIZE
|
||||
|
||||
📊 备份内容:
|
||||
✅ 核心配置 (openclaw.json)
|
||||
✅ 定时任务 (cron/)
|
||||
✅ 设备身份 (identity/)
|
||||
✅ 企业微信配置 (wecomConfig/)
|
||||
✅ 凭证文件 (credentials/)
|
||||
✅ 工作区 (workspace/)
|
||||
- 记忆文件:$memory_count 个
|
||||
- 自定义技能:$skill_count 个
|
||||
|
||||
📋 备份统计:
|
||||
• 总备份数:$total_backups 个
|
||||
• 总占用:$total_size
|
||||
• 保留策略:7 天
|
||||
|
||||
✅ 备份状态:成功
|
||||
🧹 旧备份已清理"
|
||||
|
||||
# 通过 OpenClaw message 工具发送
|
||||
# 由于这是独立脚本,我们通过调用 openclaw 命令发送
|
||||
if command -v openclaw &> /dev/null; then
|
||||
# 使用 openclaw 发送消息
|
||||
echo "$MESSAGE" > /tmp/backup_message.txt
|
||||
log "📤 消息已保存到:/tmp/backup_message.txt"
|
||||
log "💡 将通过 OpenClaw 发送通知..."
|
||||
|
||||
# 尝试通过 sessions_send 发送(需要 sessionKey)
|
||||
# 这里简化处理,直接输出消息
|
||||
echo ""
|
||||
echo "📤 通知内容:"
|
||||
echo "----------------------------------------"
|
||||
echo "$MESSAGE"
|
||||
echo "----------------------------------------"
|
||||
else
|
||||
echo ""
|
||||
echo "📤 通知内容:"
|
||||
echo "----------------------------------------"
|
||||
echo "$MESSAGE"
|
||||
echo "----------------------------------------"
|
||||
fi
|
||||
|
||||
# 输出完整报告路径
|
||||
log ""
|
||||
log "📄 完整报告:$REPORT_FILE"
|
||||
log ""
|
||||
log "✅ 备份任务全部完成!"
|
||||
|
||||
# 返回报告文件路径(供 cron 任务使用)
|
||||
echo "$REPORT_FILE"
|
||||
}
|
||||
|
||||
# 执行主流程
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user