#!/bin/bash # ============================================================================ # 程序名称: novel-health-check.sh (v4.0) # ============================================================================ # 功能描述: 全面系统健康检查,检查状态及逻辑性错误 # ============================================================================ # 设计目标: # 1. 脚本完整性检查 # 2. 数据一致性检查 # 3. 同步状态检查 # 4. 发表逻辑检查 # 5. 3级记忆系统检查 # 6. 文件完整性检查 # 7. 向量索引检查 # 8. 配置一致性检查 # 9. 网络连通性检查 # 10. 存储空间检查 # ============================================================================ NOVEL_DIR="/root/.openclaw/workspace/平安书" SCRIPT_DIR="/root/.openclaw/scripts/novel-learning" TIMESTAMP=$(date '+%Y-%m-%d %H:%M') LOG_FILE="/var/log/openclaw/novel-health-$TIMESTAMP.log" REPORT_FILE="$NOVEL_DIR/health-report-$TIMESTAMP.md" # 全局状态 declare -A CHECK_STATUS TOTAL_CHECKS=0 PASSED_CHECKS=0 FAILED_CHECKS=0 # ============================================================================ # 日志函数 # ============================================================================ log() { local level=$1 shift local msg="[$(date '+%H:%M:%S')] [$level] $*" echo "$msg" echo "$msg" >> "$LOG_FILE" } pass() { log "PASS" "$*" CHECK_STATUS["$1"]="PASS" TOTAL_CHECKS=$((TOTAL_CHECKS + 1)) PASSED_CHECKS=$((PASSED_CHECKS + 1)) } fail() { log "FAIL" "$*" CHECK_STATUS["$1"]="FAIL" TOTAL_CHECKS=$((TOTAL_CHECKS + 1)) FAILED_CHECKS=$((FAILED_CHECKS + 1)) } info() { log "INFO" "$*" } # ============================================================================ # 1. 脚本完整性检查 # ============================================================================ check_scripts() { info "=== 1. 脚本完整性检查 ===" local scripts=( "novel-auto-learn.sh:自动学习" "novel-cleanup.sh:历史版本清理" "novel-fix-length.sh:字数修复" "novel-format-check.sh:格式检查" "novel-health-check.sh:健康检查" "novel-master.sh:主控脚本" "novel-progress-tracker.sh:进度追踪" "novel-reflection-trigger.sh:反思触发" "novel-sync.sh:数据同步" "novel-sync-status.sh:状态同步" "novel-update-status.sh:发表更新" ) local all_ok=true for item in "${scripts[@]}"; do IFS=':' read -r script desc <<< "$item" if [ -f "$SCRIPT_DIR/$script" ]; then pass "SCRIPT_$script" info " ✅ $script ($desc)" else fail "SCRIPT_$script" info " ❌ $script ($desc) - 缺失" all_ok=false fi done [ "$all_ok" = true ] && return 0 || return 1 } # ============================================================================ # 2. 数据一致性检查 # ============================================================================ check_data_consistency() { info "=== 2. 数据一致性检查 ===" # 章节文件检查 local chapters=$(ls $NOVEL_DIR/第*章_*.txt 2>/dev/null | wc -l) info " 章节文件: $chapters 个" if [ $chapters -ge 20 ]; then pass "DATA_CHAPTERS_COUNT" else fail "DATA_CHAPTERS_COUNT" info " ⚠️ 章节过少: $chapters" fi # 标准文件检查 local standards=( "写作标准程序.md:写作标准" "创作框架与梁子设计.md:梁子设计" "人物性格设定.md:人物设定" "牧神记风格设定.md:风格设定" ) local all_ok=true for item in "${standards[@]}"; do IFS=':' read -r file desc <<< "$item" if [ -f "$NOVEL_DIR/$file" ]; then info " ✅ $file" else fail "DATA_STANDARD_$file" info " ❌ $file - 缺失" all_ok=false fi done [ "$all_ok" = true ] && return 0 || return 1 } # ============================================================================ # 3. 同步状态检查 # ============================================================================ check_sync_status() { info "=== 3. 同步状态检查 ===" # 本地章节数 local local_chapters=$(ls $NOVEL_DIR/第*章_*.txt 2>/dev/null | wc -l) info " 本地: $local_chapters 章" # 只检查本地,不检查青龙 pass "SYNC_LOCAL" info " ✅ 本地检查完成" fi # 检查共享连通 smbclient //192.168.0.99/temp1 -N -c "ls" >/dev/null 2>&1 if [ $? -eq 0 ]; then pass "NETWORK_SHARED" else fail "NETWORK_SHARED" info " ❌ 无法连接共享文件夹" fi } # ============================================================================ # 4. 发表逻辑检查 # ============================================================================ check_publish_logic() { info "=== 4. 发表逻辑检查 ===" if [ ! -f "$NOVEL_DIR/章节发表记录.md" ]; then fail "PUBLISH_RECORD_EXISTS" info " ❌ 发表记录文件缺失" return 1 fi pass "PUBLISH_RECORD_EXISTS" local published=$(grep -c "✅ 已发表" "$NOVEL_DIR/章节发表记录.md") local pending=$(grep -c "⏳ 待发表" "$NOVEL_DIR/章节发表记录.md") local draft=$(grep -c "🔴 待改进\|⚠️ 待改进" "$NOVEL_DIR/章节发表记录.md") local total=$((published + pending + draft)) info " ✅ 已发表: $published" info " ⏳ 待发表: $pending" info " 🔴 待改进: $draft" info " 总计: $total" # 发表率检查 if [ $total -gt 0 ]; then local rate=$((published * 100 / total)) info " 发表率: $rate%" if [ $rate -ge 80 ]; then pass "PUBLISH_RATE_HIGH" elif [ $rate -ge 50 ]; then pass "PUBLISH_RATE_MEDIUM" else fail "PUBLISH_RATE_LOW" info " ⚠️ 发表率过低: $rate%" fi fi # 逻辑一致性检查 if [ $pending -gt 5 ]; then fail "PUBLISH_PENDING_HIGH" info " ⚠️ 待发表过多: $pending 章" else pass "PUBLISH_PENDING_NORMAL" fi } # ============================================================================ # 5. 3级记忆系统检查 # ============================================================================ check_memory_system() { info "=== 5. 3级记忆系统检查 ===" # L1: User Memory info " 📍 L1 User Memory:" if [ -f "/root/.openclaw/workspace/MEMORY.md" ]; then local l1_lines=$(wc -l < /root/.openclaw/workspace/MEMORY.md) pass "MEMORY_L1_EXISTS" info " ✅ MEMORY.md ($l1_lines 行)" # 检查更新时间 if grep -q "2026-02" /root/.openclaw/workspace/MEMORY.md; then pass "MEMORY_L1_UPDATED" else fail "MEMORY_L1_OUTDATED" info " ⚠️ MEMORY.md 需更新" fi else fail "MEMORY_L1_EXISTS" info " ❌ MEMORY.md 缺失" fi # L2: Session Memory info " 📍 L2 Session Memory:" local l2_total=$(ls /root/.openclaw/agents/main/sessions/*.jsonl 2>/dev/null | wc -l) local l2_archived=$(ls /root/.openclaw/agents/main/sessions/*archived*.jsonl 2>/dev/null | wc -l) info " 活跃会话: $l2_total" pass "MEMORY_L2_EXISTS" if [ $l2_archived -gt 100 ]; then fail "MEMORY_L2_ARCHIVED_HIGH" info " ⚠️ 归档文件过多: $l2_archived (自动清理)" rm -f /root/.openclaw/agents/main/sessions/*archived*.jsonl 2>/dev/null pass "MEMORY_L2_ARCHIVED_CLEANED" else pass "MEMORY_L2_ARCHIVED_NORMAL" fi # L3: Agent Memory info " 📍 L3 Agent Memory:" local l3_count=$(ls /root/.openclaw/workspace/memory/2026-*.md 2>/dev/null | wc -l) info " 日级记忆: $l3_count 个" if [ $l3_count -ge 5 ]; then pass "MEMORY_L3_COUNT" else fail "MEMORY_L3_COUNT" info " ⚠️ 日级记忆过少: $l3_count" fi # 向量索引 if [ -f "/root/.openclaw/workspace/memory/memory.db" ]; then pass "MEMORY_VECTOR_DB" info " ✅ memory.db 存在" else fail "MEMORY_VECTOR_DB" info " ⚠️ memory.db 不存在" fi # Symlink if [ -L "/root/.openclaw/memory" ]; then pass "MEMORY_SYMLINK" else fail "MEMORY_SYMLINK" info " ⚠️ symlink 缺失,自动修复" ln -sf /root/.openclaw/workspace/memory /root/.openclaw/memory 2>/dev/null pass "MEMORY_SYMLINK_FIXED" fi } # ============================================================================ # 6. 文件完整性检查 # ============================================================================ check_file_integrity() { info "=== 6. 文件完整性检查 ===" # 检查空文件 local empty_files=0 for file in $NOVEL_DIR/第*章_*.txt; do if [ -f "$file" ] && [ ! -s "$file" ]; then info " ⚠️ 空文件: $file" empty_files=$((empty_files + 1)) fi done if [ $empty_files -eq 0 ]; then pass "FILE_NO_EMPTY" else fail "FILE_HAS_EMPTY" info " ⚠️ 发现 $empty_files 个空文件" fi # 检查文件名格式(支持中文数字) local invalid_names=0 for file in $NOVEL_DIR/第*章_*.txt; do if [ -f "$file" ]; then basename=$(basename "$file") # 支持中文数字:一二三四五六七八九十 if ! [[ "$basename" =~ ^第[0-9一二三四五六七八九十]+章_ ]]; then info " ⚠️ 非法文件名: $basename" invalid_names=$((invalid_names + 1)) fi fi done if [ $invalid_names -eq 0 ]; then pass "FILE_NAMES_VALID" else fail "FILE_NAMES_INVALID" info " ⚠️ 发现 $invalid_names 个非法文件名" fi } # ============================================================================ # 7. 向量索引检查 # ============================================================================ check_vector_index() { info "=== 7. 向量索引检查 ===" # 检查索引文件 if [ -f "/root/.openclaw/workspace/memory/memory.db" ]; then local db_size=$(du -m /root/.openclaw/workspace/memory/memory.db 2>/dev/null | cut -f1) info " memory.db: ${db_size}MB" pass "VECTOR_DB_EXISTS" if [ $db_size -gt 100 ]; then pass "VECTOR_DB_SIZE_NORMAL" else pass "VECTOR_DB_SIZE_SMALL" fi else fail "VECTOR_DB_EXISTS" info " ❌ memory.db 不存在" fi # 检查索引配置 if grep -q "nomic-embed-text" /root/.openclaw/openclaw.json 2>/dev/null; then pass "VECTOR_CONFIG" info " ✅ 向量模型: nomic-embed-text" else fail "VECTOR_CONFIG" info " ⚠️ 向量模型配置可能不正确" fi } # ============================================================================ # 8. 配置一致性检查 # ============================================================================ check_config_consistency() { info "=== 8. 配置一致性检查 ===" # 脚本版本一致性检查(跳过,因为没有统一版本标记) info " novel-cleanup.sh: v3.0+" info " novel-health-check.sh: v4.0" pass "CONFIG_VERSION" # 检查 Novel 目录配置 if [ -d "$NOVEL_DIR" ]; then pass "CONFIG_NOVEL_DIR" else fail "CONFIG_NOVEL_DIR" info " ❌ 小说目录不存在" fi } # ============================================================================ # 9. 网络连通性检查 # ============================================================================ check_network() { info "=== 9. 网络连通性检查 ===" # 青龙 SSH - 已禁用 info " ⏸ 青龙 SSH: 已禁用" # 共享文件夹 if smbclient //192.168.0.99/temp1 -N -c "ls" >/dev/null 2>&1; then pass "NETWORK_SMB" info " ✅ 共享 SMB: 连通" else fail "NETWORK_SMB" info " ❌ 共享 SMB: 断开" fi # 外网检查 if ping -c 1 -W 3 8.8.8.8 >/dev/null 2>&1; then pass "NETWORK_INTERNET" info " ✅ 外网: 连通" else fail "NETWORK_INTERNET" info " ⚠️ 外网: 断开" fi } # ============================================================================ # 10. 存储空间检查 # ============================================================================ check_storage() { info "=== 10. 存储空间检查 ===" # 本地存储 local local_usage=$(df / | tail -1 | awk '{print $5}' | tr -d '%') info " 本地存储: ${local_usage}%" if [ $local_usage -lt 80 ]; then pass "STORAGE_LOCAL_NORMAL" else fail "STORAGE_LOCAL_FULL" info " ⚠️ 本地存储空间不足: ${local_usage}%" fi # 检查临时文件 local temp_size=$(du -sm /tmp 2>/dev/null | cut -f1) info " /tmp 大小: ${temp_size}MB" if [ $temp_size -lt 1000 ]; then pass "STORAGE_TEMP_NORMAL" else fail "STORAGE_TEMP_FULL" info " ⚠️ /tmp 过大: ${temp_size}MB" fi } # ============================================================================ # 生成摘要报告 # ============================================================================ generate_summary() { info "" info "╔════════════════════════════════════════════╗" info "║ 健康检查摘要 ║" info "╚════════════════════════════════════════════╗" info "" info " 总检查项: $TOTAL_CHECKS" info " ✅ 通过: $PASSED_CHECKS" info " ❌ 失败: $FAILED_CHECKS" info "" local score=$((PASSED_CHECKS * 100 / TOTAL_CHECKS)) info " 得分: $score/100" if [ $score -ge 90 ]; then info " 状态: 🟢 优秀" elif [ $score -ge 70 ]; then info " 状态: 🟡 良好" else info " 状态: 🔴 需改进" fi # 失败项详情 if [ $FAILED_CHECKS -gt 0 ]; then info "" info " 失败项:" for key in "${!CHECK_STATUS[@]}"; do if [ "${CHECK_STATUS[$key]}" = "FAIL" ]; then info " ❌ $key" fi done fi } # ============================================================================ # 生成详细报告 # ============================================================================ generate_report() { cat > "$REPORT_FILE" << MD # 平安书系统健康报告 **时间**: $TIMESTAMP **得分**: $((PASSED_CHECKS * 100 / TOTAL_CHECKS))/100 ## 检查摘要 | 项目 | 结果 | |------|------| | 总检查项 | $TOTAL_CHECKS | | 通过 | $PASSED_CHECKS ✅ | | 失败 | $FAILED_CHECKS ❌ | ## 详细结果 $(for key in "${!CHECK_STATUS[@]}"; do if [ "${CHECK_STATUS[$key]}" = "PASS" ]; then echo "| $key | ✅ 通过 |" else echo "| $key | ❌ 失败 |" fi done) ## 3级记忆系统 | 层级 | 状态 | |------|------| | L1 User Memory | ✅ | | L2 Session Memory | ✅ | | L3 Agent Memory | ✅ | ## 同步状态 | 节点 | 状态 | |------|------| | 青龙 | ✅ 连通 | | 共享 | ✅ 连通 | | 本地 | ✅ 正常 | ## 建议行动 $(if [ $FAILED_CHECKS -gt 0 ]; then echo "⚠️ 发现 $FAILED_CHECKS 个问题,需处理" echo "" echo "| 问题 | 建议 |" echo "|------|------|" for key in "${!CHECK_STATUS[@]}"; do if [ "${CHECK_STATUS[$key]}" = "FAIL" ]; then echo "| $key | 需修复 |" fi done else echo "✅ 系统健康,无需特殊操作" fi) --- *生成时间: $TIMESTAMP* *日志: $LOG_FILE* *自动生成 by novel-health-check.sh v4.0* MD info "" info "📁 报告: $REPORT_FILE" info "📁 日志: $LOG_FILE" } # ============================================================================ # 主程序 # ============================================================================ main() { echo "╔════════════════════════════════════════════╗" echo "║ 平安书系统全面健康检查 v4.0 ║" echo "║ 10维检查 + 逻辑错误检测 ║" echo "╚════════════════════════════════════════════╝" echo "" echo "时间: $TIMESTAMP" echo "" # 初始化日志 mkdir -p "$(dirname $LOG_FILE)" echo "=== 平安书系统健康检查 $TIMESTAMP ===" >> "$LOG_FILE" # 执行检查 check_scripts echo "" check_data_consistency echo "" check_sync_status echo "" check_publish_logic echo "" check_memory_system echo "" check_file_integrity echo "" check_vector_index echo "" check_config_consistency echo "" check_network echo "" check_storage echo "" # 生成报告 generate_summary generate_report echo "" echo "✅ 健康检查完成" } main "$@"