每日备份 2026-03-27

This commit is contained in:
OpenClaw Backup
2026-03-27 23:38:45 +08:00
parent 4f11cd7b03
commit d09281e48c
827 changed files with 6991 additions and 148648 deletions
+77
View File
@@ -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()
+79
View File
@@ -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"
+83
View File
@@ -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
+142
View File
@@ -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()
+63
View File
@@ -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
+276
View File
@@ -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 "$@"