Files
diary-news/scripts/check_flow.py

89 lines
4.2 KiB
Python
Raw Normal View History

2026-06-11 17:24:46 +08:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""SSH 上服务器,快速检查:
1. .env 里的 AGNES_API_KEY 是否已配(不要再打印 key )
2. worker 进程是否在跑enrichment_loop 任务是否在跑
3. worker 日志最近 200 行是否出现 enrich_article / classify / commentary / format 等关键字
4. 翻译/enrich 各自最后处理时间
5. enrichment_loop 配置(LLM enable 状态)
"""
from __future__ import annotations
import sys
import os
import paramiko
HOST = os.environ.get("REMOTE_HOST", "207.57.129.228")
PORT = int(os.environ.get("REMOTE_PORT", "19717"))
USER = os.environ.get("REMOTE_USER", "root")
PASS = os.environ.get("REMOTE_PASS", "")
if not PASS:
print("ERROR: REMOTE_PASS not set", file=sys.stderr)
sys.exit(1)
def run(c, cmd, timeout=30, label=""):
if label: print(f"\n=== {label} ===")
print(f"$ {cmd}")
si, so, se = c.exec_command(cmd, timeout=timeout, get_pty=True)
out = so.read().decode(errors="replace")
err = se.read().decode(errors="replace")
rc = so.channel.recv_exit_status()
if out.strip(): print(out.rstrip())
if err.strip(): print(f"[stderr] {err.rstrip()}")
print(f"-> rc={rc}")
return out
print(f"{USER}@{HOST}:{PORT} ...")
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect(HOST, port=PORT, username=USER, password=PASS,
timeout=30, banner_timeout=30, auth_timeout=30,
allow_agent=False, look_for_keys=False)
print("✓ 连上\n")
# 1) AGNES_API_KEY 状态(只看长度,不打值)
run(c, "cd /srv/news && "
"grep -E '^AGNES_(API_KEY|BASE_URL|CHAT_MODEL|IMAGE_MODEL)=' .env | "
"awk -F= 'BEGIN{FS=\"=\"} { "
" if ($1==\"AGNES_API_KEY\") { k=$2; gsub(/\"/,\"\",k); "
" printf \" %s = (length=%d, prefix=%s***)\\n\", $1, length(k), substr(k,1,4) "
" } else { print \" \" $0 }"
"}'", label="1) .env 中 Agnes 相关配置")
# 2) worker 进程 + enrichment_loop 状态
run(c, "cd /srv/news && "
"echo '--- docker compose ps ---' && "
"docker compose ps worker && "
"echo '--- worker 容器内进程 ---' && "
"docker compose exec -T worker sh -c 'ps -ef | grep -E \"python|app.workers\" | grep -v grep' && "
"echo '--- enrichment 任务在 asyncio 队列 ---' && "
"docker compose exec -T worker sh -c 'cat /proc/1/status 2>/dev/null | head -3' ",
label="2) Worker 进程 + enrichment_loop 状态")
# 3) LLM enable 状态(admin_llm_settings 表)
run(c, "cd /srv/news && set -a && . ./.env && set +a && "
"docker compose exec -T postgres psql -U \"$POSTGRES_USER\" -d \"$POSTGRES_DB\" -t -A -F $'\\t' -c "
"\"SELECT key, value, updated_at FROM admin_llm_settings ORDER BY key;\" 2>&1 | head -10",
label="3) admin_llm_settings(LLM enable 状态)")
# 4) worker 日志最近 200 行
run(c, "cd /srv/news && "
"docker compose logs --no-color --tail=200 worker 2>&1 | tail -80",
label="4) worker 日志(最近 200 行)")
# 5) 翻译/enrich 各自最后活跃时间
run(c, "cd /srv/news && set -a && . ./.env && set +a && "
"docker compose exec -T postgres psql -U \"$POSTGRES_USER\" -d \"$POSTGRES_DB\" -t -A -F $'\\t' -c \""
"SELECT 'translated_last_5min=' || count(*) FROM articles WHERE translated_at > now() - interval '5 minute';"
"SELECT 'classified_last_5min=' || count(*) FROM articles WHERE classify_status='ok' AND translated_at > now() - interval '5 minute';"
"SELECT 'format_last_5min=' || count(*) FROM articles WHERE format_status='ok' AND translated_at > now() - interval '5 minute';"
"SELECT 'commentary_last_5min=' || count(*) FROM articles WHERE commentary_status='ok' AND translated_at > now() - interval '5 minute';"
"SELECT 'image_ai_last_5min=' || count(*) FROM articles WHERE image_ai_status='ok' AND translated_at > now() - interval '5 minute';"
"SELECT 'pending_classify=' || count(*) FROM articles WHERE classify_status IN ('pending','n/a') AND translation_status='ok';"
"SELECT 'pending_format=' || count(*) FROM articles WHERE format_status IN ('pending','n/a') AND translation_status='ok';"
"\"",
label="5) 最近 5 分钟 LLM 步骤活跃度")
c.close()
print("\n✓ 检查完成")