Files
my-project/config/openclaw/scripts/novel-learning/novel-health-check.sh
T

600 lines
17 KiB
Bash
Executable File

#!/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 "$@"