import paramiko, sys sys.stdout.reconfigure(encoding='utf-8', errors='replace') c = paramiko.SSHClient(); c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) c.connect('101.79.17.164', username='root', password='1q2w3e!Q', timeout=15) sftp = c.open_sftp() # sso_provider가 create_access_token을 임포트하는지 확인 test = """ import sys sys.path.insert(0, '/opt/guardia/app') # core.auth에 create_access_token이 있는지 try: from core.auth import create_access_token print("create_access_token: OK") except ImportError as e: print(f"create_access_token: MISSING - {e}") # sso_provider에서만 임포트 테스트 import importlib, traceback for mod in ['kubernetes', 'sso_provider', 'predictive_ops', 'slack_connector', 'white_label']: try: m = importlib.import_module(f'routers.{mod}') # lifespan 이벤트 확인 has_startup = hasattr(m.router, 'on_startup') and m.router.on_startup print(f"{mod}: OK (startup={has_startup})") except Exception as e: print(f"{mod}: ERROR - {traceback.format_exc()[-200:]}") """ with sftp.open('/tmp/find_bad.py', 'w') as f: f.write(test) _, o, _ = c.exec_command( 'cd /opt/guardia/app && /opt/guardia/venv/bin/python3 /tmp/find_bad.py 2>&1; rm /tmp/find_bad.py', timeout=15) print(o.read().decode('utf-8','replace').strip()) # main.py의 lifespan 이벤트 확인 _, o2, _ = c.exec_command( "grep -n 'lifespan\\|on_startup\\|on_shutdown\\|@app.on' /opt/guardia/app/main.py | head -20", timeout=10) print('\n[main.py lifespan 이벤트]') print(o2.read().decode('utf-8','replace').strip()[:400]) sftp.close(); c.close()