SQLite 是单文件、没有外部主从,坏一份就是全丢,而 data/ 一直被 gitignore、 此前没有任何备份。备份做进二进制,不依赖外部 cron / systemd timer。 - 快照用 VACUUM INTO,不用 cp 主库:服务边跑边写时 cp 可能拷到写了一半的页 - 启动时补一次,之后每小时醒一次看是否到期;默认间隔 24h、保留最近 7 份 - 产出自检 SQLite 文件头,不合格即删并报错,不留「看着像备份的废物」 - 新增 -backup 子命令,供升级 / 迁移 / 交付前手工备一份 - 落 data/backups/ —— systemd 单元是 ProtectSystem=strict,只放开了 data/ 可写 - 边界写进文档:只防误删 / 误改 / 写坏,不防整盘损坏,跨机保存仍需人工 配套: - deploy/DELIVERY.md 新增第 7 节「数据备份与恢复」+ 红线条目 - clonezilla-cleanup.sh 提示克隆前清空 data/backups/,避免原型机测试数据被带走 - deploy/eaisalestrain.env 补 4 个备份环境变量 - PROJECT_STATE.md 记 D24 另:清理 worker_task 中 17 条没聊过天的历史空任务(id 1-11、13-18), 删前先备份、清单经确认,删除程序带「命中数与白名单不一致即中止」保险。 该项为一次性数据操作,不产生代码改动。 Co-Authored-By: Claude Code <noreply@anthropic.com>
83 lines
3.4 KiB
Bash
83 lines
3.4 KiB
Bash
#!/usr/bin/env bash
|
|
# ============================================================
|
|
# eai_agentplatform — Clonezilla 整盘克隆前的清理脚本
|
|
# 目标:交付给客户的设备上「无源代码、无开发痕迹、无测试数据、无默认口令」。
|
|
#
|
|
# 用法(在交付原型机上以 root 执行):
|
|
# sudo bash clonezilla-cleanup.sh
|
|
#
|
|
# 脚本只做「可逆的清理」;删除源代码属于不可逆动作,默认 DRY-RUN,
|
|
# 确认无误后加 --confirm 才真正执行删除。
|
|
# ============================================================
|
|
set -euo pipefail
|
|
|
|
APP_DIR="/opt/eai_agentplatform"
|
|
CONFIRM="${1:-}"
|
|
|
|
log() { echo -e "\033[1;32m[OK]\033[0m $*"; }
|
|
warn() { echo -e "\033[1;33m[!!]\033[0m $*"; }
|
|
step() { echo -e "\n\033[1;36m==>\033[0m $*"; }
|
|
|
|
DRY=1
|
|
if [[ "$CONFIRM" == "--confirm" ]]; then DRY=0; warn "已确认,执行真实清理。"; else warn "DRY-RUN 模式:只列出将执行的动作,不实际修改。加 --confirm 真正执行。"; fi
|
|
|
|
step "1. 删除 Go 源代码(二进制保留,源代码不复原)"
|
|
for p in \
|
|
"$APP_DIR/cmd" "$APP_DIR/internal" \
|
|
"$APP_DIR/go.mod" "$APP_DIR/go.sum" \
|
|
"$APP_DIR/*.go"; do
|
|
if compgen -G "$p" >/dev/null 2>&1; then
|
|
echo " 将删除: $p"
|
|
[[ $DRY -eq 0 ]] && rm -rf $p
|
|
fi
|
|
done
|
|
|
|
step "2. 清除版本控制痕迹"
|
|
for p in "$APP_DIR/.git" "$APP_DIR/.gitignore" "$APP_DIR/.github" "$APP_DIR/.gitlab"; do
|
|
if [[ -e "$p" ]]; then
|
|
echo " 将删除: $p"
|
|
[[ $DRY -eq 0 ]] && rm -rf "$p"
|
|
fi
|
|
done
|
|
|
|
step "3. 清理测试/演示数据(保留生产库结构,清空内容)"
|
|
echo " - 提示:测试用户 zhangsan / 演示素材 / 演示考试记录等由管理员在 Web 界面手动清理,"
|
|
echo " 或在克隆前用 sqlite3 执行(见 DELIVERY.md 第 4 节)。脚本不自动清库,避免误删正式数据。"
|
|
echo " - 别漏了 $APP_DIR/data/backups/ :里面是原型机自己的历史快照,含同一批测试数据,"
|
|
echo " 整盘克隆会一起带到客户机器上。确认无用后手工清空该目录(见 DELIVERY.md 第 7 节)。"
|
|
|
|
step "4. 清空日志与 shell 历史"
|
|
for f in "$APP_DIR/logs" "$APP_DIR"/*.log /var/log/eai_agentplatform*.log; do
|
|
if compgen -G "$f" >/dev/null 2>&1; then
|
|
echo " 将清空: $f"
|
|
[[ $DRY -eq 0 ]] && find "$f" -type f -name '*.log' -exec truncate -s 0 {} \; 2>/dev/null || true
|
|
fi
|
|
done
|
|
for h in /root/.bash_history /home/*/.bash_history; do
|
|
if [[ -f "$h" ]]; then
|
|
echo " 将清空: $h"
|
|
[[ $DRY -eq 0 ]] && truncate -s 0 "$h"
|
|
fi
|
|
done
|
|
|
|
step "5. 提示:以下必须手工完成(脚本无法替你决定口令)"
|
|
cat <<'EOF'
|
|
[A] 重置管理员密码:
|
|
sudo -u eai_agentplatform /opt/eai_agentplatform/eai_agentplatform-server -reset-admin '<新强密码>'
|
|
[B] 重新生成 JWT 密钥(写回 /opt/eai_agentplatform/.env):
|
|
python3 -c "import secrets; print('JWT_SECRET='+secrets.token_urlsafe(48))"
|
|
[C] 确认 .env 内无 __CHANGE_ME__ 占位符:
|
|
grep -n '__CHANGE_ME__' /opt/eai_agentplatform/.env && echo '!! 存在未替换占位符' || echo '无占位符'
|
|
EOF
|
|
|
|
step "6. 移除本清理脚本自身(交付物不含脚本)"
|
|
echo " 将删除: $0"
|
|
[[ $DRY -eq 0 ]] && rm -f "$0"
|
|
|
|
echo
|
|
if [[ $DRY -eq 0 ]]; then
|
|
log "清理完成。请复核 [A][B][C] 三项,再执行 Clonezilla 整盘克隆。"
|
|
else
|
|
warn "DRY-RUN 结束,未做任何修改。确认后:sudo bash $0 --confirm"
|
|
fi
|