diff --git a/scripts/db-monitor.sh b/scripts/db-monitor.sh index 43ee9cc1..2f391a86 100755 --- a/scripts/db-monitor.sh +++ b/scripts/db-monitor.sh @@ -39,13 +39,28 @@ do continue fi # 全量 integrity_check(2026-09-06 起不用 quick_check——它会漏检深层页引用/FTS 索引错误) - # -readonly: 只读打开绝不触发 recovery; WAL 库按一致快照读, live 库无需停机 + # python3 sqlite3 3.53.1 + mode=ro:与 gateway 同版本,只读绝不触发 recovery,WAL 库一致快照读,live 库无需停机 + # 2026-09-09:弃用 /usr/bin/sqlite3 3.45.1(WAL-reset bug #69784,3.7.0~3.51.2 vulnerable)——两代 SQLite 交替操作是反复损坏元凶 # 大文件给足超时; 记录退出码供诊断 rc=0 if [ "$size" -gt 104857600 ]; then - timeout 120 sqlite3 -readonly "$db" "PRAGMA integrity_check;" > /tmp/dbmon-check-$$.tmp 2>&1 || rc=$? + timeout 120 python3 - "$db" <<'PY' > /tmp/dbmon-check-$$.tmp 2>&1 || rc=$? +import sqlite3, sys +c = sqlite3.connect(f"file:{sys.argv[1]}?mode=ro", uri=True, timeout=30) +try: + print(c.execute("PRAGMA integrity_check;").fetchone()[0]) +finally: + c.close() +PY else - timeout 20 sqlite3 -readonly "$db" "PRAGMA integrity_check;" > /tmp/dbmon-check-$$.tmp 2>&1 || rc=$? + timeout 20 python3 - "$db" <<'PY' > /tmp/dbmon-check-$$.tmp 2>&1 || rc=$? +import sqlite3, sys +c = sqlite3.connect(f"file:{sys.argv[1]}?mode=ro", uri=True, timeout=30) +try: + print(c.execute("PRAGMA integrity_check;").fetchone()[0]) +finally: + c.close() +PY fi result=$(head -1 /tmp/dbmon-check-$$.tmp) rm -f /tmp/dbmon-check-$$.tmp @@ -57,9 +72,11 @@ do fi done -# 3. 写入日志 +# 3. 写入日志(DB_ALERT 为空时计 0——2026-09-09 修:原 echo -e "" | wc -l 空也计 1,永远显示 db=1) TS=$(date '+%Y-%m-%d %H:%M:%S') -echo "[$TS] mem=${MEM_FREE}M swap=${SWAP_USED}/${SWAP_TOTAL}M db=$(echo -e "$DB_ALERT" | wc -l) issues" >> "$LOG" +db_issue_cnt=0 +[ -n "$DB_ALERT" ] && db_issue_cnt=$(printf '%b' "$DB_ALERT" | grep -c . || true) +echo "[$TS] mem=${MEM_FREE}M swap=${SWAP_USED}/${SWAP_TOTAL}M db=${db_issue_cnt} issues" >> "$LOG" # 4. 报警逻辑(异常时飞书,正常时静默) ALERT_TEXT="${MEM_ALERT}${DB_ALERT}"