每日备份 2026-06-10 12:57:13

This commit is contained in:
root-backup committed 2026-06-10 12:57:14 +08:00
1 parent fda2ccb8c2
commit 3d2e638c6a
244 files changed
+58890 -3

No files matched your search

+51
View File
@@ -0,0 +1,51 @@
#!/bin/bash
# 2号机: 添加学习任务到青龙任务队列
QUEUE_FILE="/root/.openclaw/workspace/memory/task_queue.txt"
usage() {
echo "用法: $0 <主题> <类型> [数量] [时间]"
echo " 主题: 学习主题关键词"
echo " 类型: article(文章) / novel(小说) / stock(股票)"
echo " 数量: 默认 3"
echo " 时间: 执行时间 (默认: 下一小时整点)"
echo ""
echo "示例:"
echo " $0 '机器学习' article 5"
echo " $0 'AAPL' stock 1 '2026-02-07T09:00:00'"
}
# 参数
TOPIC="$1"
TYPE="${2:-article}"
COUNT="${3:-3}"
TIME="${4:-}"
if [ -z "$TOPIC" ]; then
usage
exit 1
fi
# 默认时间: 下一小时整点
if [ -z "$TIME" ]; then
TIME=$(date -d "+1 hour" '+%Y-%m-%dT%H:00:00')
fi
# 格式验证
if ! [[ "$TIME" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}$ ]]; then
echo "✗ 时间格式错误,应为: YYYY-MM-DDTHH:MM:SS"
exit 1
fi
# 添加任务
echo "$TIME|$TOPIC|$TYPE|$COUNT" >> "$QUEUE_FILE"
echo "✅ 任务已添加"
echo ""
echo "任务队列: $QUEUE_FILE"
echo "执行时间: $TIME"
echo "主题: $TOPIC"
echo "类型: $TYPE"
echo "数量: $COUNT"
echo ""
echo "要查看队列吗? (cat $QUEUE_FILE)"
+212
View File
@@ -0,0 +1,212 @@
#!/bin/bash
# 1号机学习工作流 v3.0
# 完整流程: 搜索 → 学习 → 分析 → 总结 → 内化
LEARNING_DIR="/root/.openclaw/workspace/memory"
BRAVE_API_KEY="BSAPuOacSUCIDGzg53VSPTcMQI_p0_G"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
echo "=== 1号机学习任务开始 ==="
echo "时间: $DATE"
echo ""
# ========================
# Brave 搜索函数
# ========================
brave_search() {
local query="$1"
local count="${2:-5}"
echo "🔍 搜索: $query"
local response
response=$(curl -s -H "X-Subscription-Token: $BRAVE_API_KEY" \
"https://api.search.brave.com/res/v1/web/search?q=$(echo "$query" | tr ' ' '+')&count=$count")
if [ -z "$response" ]; then
echo " ✗ 搜索失败"
return 1
fi
# 提取 URL
local urls
urls=$(echo "$response" | grep -oE '"url":"[^"]+"' | sed 's/"url":"//;s/"$//' | head -"$count")
if [ -z "$urls" ]; then
echo " ✗ 未找到结果"
return 1
fi
echo " ✓ 找到 $(echo "$urls" | wc -l) 个结果"
echo "$urls"
}
# ========================
# 学习 + 分析函数
# ========================
learn_and_analyze() {
local topic="$1"
local category="$2" # article / novel / stock
local url="$3"
local output_dir="$LEARNING_DIR/$category"
echo " 📚 学习: $url"
mkdir -p "$output_dir/completed"
# 获取内容
local content
content=$(curl -s "$url" 2>/dev/null)
if [ -z "$content" ]; then
echo " ✗ 获取失败"
return 1
fi
local output_file="$output_dir/completed/$(echo "$url" | md5sum | cut -d' ' -f1).md"
# 生成分析报告
{
echo "# $url"
echo "主题: $topic"
echo "分类: $category"
echo "学习时间: $DATE"
echo ""
echo "---"
echo ""
echo "## 📝 原文内容"
echo ""
echo "$content"
echo ""
echo "---"
echo ""
echo "## 🧠 分析总结"
echo ""
echo "### 核心观点"
echo "- "
echo ""
echo "### 关键要点"
echo "- "
echo ""
echo "### 启发思考"
echo "- "
echo ""
echo "### 与已有知识的关联"
echo "- "
echo ""
echo "### 可应用场景"
echo "- "
echo ""
echo "## 📚 内化笔记"
echo ""
echo "用自己的话复述:"
echo ""
echo "---"
echo "学习完成: $DATE"
} >> "$output_file"
echo " ✓ 完成: $(basename "$output_file")"
}
# ========================
# 股票特殊处理
# ========================
analyze_stock() {
local symbol="$1"
local output_dir="$LEARNING_DIR/stocks"
mkdir -p "$output_dir/completed"
echo " 📈 分析: $symbol"
# 获取股票数据
local api_data
api_data=$(curl -s "https://query1.finance.yahoo.com/v8/finance/chart/$symbol?interval=1d&range=1mo" 2>/dev/null)
local close_price
close_price=$(echo "$api_data" | grep -oE '"close":\[[0-9.]+\]' | grep -oE '[0-9.]+' | tail -1)
local output_file="$output_dir/completed/${symbol}_$(date '+%Y%m%d').md"
{
echo "# 股票分析: $symbol"
echo "分析时间: $DATE"
echo ""
echo "## 📊 数据概览"
echo "- 当前价格: ${close_price:-N/A}"
echo ""
echo "## 🧠 技术分析"
echo ""
echo "### 趋势判断"
echo "- 短期: 待分析"
echo "- 中期: 待分析"
echo ""
echo "### 核心要点"
echo "- 行业:"
echo "- 财务:"
echo ""
echo "### 操作建议"
echo "- 买入:"
echo "- 卖出:"
echo ""
echo "---"
echo "分析完成: $DATE"
} >> "$output_file"
echo " ✓ 完成: $output_file"
}
# ========================
# 主流程
# ========================
main() {
local topic="$1"
local category="$2" # article / novel / stock
local count="${3:-5}"
if [ -z "$topic" ]; then
echo "用法: $0 <主题> <类型> [数量]"
echo " 类型: article(文章) / novel(小说) / stock(股票)"
echo " 示例: $0 '机器学习' article 5"
echo " 示例: $0 'AAPL' stock 1"
return 1
fi
echo "🎯 目标: $topic"
echo "📂 类型: $category}"
echo ""
# 执行搜索
local urls
urls=$(brave_search "$topic" "$count")
if [ -z "$urls" ]; then
echo "✗ 搜索失败,退出"
return 1
fi
echo ""
echo "=== 开始学习 ==="
# 学习每个结果
local success=0
local total=0
while IFS= read -r url; do
if [ -n "$url" ]; then
total=$((total + 1))
if [ "$category" = "stock" ]; then
analyze_stock "$topic"
else
learn_and_analyze "$topic" "$category" "$url"
fi
success=$((success + 1))
fi
done <<< "$urls"
echo ""
echo "=== 学习完成 ==="
echo "成功: $success/$total"
echo "结果: $LEARNING_DIR/$category/completed/"
}
main "$@"
+394
View File
@@ -0,0 +1,394 @@
#!/bin/bash
# OpenClaw Dog 守护程序 - 优化重试版
# 功能:监控 Gateway 状态,自动修复故障
# 特性:智能重试机制(指数退避 + 错误类型适配)
# ==================== 配置 ====================
LOG_DIR="/root/.openclaw/logs"
STATUS_FILE="$LOG_DIR/guardian_status.json"
METRICS_FILE="$LOG_DIR/guardian_metrics.json"
BACKUP_DIR="/root/.openclaw/backup"
CONFIG_FILE="/root/.openclaw/openclaw.json"
LOG_FILE="$LOG_DIR/guardian.log"
PID_FILE="$LOG_DIR/guardian.pid"
GATEWAY_PORT=18789
GATEWAY_PROCESS="openclaw.*gateway"
# 锁清理配置
SESSION_LOCK_DIR="/root/.openclaw/agents/main/sessions"
LOCK_CLEAN_MIN=10
# 检查配置
FAILURE_THRESHOLD=3
MAX_RETRIES=3 # 增加重试次数
INITIAL_RETRY_DELAY=10 # 初始重试延迟(秒)
MAX_RETRY_DELAY=120 # 最大重试延迟(秒)
BACKOFF_FACTOR=2 # 指数退避因子
FAILURE_THRESHOLD=3
STARTUP_WAIT=30
MAX_BACKUPS=10
# ==================== 智能重试函数 ====================
# 计算下一次重试延迟(指数退避)
calculate_retry_delay() {
local attempt=$1
local delay=$INITIAL_RETRY_DELAY
# 指数退避: delay = initial * (factor ^ (attempt-1))
for i in $(seq 2 $attempt); do
delay=$((delay * BACKOFF_FACTOR))
done
# 不超过最大延迟
[ $delay -gt $MAX_RETRY_DELAY ] && delay=$MAX_RETRY_DELAY
echo $delay
}
# 根据错误类型获取建议的重试延迟
get_error_based_delay() {
local error_msg=$1
# 网络错误 - 较短延迟
if echo "$error_msg" | grep -qi "network\|connection\|timeout"; then
echo 15
# 权限错误 - 中等延迟
elif echo "$error_msg" | grep -qi "permission\|denied\|auth"; then
echo 30
# 资源不足 - 较长延迟
elif echo "$error_msg" | grep -qi "memory\|cpu\|resource"; then
echo 60
# 默认使用指数退避
else
echo 0 # 使用默认指数退避
fi
}
# 智能重试函数
smart_retry() {
local max_attempts=$1
local attempt=1
local success=0
while [ $attempt -le $max_attempts ]; do
# 执行检查
if check_gateway; then
success=1
break
fi
# 获取错误信息
local error_msg=$(check_gateway 2>&1)
# 计算延迟
local delay
local specific_delay=$(get_error_based_delay "$error_msg")
if [ $specific_delay -gt 0 ]; then
delay=$specific_delay
else
delay=$(calculate_retry_delay $attempt)
fi
log "RETRY" "Attempt $attempt/$max_attempts failed, waiting ${delay}s..."
sleep $delay
attempt=$((attempt + 1))
done
return $success
}
# ==================== 会话锁清理 ====================
clean_stale_locks() {
local cleaned=0
local now=$(date +%s)
find "$SESSION_LOCK_DIR" -name "*.lock" -type f 2>/dev/null | while read lockfile; do
local age=$(($(date +%s) - $(stat -c %Y "$lockfile" 2>/dev/null || echo 0)))
local age_min=$((age / 60))
if [ $age_min -gt $LOCK_CLEAN_MIN ]; then
local pid=$(grep -o '"pid":[0-9]*' "$lockfile" 2>/dev/null | cut -d':' -f2)
if [ -n "$pid" ]; then
if ! ps -p "$pid" > /dev/null 2>&1; then
rm -f "$lockfile"
log "CLEAN" "Removed stale lock: $(basename $lockfile) (age: ${age_min}min)"
cleaned=$((cleaned + 1))
fi
else
rm -f "$lockfile"
cleaned=$((cleaned + 1))
fi
fi
done
[ $cleaned -gt 0 ] && log "CLEAN" "Cleaned $cleaned stale locks"
return 0
}
# ==================== 并发函数 ====================
check_single_instance() {
if [ -f "$PID_FILE" ]; then
local old_pid=$(cat "$PID_FILE" 2>/dev/null)
if [ -n "$old_pid" ] && kill -0 "$old_pid" 2>/dev/null; then
return 1
fi
fi
echo $$ > "$PID_FILE"
return 0
}
cleanup_pid() {
rm -f "$PID_FILE"
}
# ==================== 日志 ====================
log() {
local level=$1
shift
local msg="$@"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $msg" >> "$LOG_FILE"
echo "[$timestamp] [$level] $msg"
}
log_header() {
log "=================================================="
log " OpenClaw Dog - Gateway Guardian (Smart Retry)"
log "=================================================="
}
log_status() {
log " Gateway: $1 | Fail: $2/$3 | Retry: $4/$5"
}
log_summary() {
local runs=$1 rate=$2 fails=$3 restarts=$4
log "--------------------------------------------------"
log " STATS: Runs=$runs | Success=$rate% | Fail=$fails | Restart=$restarts"
log "--------------------------------------------------"
}
# ==================== 核心函数 ====================
get_timestamp_ms() { date +%s%3N; }
get_elapsed_ms() { echo $(($(date +%s%3N) - $1)); }
get_system_load() { uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | tr -d ','; }
get_gateway_pid() { pgrep -f "$GATEWAY_PROCESS" | head -1; }
check_port() { ss -tlnp 2>/dev/null | grep -q ":$GATEWAY_PORT"; }
check_http() {
curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "http://127.0.0.1:$GATEWAY_PORT/" 2>/dev/null
}
check_gateway() {
local issues=0
[ -z "$(get_gateway_pid)" ] && ((issues++))
check_port || ((issues++))
[ "$(check_http)" != "200" ] && ((issues++))
return $issues
}
# ==================== 状态管理 ====================
read_status() { [ -f "$STATUS_FILE" ] && cat "$STATUS_FILE" || echo '{"failure_count":0,"retry_count":0}'; }
get_value() { echo "$1" | grep -o "\"$2\":[0-9]*" | cut -d':' -f2; }
save_status() {
cat > "$STATUS_FILE" << EOF
{
"failure_count": $1,
"retry_count": $2,
"last_check": "$(date '+%Y-%m-%d %H:%M:%S')"
}
EOF
}
record_metrics() {
local time=$1 result=$2
local runs=1 fails=0 restarts=0
if [ -f "$METRICS_FILE" ]; then
runs=$(($(grep -o '"total_runs":[0-9]*' "$METRICS_FILE" | cut -d':' -f2) + 1))
fails=$(grep -o '"total_failures":[0-9]*' "$METRICS_FILE" | cut -d':' -f2)
restarts=$(grep -o '"total_restarts":[0-9]*' "$METRICS_FILE" | cut -d':' -f2)
[ -z "$fails" ] && fails=0
[ -z "$restarts" ] && restarts=0
[ "$result" != "success" ] && fails=$((fails + 1))
[ "$result" == "restarted" ] && restarts=$((restarts + 1))
fi
local rate=$((100 - (fails * 100 / runs)))
cat > "$METRICS_FILE" << EOF
{
"total_runs": $runs,
"total_failures": $fails,
"total_restarts": $restarts,
"success_rate": $rate,
"avg_execution_ms": $time,
"last_run": "$(date '+%Y-%m-%d %H:%M:%S')",
"last_result": "$result"
}
EOF
echo "$runs,$rate,$fails,$restarts"
}
# ==================== 维修模块 ====================
backup_config() {
mkdir -p "$BACKUP_DIR"
local bf="${BACKUP_DIR}/openclaw_$(date '+%Y%m%d_%H%M%S').json"
[ -f "$CONFIG_FILE" ] && cp "$CONFIG_FILE" "$bf" && log "REPAIR" "Backup: $(basename $bf)"
echo "$bf"
}
list_backups() { ls -t "${BACKUP_DIR}"/openclaw_*.json 2>/dev/null; }
restore_config() {
[ -f "$1" ] && cp "$1" "$CONFIG_FILE" && log "REPAIR" "Restored: $(basename $1)"
}
restart_gateway() {
log "REPAIR" "Restarting Gateway..."
systemctl --user restart openclaw-gateway.service
}
repair_gateway() {
log "REPAIR" "=== ENTER REPAIR MODE ==="
local current=$(backup_config)
local backups=$(list_backups)
local count=$(echo "$backups" | wc -l)
log "REPAIR" "Found $count backups"
local attempt=1 success=0
for backup in $backups; do
[ $attempt -gt $MAX_BACKUPS ] && break
log "REPAIR" "Try #$attempt: $(basename $backup)"
restore_config "$backup"
restart_gateway
sleep 10
if check_gateway; then
success=1
break
fi
attempt=$((attempt + 1))
done
if [ $success -eq 1 ]; then
log "REPAIR" "SUCCESS: Gateway recovered"
return 0
else
log "REPAIR" "FAILED: Restore original"
restore_config "$current"
restart_gateway
log "REPAIR" "!!! REPAIR COMPLETELY FAILED !!!"
return 1
fi
}
# ==================== 主程序 ====================
main() {
if ! check_single_instance; then
log "WARN" "Another instance is running, exiting"
exit 1
fi
trap cleanup_pid EXIT
# 先清理过期会话锁
log "CLEAN" "=== Session Lock Cleanup ==="
clean_stale_locks
local start=$(get_timestamp_ms)
log_header
local status=$(read_status)
local failure=$(get_value "$status" "failure_count")
local retry=$(get_value "$status" "retry_count")
[ -z "$failure" ] && failure=0
[ -z "$retry" ] && retry=0
log_status "CHECK" "$failure" "$FAILURE_THRESHOLD" "$retry" "$MAX_RETRIES"
log " Load: $(get_system_load)"
check_gateway
issues=$?
local elapsed=$(get_elapsed_ms $start)
if [ $issues -eq 0 ]; then
[ $failure -gt 0 ] && log " [OK] Gateway recovered" || log " [OK] Gateway healthy"
local m=$(record_metrics $elapsed "success")
local runs=$(echo $m | cut -d',' -f1)
local rate=$(echo $m | cut -d',' -f2)
local fails=$(echo $m | cut -d',' -f3)
local restarts=$(echo $m | cut -d',' -f4)
log_summary $runs $rate $fails $restarts
log " Time: ${elapsed}ms"
save_status 0 0
exit 0
else
failure=$((failure + 1))
if [ $failure -lt $FAILURE_THRESHOLD ]; then
save_status $failure $retry
log " [WARN] Check failed, need $((FAILURE_THRESHOLD - failure)) more"
exit 1
fi
log " [ERROR] $FAILURE_THRESHOLD consecutive failures"
# 使用智能重试
retry=0
while [ $retry -lt $MAX_RETRIES ]; do
retry=$((retry + 1))
if [ $retry -eq 1 ]; then
log " [RETRY] Smart Retry #1 (initial delay: ${INITIAL_RETRY_DELAY}s)"
else
local delay=$(calculate_retry_delay $retry)
log " [RETRY] Smart Retry #$retry (backoff delay: ${delay}s)"
fi
restart_gateway
sleep $STARTUP_WAIT
if check_gateway; then
log " [OK] Gateway recovered after smart retry"
local m=$(record_metrics $elapsed "restarted")
local runs=$(echo $m | cut -d',' -f1)
local rate=$(echo $m | cut -d',' -f2)
local fails=$(echo $m | cut -d',' -f3)
local restarts=$(echo $m | cut -d',' -f4)
log_summary $runs $rate $fails $restarts
save_status 0 0
exit 0
fi
done
# 维修
log " [ERROR] All smart retries failed, entering repair..."
if repair_gateway; then
record_metrics $elapsed "repaired"
save_status 0 0
exit 0
else
record_metrics $elapsed "failed"
save_status $FAILURE_THRESHOLD $MAX_RETRIES
exit 2
fi
fi
}
main
+121
View File
@@ -0,0 +1,121 @@
#!/bin/bash
# 1号机任务检查脚本
# 定时检查任务队列,自动执行学习任务
TASK_QUEUE="/root/.openclaw/workspace/memory/task_queue.txt"
LEARN_SCRIPT="/root/.openclaw/tools/learn-workflow.sh"
REPORT_DIR="/root/.openclaw/workspace/memory/reports"
LOG_FILE="/root/.openclaw/workspace/memory/task.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
mkdir -p "$REPORT_DIR"
echo "=== 任务检查: $DATE ===" >> "$LOG_FILE"
# 检查任务队列是否存在
if [ ! -f "$TASK_QUEUE" ]; then
echo "队列文件不存在" >> "$LOG_FILE"
exit 0
fi
# 当前时间戳
NOW=$(date +%s)
# 读取并执行到期任务
TEMP_FILE=$(mktemp)
COMPLETED_FILE=$(mktemp)
REPORT_FILE="$REPORT_DIR/$(date '+%Y%m%d_%H%M%S').report"
# 开始报告
{
echo "任务执行报告"
echo "时间: $DATE"
echo "================"
} > "$REPORT_FILE"
# 读取并执行到期任务
while IFS= read -r line; do
# 跳过注释和空行
[[ "$line" =~ ^#.*$ ]] && continue
[[ -z "$line" ]] && continue
# 解析: 时间|主题|类型|数量
TIMESTAMP=$(echo "$line" | cut -d'|' -f1)
TOPIC=$(echo "$line" | cut -d'|' -f2)
TYPE=$(echo "$line" | cut -d'|' -f3)
COUNT=$(echo "$line" | cut -d'|' -f4)
# 转换时间为秒
TASK_SECONDS=$(date -d "$TIMESTAMP" +%s 2>/dev/null)
if [ -z "$TASK_SECONDS" ]; then
echo " ⚠️ 无效时间格式: $TIMESTAMP"
echo "[跳过] $TIMESTAMP | $TOPIC | 无效时间格式" >> "$REPORT_FILE"
continue
fi
# 检查是否到期
if [ "$TASK_SECONDS" -le "$NOW" ]; then
echo "执行: $TOPIC ($TYPE) x$COUNT" >> "$LOG_FILE"
echo "- 任务: $TOPIC" >> "$REPORT_FILE"
echo " 类型: $TYPE" >> "$REPORT_FILE"
echo " 数量: $COUNT" >> "$REPORT_FILE"
echo " 状态: " >> "$REPORT_FILE"
# 执行学习任务
TASK_LOG=$(mktemp)
if "$LEARN_SCRIPT" "$TOPIC" "$TYPE" "$COUNT" >> "$TASK_LOG" 2>&1; then
echo " ✓ 完成: $TOPIC" >> "$LOG_FILE"
echo " 完成" >> "$REPORT_FILE"
# 记录到已完成
echo "$line" >> "$COMPLETED_FILE"
else
echo " ✗ 失败: $TOPIC" >> "$LOG_FILE"
echo " 失败 (保留重试)" >> "$REPORT_FILE"
# 保留到下一轮
echo "$line" >> "$TEMP_FILE"
fi
# 追加任务日志
echo " 日志:" >> "$REPORT_FILE"
sed 's/^/ /' "$TASK_LOG" >> "$REPORT_FILE"
rm -f "$TASK_LOG"
else
# 未到期,保留
echo "$line" >> "$TEMP_FILE"
fi
done < "$TASK_QUEUE"
# 结束报告
{
echo "================"
echo "完成: $(date '+%Y-%m-%d %H:%M:%S')"
} >> "$REPORT_FILE"
# 更新任务队列
if [ -f "$COMPLETED_FILE" ]; then
# 添加已完成标记
echo "" >> "$COMPLETED_FILE"
echo "# 完成于: $DATE" >> "$COMPLETED_FILE"
cat "$COMPLETED_FILE" >> "$TASK_QUEUE.completed"
fi
if [ -f "$TEMP_FILE" ] && [ -s "$TEMP_FILE" ]; then
mv "$TEMP_FILE" "$TASK_QUEUE"
else
rm -f "$TASK_QUEUE"
fi
# 清理
rm -f "$COMPLETED_FILE"
# 清理旧报告 (保留最近3天)
find "$REPORT_DIR" -name "*.report" -mtime +3 -delete
echo "检查完成: $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
# 显示报告摘要
if [ -f "$REPORT_FILE" ]; then
LINES=$(wc -l < "$REPORT_FILE")
echo "报告: $REPORT_FILE ($LINES 行)"
fi