xiaowei-system/scripts/config-protector.sh

160 lines
4.4 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# ============================================================
# config-protector.sh — 配置保护器
# 作用:在每次修改配置前自动备份
# 修改后健康检查失败 → 自动回滚
# 成功 → 标记为新的稳定点
# 由 health-watchdog.sh 联动触发
# 也支持手动调用config-protector.sh [snapshot|rollback|status]
# ============================================================
set -e
CONFIG_DIR="$HOME/.hermes"
LOG="$HOME/.hermes/watchdog/config-protector.log"
mkdir -p "$(dirname "$LOG")"
log() { echo "[$(date '+%H:%M:%S')] $*" | tee -a "$LOG"; }
# === 快照:记录当前配置状态 ===
snapshot() {
cd "$CONFIG_DIR"
# 检查是否有未提交的变更
if git diff --quiet && git diff --cached --quiet; then
log "✅ 配置无变更,无需快照"
return 0
fi
# 有变更 → 自动 commit
git add -A 2>/dev/null
local changed=$(git diff --cached --name-only | head -5)
git commit -m "auto-snapshot $(date '+%Y-%m-%d %H:%M:%S')" 2>&1 | tail -1 | log
log "📸 快照已保存(变更文件:${changed:-无描述}"
# 标记最近配置
git tag -f last-config 2>/dev/null
return 0
}
# === 回滚:恢复到上次稳定点 ===
rollback() {
cd "$CONFIG_DIR"
local target="${1:-stable}"
if ! git rev-parse --verify "$target" 2>/dev/null; then
log "❌ 回滚目标 '$target' 不存在"
return 1
fi
log "⚠️ 开始回滚到 $target..."
# 保存当前状态(回滚前的状态,用于诊断)
git stash 2>/dev/null || true
# 硬重置到目标
git checkout --force "$target" 2>&1 | log
log "✅ 已回滚到 $target"
log "📋 受影响文件:$(git diff --name-only HEAD~1..HEAD 2>/dev/null | head -10 || echo '首次回滚')"
# 创建回滚事件记录
echo "$(date '+%Y-%m-%dT%H:%M:%S')|rollback|$target" >> "$CONFIG_DIR/watchdog/rollback-history.txt"
return 0
}
# === 标记当前为稳定 ===
mark_stable() {
cd "$CONFIG_DIR"
local tag="stable-$(date '+%Y%m%d-%H%M%S')"
git tag -f "$tag" 2>/dev/null
git tag -f stable 2>/dev/null
log "⭐ 已标记 $tag 为稳定点"
return 0
}
# === 状态:显示配置保护和最近变更 ===
status() {
cd "$CONFIG_DIR"
echo "=== 配置保护状态 ==="
echo "仓库: $CONFIG_DIR/.git"
echo "最近提交:"
git log --oneline -5 2>/dev/null || echo " (无提交)"
echo ""
echo "未跟踪文件:"
git status --short 2>/dev/null | head -10 || echo " 全部已跟踪"
echo ""
echo "稳定标签:"
git tag -l 'stable-*' | sort -r | head -5 2>/dev/null || echo " (无)"
echo ""
if [ -f "$CONFIG_DIR/watchdog/rollback-history.txt" ]; then
echo "回滚历史:"
tail -3 "$CONFIG_DIR/watchdog/rollback-history.txt"
fi
}
# === 与看门狗联动:健康检测失败时自动回滚 ===
auto_rollback_if_unhealthy() {
# 由 watchdog 调用,检测上次变更后系统是否正常
cd "$CONFIG_DIR"
# 检查最近是否有配置变更30分钟内
local last_change=$(git log --oneline -1 --format="%ct" HEAD 2>/dev/null || echo 0)
local now=$(date +%s)
local age=$(( (now - last_change) / 60 ))
if [ "$age" -gt 30 ]; then
# 上次变更超过30分钟不触发自动回滚
return 0
fi
# 检查关键进程
local dead=""
for p in zhiyid-new new-api hermes bge_embed_server; do
if ! pgrep -f "$p" > /dev/null 2>&1; then
dead="$dead $p"
fi
done
if [ -n "$dead" ]; then
log "🚨 检测到自动回滚条件:最近配置变更后进程挂了($dead)"
log "🔙 自动回滚中..."
rollback "stable"
log "🔄 回滚完成,重启服务..."
# 重启关键服务
systemctl --user restart zhiyid.service bge-embed.service new-api.service 2>/dev/null || true
sleep 5
log "✅ 回滚自愈完成"
return 0
fi
return 0
}
# === 主入口 ===
case "${1:-snapshot}" in
snapshot)
snapshot
;;
rollback)
rollback "$2"
;;
mark-stable)
mark_stable
;;
status)
status
;;
auto-heal)
auto_rollback_if_unhealthy
;;
*)
echo "用法: config-protector.sh [snapshot|rollback <tag>|mark-stable|status|auto-heal]"
;;
esac