Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b2a0c237d7 | |||
| 3f47e63aef | |||
| ca108bb14e |
@@ -0,0 +1,43 @@
|
|||||||
|
name: Debug Lipsync SSH Diag
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
reason:
|
||||||
|
description: "debug reason"
|
||||||
|
required: false
|
||||||
|
default: "lipsync tts_processing stuck diagnosis"
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- debug/lipsync-ssh-diag
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
jobs:
|
||||||
|
ssh-diag:
|
||||||
|
name: SSH Staging Diagnostics
|
||||||
|
runs-on: runtime-builder
|
||||||
|
timeout-minutes: 15
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup SSH
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
STAGING_SSH_KEY: ${{ secrets.PREVIEW_SSH_KEY }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
which ssh || (apt-get update -qq && apt-get install -y -qq openssh-client)
|
||||||
|
mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
||||||
|
printf "%s" "$STAGING_SSH_KEY" > ~/.ssh/id_rsa
|
||||||
|
chmod 600 ~/.ssh/id_rsa
|
||||||
|
H=47.98.113.167; P=22222
|
||||||
|
ssh-keyscan -p $P -H $H >> ~/.ssh/known_hosts 2>/dev/null
|
||||||
|
ssh -p $P -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no root@$H "echo SSH_OK; hostname; date"
|
||||||
|
- name: Upload diag script and run
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
H=47.98.113.167; P=22222
|
||||||
|
scp -P $P -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no \
|
||||||
|
infra/scripts/server-lipsync-diag-v3.sh root@$H:/tmp/server-lipsync-diag-v3.sh
|
||||||
|
ssh -p $P -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no root@$H \
|
||||||
|
"bash /tmp/server-lipsync-diag-v3.sh 2>&1"
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Lipsync 深度诊断脚本 v2 - 重点排查broker连通/消息投递/DB状态
|
||||||
|
set +e
|
||||||
|
echo "#########################################################"
|
||||||
|
echo "# Lipsync 深度诊断 v2"
|
||||||
|
echo "# Date: $(date)"
|
||||||
|
echo "#########################################################"
|
||||||
|
|
||||||
|
W=$(docker ps --format '{{.Names}}' | grep -E 'worker' | head -1)
|
||||||
|
A=$(docker ps --format '{{.Names}}' | grep -E 'api' | grep -v 'web' | head -1)
|
||||||
|
R=$(docker ps --format '{{.Names}}' | grep -E 'redis' | head -1)
|
||||||
|
echo "Containers: W=$W A=$A R=$R"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 1. 容器 uptime + image tag ==="
|
||||||
|
for c in $W $A; do
|
||||||
|
echo "--- $c ---"
|
||||||
|
docker inspect "$c" --format 'Image={{.Config.Image}} Created={{.Created}} Started={{.State.StartedAt}} Restarts={{.RestartCount}}'
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 2. API+Worker 的 BROKER/REDIS 地址(隐藏密码) ==="
|
||||||
|
echo "--- API BROKER ---"
|
||||||
|
docker exec "$A" env | grep -iE "broker|celery_broker|redis_url|backend" | sed -E 's|(:)?//[^:]+:([^@]+)@|\1//***:***@|g'
|
||||||
|
echo "--- Worker BROKER ---"
|
||||||
|
docker exec "$W" env | grep -iE "broker|celery_broker|redis_url|backend" | sed -E 's|(:)?//[^:]+:([^@]+)@|\1//***:***@|g'
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 3. API容器 完整日志(近1000行) lipsync/TTS 相关 ==="
|
||||||
|
docker logs --tail=1000 "$A" 2>&1 | grep -iE "lipsync|tts_synth|tts_processing|celery.*task|apply_async|NotRegistered|OperationalError|ConnectionError|error.*submit|traceback|submitted" | tail -200
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 4. API 容器最近的 ERROR/Exception ==="
|
||||||
|
docker logs --tail=2000 "$A" 2>&1 | grep -iE "error|exception|traceback|critical" | grep -v "health\|/health" | tail -80
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 5. 测试1:在API容器内实际投递一条测试消息,看Worker是否消费 ==="
|
||||||
|
# 投递后立即检查队列和Worker日志
|
||||||
|
docker exec "$A" python - <<'PYEOF'
|
||||||
|
import sys, time, traceback
|
||||||
|
try:
|
||||||
|
from app.tasks.lipsync_tts import tts_synthesize_and_submit
|
||||||
|
from app.core.celery_app import celery_app as api_app
|
||||||
|
# 检查broker连接
|
||||||
|
conn = api_app.connection()
|
||||||
|
conn.ensure_connection(max_retries=2)
|
||||||
|
print("API celery broker connected:", conn.as_uri())
|
||||||
|
# 投递到celery默认队列
|
||||||
|
result = tts_synthesize_and_submit.apply_async(
|
||||||
|
args=["diag-test-job-id", "diag-user-id", "diag-voice", "diagnostic script text", 1.0, "neutral"],
|
||||||
|
queue="celery",
|
||||||
|
)
|
||||||
|
print("APPLY_ASYNC_OK task_id:", result.id)
|
||||||
|
print("task name:", result.name)
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
PYEOF
|
||||||
|
echo ""
|
||||||
|
sleep 3
|
||||||
|
echo "--- After apply_async: queue lengths ---"
|
||||||
|
for q in celery generation transcode; do
|
||||||
|
echo " $q: $(docker exec "$R" redis-cli LLEN $q)"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 6. 等8秒看Worker是否收到并消费 ==="
|
||||||
|
sleep 8
|
||||||
|
echo "--- Queue lengths after 8s ---"
|
||||||
|
for q in celery generation transcode; do
|
||||||
|
echo " $q: $(docker exec "$R" redis-cli LLEN $q)"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 7. Worker 日志最新记录(查看是否消费了测试消息) ==="
|
||||||
|
docker logs --since=30s "$W" 2>&1 | tail -60
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 8. Worker 内 Python 直接连接broker测试 ==="
|
||||||
|
docker exec "$W" python - <<'PYEOF'
|
||||||
|
import traceback
|
||||||
|
try:
|
||||||
|
from worker_app.celery_app import celery_app
|
||||||
|
conn = celery_app.connection()
|
||||||
|
conn.ensure_connection(max_retries=2)
|
||||||
|
print("Worker celery broker connected:", conn.as_uri())
|
||||||
|
insp = celery_app.control.inspect(timeout=3)
|
||||||
|
reg = insp.registered()
|
||||||
|
print("Registered from worker inspect (via broker):")
|
||||||
|
for node, tasks in (reg or {}).items():
|
||||||
|
has_l = any('lipsync' in t for t in tasks)
|
||||||
|
print(f" {node}: {len(tasks)} tasks, lipsync registered: {has_l}")
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
PYEOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 9. DB 查询最近10条lipsync_jobs状态 ==="
|
||||||
|
docker exec "$A" python - <<'PYEOF' 2>&1
|
||||||
|
import os, traceback
|
||||||
|
db_url = os.environ.get("DATABASE_URL","")
|
||||||
|
print("DATABASE_URL prefix:", (db_url[:50]+"...") if db_url else "(empty)")
|
||||||
|
try:
|
||||||
|
# 通过现有代码路径
|
||||||
|
from app.db.session import SessionLocal
|
||||||
|
from packages.adapters.sqlalchemy_impl.models import LipsyncJobModel
|
||||||
|
db = SessionLocal()
|
||||||
|
jobs = db.query(LipsyncJobModel).order_by(LipsyncJobModel.created_at.desc()).limit(10).all()
|
||||||
|
print(f"Found {len(jobs)} recent lipsync jobs:")
|
||||||
|
for j in jobs:
|
||||||
|
err = getattr(j, 'error_message', '') or ''
|
||||||
|
t_id = getattr(j, 'celery_task_id', '') or ''
|
||||||
|
print(f" id={j.id} status={j.status} mode={getattr(j,'mode','?')} "
|
||||||
|
f"created={j.created_at} celery_task_id={t_id} "
|
||||||
|
f"error={(err[:120]+'...') if len(err)>120 else err!r}")
|
||||||
|
db.close()
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
PYEOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 10. Worker 启动完整日志(前60行)==="
|
||||||
|
docker logs "$W" 2>&1 | head -60
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 11. lipsync_service.py 完整 create_job 相关段 ==="
|
||||||
|
docker exec "$A" sed -n '170,240p' /app/apps/api/app/services/lipsync_service.py 2>&1
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 12. celery_app task_routes / queue 配置(API侧)==="
|
||||||
|
docker exec "$A" python - <<'PYEOF'
|
||||||
|
from app.core.celery_app import celery_app
|
||||||
|
print("task_routes:", getattr(celery_app.conf, 'task_routes', None))
|
||||||
|
print("task_default_queue:", celery_app.conf.task_default_queue)
|
||||||
|
print("task_queues:", celery_app.conf.task_queues)
|
||||||
|
print("broker_url prefix:", celery_app.conf.broker_url[:60])
|
||||||
|
print("result_backend prefix:", str(celery_app.conf.result_backend)[:60] if celery_app.conf.result_backend else None)
|
||||||
|
PYEOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 13. Worker celery_app queue 配置 ==="
|
||||||
|
docker exec "$W" python - <<'PYEOF'
|
||||||
|
from worker_app.celery_app import celery_app
|
||||||
|
print("task_routes:", getattr(celery_app.conf, 'task_routes', None))
|
||||||
|
print("task_default_queue:", celery_app.conf.task_default_queue)
|
||||||
|
print("task_queues:", celery_app.conf.task_queues)
|
||||||
|
print("include/imports count:", len(celery_app.conf.imports))
|
||||||
|
PYEOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "#########################################################"
|
||||||
|
echo "# v2 诊断完成"
|
||||||
|
echo "#########################################################"
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Lipsync 诊断脚本 v3 - 用独立文件避免heredoc问题
|
||||||
|
set +e
|
||||||
|
echo "#########################################################"
|
||||||
|
echo "# Lipsync 诊断 v3"
|
||||||
|
echo "# Date: $(date)"
|
||||||
|
echo "#########################################################"
|
||||||
|
|
||||||
|
W=$(docker ps --format '{{.Names}}' | grep -E 'worker' | head -1)
|
||||||
|
A=$(docker ps --format '{{.Names}}' | grep -E 'api' | grep -v 'web' | head -1)
|
||||||
|
R=$(docker ps --format '{{.Names}}' | grep -E 'redis' | head -1)
|
||||||
|
NGINX=$(docker ps --format '{{.Names}}' | grep -iE 'nginx|web' | head -1)
|
||||||
|
echo "Containers:"
|
||||||
|
echo " W=$W"
|
||||||
|
echo " A=$A"
|
||||||
|
echo " R=$R"
|
||||||
|
echo " NGINX=$NGINX"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== A1. API 容器近 2000 行日志全部(看请求是否进来) ==="
|
||||||
|
docker logs --tail=2000 "$A" 2>&1 | tail -300
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== A2. API容器启动命令 & 网络 ==="
|
||||||
|
docker inspect "$A" --format 'Cmd={{.Config.Cmd}} Entrypoint={{.Config.Entrypoint}} NetworkMode={{.HostConfig.NetworkMode}}'
|
||||||
|
docker inspect "$A" --format '{{range .NetworkSettings.Networks}}{{.NetworkID}} {{.IPAddress}}{{end}}'
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== A3. Nginx 容器(如果有)日志 ==="
|
||||||
|
if [ -n "$NGINX" ]; then
|
||||||
|
docker logs --tail=200 "$NGINX" 2>&1 | grep -iE "lipsync|ai-avatar|error|upstream" | tail -100
|
||||||
|
echo "--- nginx config ---"
|
||||||
|
docker exec "$NGINX" cat /etc/nginx/conf.d/default.conf 2>&1 | head -80
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== B1. 写测试脚本到/tmp,再docker cp到容器里执行(避免heredoc问题) ==="
|
||||||
|
cat > /tmp/api_diag.py << 'PYEOF'
|
||||||
|
import sys, traceback, os
|
||||||
|
print("=== PYTHON OK in API container, cwd=", os.getcwd())
|
||||||
|
print("sys.path[0:3]:", sys.path[:3])
|
||||||
|
print("PYTHONPATH:", os.environ.get("PYTHONPATH",""))
|
||||||
|
try:
|
||||||
|
from app.tasks.lipsync_tts import tts_synthesize_and_submit
|
||||||
|
from app.core.celery_app import celery_app as api_app
|
||||||
|
print("api_app.main:", api_app.main)
|
||||||
|
print("api_app.conf.broker_url:", api_app.conf.broker_url)
|
||||||
|
print("task name:", tts_synthesize_and_submit.name)
|
||||||
|
print("task.app.main:", tts_synthesize_and_submit.app.main)
|
||||||
|
print("task in api_app.tasks:", tts_synthesize_and_submit.name in api_app.tasks)
|
||||||
|
print("api_app.conf.task_routes:", api_app.conf.task_routes)
|
||||||
|
print("api_app.conf.task_default_queue:", api_app.conf.task_default_queue)
|
||||||
|
# 测试broker连接
|
||||||
|
conn = api_app.connection()
|
||||||
|
conn.ensure_connection(max_retries=2)
|
||||||
|
print("broker connected OK:", conn.as_uri())
|
||||||
|
# 投递测试任务
|
||||||
|
result = tts_synthesize_and_submit.apply_async(
|
||||||
|
args=["diag-v3-job", "diag-user", "diag-voice", "hello v3 diag", 1.0, "neutral"],
|
||||||
|
queue="celery",
|
||||||
|
)
|
||||||
|
print("APPLY_ASYNC_OK id=", result.id, "name=", result.name, "queue=celery")
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
PYEOF
|
||||||
|
docker cp /tmp/api_diag.py "$A:/tmp/api_diag.py"
|
||||||
|
echo "--- docker exec python /tmp/api_diag.py in API ---"
|
||||||
|
docker exec "$A" python /tmp/api_diag.py 2>&1
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== B2. 投递3秒后查队列 ==="
|
||||||
|
sleep 3
|
||||||
|
for q in celery generation transcode; do
|
||||||
|
echo " queue $q: $(docker exec "$R" redis-cli LLEN $q)"
|
||||||
|
done
|
||||||
|
echo "--- peek celery ---"
|
||||||
|
docker exec "$R" redis-cli LRANGE celery 0 2 2>&1 | head -20
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== B3. 等10秒再查队列和Worker日志 ==="
|
||||||
|
sleep 7
|
||||||
|
for q in celery generation transcode; do
|
||||||
|
echo " queue $q: $(docker exec "$R" redis-cli LLEN $q)"
|
||||||
|
done
|
||||||
|
echo "--- Worker logs since 20s ago ---"
|
||||||
|
docker logs --since=20s "$W" 2>&1 | tail -50
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== C1. Worker侧执行诊断脚本 ==="
|
||||||
|
cat > /tmp/worker_diag.py << 'PYEOF'
|
||||||
|
import sys, os, traceback
|
||||||
|
print("=== PYTHON OK in Worker container ===")
|
||||||
|
try:
|
||||||
|
from worker_app.celery_app import celery_app
|
||||||
|
print("worker celery_app.main:", celery_app.main)
|
||||||
|
print("broker_url:", celery_app.conf.broker_url)
|
||||||
|
print("task_default_queue:", celery_app.conf.task_default_queue)
|
||||||
|
print("task_routes:", celery_app.conf.task_routes)
|
||||||
|
print("task_queues:", [(q.name, [b.name for b in q.bindings]) for q in (celery_app.conf.task_queues or [])])
|
||||||
|
# inspect via broker
|
||||||
|
insp = celery_app.control.inspect(timeout=3)
|
||||||
|
act = insp.active() or {}
|
||||||
|
reg = insp.registered() or {}
|
||||||
|
res = insp.reserved() or {}
|
||||||
|
for node, tasks in act.items():
|
||||||
|
print(f"ACTIVE on {node}: {len(tasks)} tasks")
|
||||||
|
for t in tasks:
|
||||||
|
print(f" - {t.get('name')} args={str(t.get('args',''))[:60]}")
|
||||||
|
for node, tasks in res.items():
|
||||||
|
print(f"RESERVED on {node}: {len(tasks)} tasks")
|
||||||
|
for t in tasks:
|
||||||
|
print(f" - {t.get('name')}")
|
||||||
|
print("registered lipsync count per node:")
|
||||||
|
for node, tasks in reg.items():
|
||||||
|
has = [t for t in tasks if 'lipsync' in t]
|
||||||
|
print(f" {node}: total={len(tasks)}, lipsync={has}")
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
PYEOF
|
||||||
|
docker cp /tmp/worker_diag.py "$W:/tmp/worker_diag.py"
|
||||||
|
docker exec "$W" python /tmp/worker_diag.py 2>&1
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== D1. DB最近20条lipsync jobs ==="
|
||||||
|
cat > /tmp/db_diag.py << 'PYEOF'
|
||||||
|
import sys, os, traceback
|
||||||
|
print("=== DB diag in API container ===")
|
||||||
|
print("DATABASE_URL prefix:", os.environ.get("DATABASE_URL","")[:60])
|
||||||
|
try:
|
||||||
|
from app.db.session import SessionLocal
|
||||||
|
from packages.adapters.sqlalchemy_impl.models import LipsyncJobModel
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
db = SessionLocal()
|
||||||
|
jobs = db.query(LipsyncJobModel).order_by(LipsyncJobModel.created_at.desc()).limit(20).all()
|
||||||
|
print(f"Found {len(jobs)} recent lipsync jobs:")
|
||||||
|
for j in jobs:
|
||||||
|
err = getattr(j, 'error_message', None) or ''
|
||||||
|
t_id = getattr(j, 'celery_task_id', None) or ''
|
||||||
|
c_at = j.created_at.isoformat() if j.created_at else '?'
|
||||||
|
print(f" id={j.id} status={j.status} mode={'tts' if (j.voice_id and not j.audio_url) else 'audio'} "
|
||||||
|
f"created={c_at} celery_task_id={t_id} err={(err[:100]+'...') if len(err)>100 else err!r}")
|
||||||
|
db.close()
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
PYEOF
|
||||||
|
docker cp /tmp/db_diag.py "$A:/tmp/db_diag.py"
|
||||||
|
docker exec "$A" python /tmp/db_diag.py 2>&1
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== D2. API容器监听端口 ==="
|
||||||
|
docker exec "$A" sh -c "ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null || cat /proc/net/tcp | head" 2>&1 | head -20
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== E1. 外部HTTPS健康检查 ==="
|
||||||
|
curl -sk --max-time 8 https://staging-api.xiaoxiajianji.com/api/v1/health 2>&1 | head -3
|
||||||
|
echo ""
|
||||||
|
curl -sk --max-time 8 https://staging-api.xiaoxiajianji.com/api/v1/lipsync/jobs 2>&1 | head -3
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "#########################################################"
|
||||||
|
echo "# v3 诊断完成"
|
||||||
|
echo "#########################################################"
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Lipsync staging 诊断脚本(在staging服务器本机执行)
|
||||||
|
set +e
|
||||||
|
echo "#########################################################"
|
||||||
|
echo "# Lipsync TTS async 诊断报告"
|
||||||
|
echo "# Host: $(hostname)"
|
||||||
|
echo "# Date: $(date)"
|
||||||
|
echo "#########################################################"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 1. docker ps (worker/api/redis) ==="
|
||||||
|
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.CreatedAt}}' | grep -E "worker|api|redis|nginx|NAMES"
|
||||||
|
|
||||||
|
W=$(docker ps --format '{{.Names}}' | grep -E 'worker' | head -1)
|
||||||
|
A=$(docker ps --format '{{.Names}}' | grep -E 'api' | grep -v 'web' | head -1)
|
||||||
|
R=$(docker ps --format '{{.Names}}' | grep -E 'redis' | head -1)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Worker container: $W ==="
|
||||||
|
echo "=== API container: $A ==="
|
||||||
|
echo "=== Redis container: $R ==="
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 2. Worker container image + created time ==="
|
||||||
|
docker inspect "$W" --format 'Image={{.Config.Image}} Created={{.Created}}'
|
||||||
|
docker inspect "$A" --format 'Image={{.Config.Image}} Created={{.Created}}'
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 3. Worker 启动日志:celery ready / registered / lipsync 相关 ==="
|
||||||
|
docker logs --tail=500 "$W" 2>&1 | grep -iE "lipsync|tts_synth|synthesize|celery@|ready|registered|register|error|traceback|import|critical|not registered|Consumer|mingle|tasks" | tail -120
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 4. celery -A inspect registered ==="
|
||||||
|
docker exec "$W" celery -A worker_app.celery_app inspect registered 2>&1 | tail -80
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 5. celery -A inspect active/reserved ==="
|
||||||
|
echo "--- active ---"
|
||||||
|
docker exec "$W" celery -A worker_app.celery_app inspect active 2>&1 | tail -30
|
||||||
|
echo "--- reserved ---"
|
||||||
|
docker exec "$W" celery -A worker_app.celery_app inspect reserved 2>&1 | tail -30
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 6. Worker 内 Python: import lipsync_tts task,看绑定 ==="
|
||||||
|
docker exec "$W" python -c "
|
||||||
|
from worker_app.celery_app import celery_app
|
||||||
|
print('worker celery_app.main:', celery_app.main)
|
||||||
|
print('worker celery_app.conf.imports:')
|
||||||
|
for m in celery_app.conf.imports:
|
||||||
|
print(' ', m)
|
||||||
|
import app.tasks.lipsync_tts as m
|
||||||
|
t = m.tts_synthesize_and_submit
|
||||||
|
print('task name:', t.name)
|
||||||
|
print('task.app.main:', t.app.main)
|
||||||
|
print('task.app is worker celery_app:', t.app is celery_app)
|
||||||
|
print('task.name in worker celery_app.tasks:', t.name in celery_app.tasks)
|
||||||
|
" 2>&1
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 7. API 容器日志:lipsync/celery/apply_async 相关错误 ==="
|
||||||
|
docker logs --tail=800 "$A" 2>&1 | grep -iE "lipsync|tts_|celery|apply_async|NotRegistered|traceback|error.*task" | tail -120
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 8. API 内 Python: import task 看绑定 + apply_async 试投递(不消费) ==="
|
||||||
|
docker exec "$A" python -c "
|
||||||
|
import traceback
|
||||||
|
try:
|
||||||
|
from app.tasks.lipsync_tts import tts_synthesize_and_submit
|
||||||
|
from app.core.celery_app import celery_app as api_app
|
||||||
|
print('api celery_app.main:', api_app.main)
|
||||||
|
print('task name:', tts_synthesize_and_submit.name)
|
||||||
|
print('task.app.main:', tts_synthesize_and_submit.app.main)
|
||||||
|
print('task.app is api_app:', tts_synthesize_and_submit.app is api_app)
|
||||||
|
print('task.name in api_app.tasks:', tts_synthesize_and_submit.name in api_app.tasks)
|
||||||
|
# 测试 send_task 是否能路由(不发送真任务)
|
||||||
|
print('api_app tasks includes lipsync_tts.synthesize_and_submit:', 'lipsync_tts.synthesize_and_submit' in api_app.tasks)
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
" 2>&1
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 9. Redis 队列长度 ==="
|
||||||
|
for q in celery generation transcode; do
|
||||||
|
len=$(docker exec "$R" redis-cli LLEN $q 2>&1)
|
||||||
|
echo " $q length: $len"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 10. Redis celery 队列 peek(最多5条) ==="
|
||||||
|
docker exec "$R" redis-cli LRANGE celery 0 4 2>&1 | head -40
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 11. Worker 关键文件内容校验 ==="
|
||||||
|
echo "--- worker_app/celery_app.py imports 段 ---"
|
||||||
|
docker exec "$W" grep -n "lipsync\|imports\s*=\|app.tasks\|apps.api" /app/apps/worker/worker_app/celery_app.py 2>&1
|
||||||
|
echo ""
|
||||||
|
echo "--- lipsync_tts.py 前20行(应该是 shared_task) ---"
|
||||||
|
docker exec "$W" head -25 /app/apps/api/app/tasks/lipsync_tts.py 2>&1
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 12. API lipsync_service.py apply_async 上下文 ==="
|
||||||
|
docker exec "$A" grep -n -B3 -A10 "apply_async\|tts_synthesize" /app/apps/api/app/services/lipsync_service.py 2>&1 | head -80
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== 13. Worker /app 目录结构(app/tasks) ==="
|
||||||
|
docker exec "$W" ls -la /app/apps/api/app/tasks/ 2>&1 | head -30
|
||||||
|
echo ""
|
||||||
|
echo "--- /app/apps/api/app/__init__.py? ---"
|
||||||
|
docker exec "$W" ls -la /app/apps/api/app/__init__.py /app/apps/api/app/core/__init__.py /app/apps/api/app/api/__init__.py 2>&1
|
||||||
|
echo ""
|
||||||
|
echo "--- PYTHONPATH inside worker ---"
|
||||||
|
docker exec "$W" env | grep PYTHONPATH
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "#########################################################"
|
||||||
|
echo "# 诊断完成"
|
||||||
|
echo "#########################################################"
|
||||||
Reference in New Issue
Block a user