89 lines
4.2 KiB
Python
89 lines
4.2 KiB
Python
|
|
#!/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✓ 检查完成")
|