Files
karuo-ai/01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_Node批量修复.py

155 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
腾讯云 TAT 在 kr宝塔 CVM 上执行 Node 批量修复(无需 SSH
凭证00_账号与API索引.md 或环境变量
依赖pip install tencentcloud-sdk-python-common tencentcloud-sdk-python-tat
"""
import base64
import os
import re
import sys
import time
KR_INSTANCE_ID = "ins-aw0tnqjo"
REGION = "ap-guangzhou"
def _find_karuo_ai_root():
d = os.path.dirname(os.path.abspath(__file__))
for _ in range(6):
if os.path.basename(d) == "卡若AI" or (os.path.isdir(os.path.join(d, "运营中枢")) and os.path.isdir(os.path.join(d, "01_卡资"))):
return d
d = os.path.dirname(d)
return None
def _read_creds():
root = _find_karuo_ai_root()
if not root:
return None, None
path = os.path.join(root, "运营中枢", "工作台", "00_账号与API索引.md")
if not os.path.isfile(path):
return None, None
with open(path, "r", encoding="utf-8") as f:
text = f.read()
secret_id = secret_key = None
in_tencent = False
for line in text.splitlines():
if "### 腾讯云" in line:
in_tencent = True
continue
if in_tencent and line.strip().startswith("###"):
break
if not in_tencent:
continue
m = re.search(r"\|\s*[^|]*(?:SecretId|密钥)[^|]*\|\s*`([^`]+)`", line, re.I)
if m:
val = m.group(1).strip()
if val.startswith("AKID"):
secret_id = val
m = re.search(r"\|\s*SecretKey\s*\|\s*`([^`]+)`", line, re.I)
if m:
secret_key = m.group(1).strip()
return secret_id or None, secret_key or None
# 在服务器上执行的 Node 批量修复脚本(内联)
NODE_FIX_SCRIPT = r'''
import hashlib, json, os, re, subprocess, time, urllib.request, urllib.parse, ssl
ssl._create_default_https_context = ssl._create_unverified_context
PANEL, API_KEY = "https://127.0.0.1:9988", "qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT"
def sign():
n = int(time.time())
s = str(n) + hashlib.md5(API_KEY.encode()).hexdigest()
return {"request_time": n, "request_token": hashlib.md5(s.encode()).hexdigest()}
def post(p, d=None):
pl = sign()
if d: pl.update(d)
r = urllib.request.Request(PANEL + p, data=urllib.parse.urlencode(pl).encode())
with urllib.request.urlopen(r, timeout=25) as resp:
return json.loads(resp.read().decode())
def pids(port):
try:
o = subprocess.check_output("ss -tlnp | grep ':%s ' || true" % port, shell=True, universal_newlines=True)
return sorted({int(x) for x in re.findall(r"pid=(\d+)", o)})
except: return []
def ports(it):
cfg = it.get("project_config") or {}
ps = []
if cfg.get("port"): ps.append(int(cfg["port"]))
for m in re.findall(r"-p\s*(\d+)", str(cfg.get("project_script",""))): ps.append(int(m))
return sorted(set(ps))
items = post("/project/nodejs/get_project_list").get("data") or post("/project/nodejs/get_project_list").get("list") or []
for it in items:
try:
name = it.get("name")
if not name or it.get("run") is True: continue
for port in ports(it):
for pid in pids(port):
try: subprocess.call("kill -9 %s" % pid, shell=True)
except: pass
pf = "/www/server/nodejs/vhost/pids/%s.pid" % name
if os.path.exists(pf):
try: open(pf,"w").write("0")
except: pass
post("/project/nodejs/stop_project", {"project_name": name})
r = post("/project/nodejs/start_project", {"project_name": name})
ok = r.get("status") is True or "成功" in str(r.get("msg",""))
print("%s: %s" % (name, "OK" if ok else "FAIL"))
except Exception as e:
print("%s: ERR %s" % (name, str(e)[:80]))
time.sleep(1)
time.sleep(4)
items2 = post("/project/nodejs/get_project_list").get("data") or []
run_c = sum(1 for x in items2 if x.get("run"))
print("RUN:%d STOP:%d" % (run_c, len(items2)-run_c))
'''
def main():
secret_id = os.environ.get("TENCENTCLOUD_SECRET_ID")
secret_key = os.environ.get("TENCENTCLOUD_SECRET_KEY")
if not secret_id or not secret_key:
sid, skey = _read_creds()
secret_id = secret_id or sid
secret_key = secret_key or skey
if not secret_id or not secret_key:
print("❌ 未配置腾讯云 SecretId/SecretKey")
return 1
try:
from tencentcloud.common import credential
from tencentcloud.tat.v20201028 import tat_client, models
except ImportError:
print("请安装: pip install tencentcloud-sdk-python-common tencentcloud-sdk-python-tat")
return 1
cred = credential.Credential(secret_id, secret_key)
client = tat_client.TatClient(cred, REGION)
req = models.RunCommandRequest()
req.Content = base64.b64encode(NODE_FIX_SCRIPT.encode()).decode()
req.InstanceIds = [KR_INSTANCE_ID]
req.CommandType = "SHELL"
req.Timeout = 120
req.CommandName = "NodeBatchFix"
resp = client.RunCommand(req)
inv_id = resp.InvocationId
print("✅ TAT 执行已下发 InvocationId:", inv_id)
print(" 等待 30s 后查询结果...")
time.sleep(30)
# 查询执行结果Filter 方式)
try:
req2 = models.DescribeInvocationTasksRequest()
f = models.Filter()
f.Name = "invocation-id"
f.Values = [inv_id]
req2.Filters = [f]
resp2 = client.DescribeInvocationTasks(req2)
for t in (resp2.InvocationTaskSet or []):
print(" 任务:", getattr(t, "InvocationTaskId", t), "状态:", getattr(t, "TaskStatus", "N/A"))
if hasattr(t, "Output") and t.Output:
print(" 输出:", (t.Output or "")[:800])
except Exception as e:
print(" 查询结果异常:", e)
print("=" * 50)
return 0
if __name__ == "__main__":
sys.exit(main())