🔄 卡若AI 同步 2026-02-22 11:32 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 8 个
This commit is contained in:
@@ -376,6 +376,7 @@ ss -tlnp | grep :端口号
|
||||
|
||||
| 脚本 | 功能 | 位置 |
|
||||
|------|------|------|
|
||||
| `腾讯云_TAT_word_ai_hair_is_phone_诊断修复.py` | word/ai_hair/is_phone 日志诊断、MODULE_NOT_FOUND 修复、重启(宝塔 API) | `./scripts/` |
|
||||
| `kr宝塔_node项目批量修复.py` | 批量启动 kr宝塔 Node 项目(服务器内执行,宝塔 API) | `./scripts/` |
|
||||
| `kr宝塔_宝塔API_修复502.py` | 修复 502(重启 Nginx + soul 相关 Node) | `./scripts/` |
|
||||
| `快速检查服务器.py` | 一键检查所有服务器状态 | `./脚本/` |
|
||||
|
||||
@@ -31,6 +31,7 @@ Error: Cannot find module '/www/wwwroot/自营/wzdj'
|
||||
| **tongzhi** | /www/wwwroot/自营/玩值/tongzhi | `cd /www/wwwroot/自营/玩值/tongzhi && node server.js` 或 `npm run start` | 同上 |
|
||||
| **is_phone** | /www/wwwroot/自营/kr/kr-phone | `cd /www/wwwroot/自营/kr/kr-phone && node server.js` 或 `npm run start` | 同上 |
|
||||
| **ai_hair** | /www/wwwroot/客户/ai_hair | 同上 | 同上 |
|
||||
| **word** | /www/wwwroot/自营/word 或 扩展/word | `cd 项目根目录 && npm run start` | Next.js,按实际路径 |
|
||||
| **AITOUFA** | /www/wwwroot/扩展/小工具/AITOUFA | `cd /www/wwwroot/扩展/小工具/AITOUFA && npm run start` | 参考 Skill §4.6 |
|
||||
| **zhiji** | /www/wwwroot/... | 同上 | 按实际结构 |
|
||||
| **ymao** | /www/wwwroot/扩展/ymao | 同上 | 同上 |
|
||||
|
||||
@@ -112,7 +112,17 @@ python3 "01_卡资(金)/金仓_存储备份/服务器管理/scripts/kr宝塔
|
||||
|
||||
**前置**:本机公网 IP 已加入 kr宝塔 **设置 → API 接口** 白名单。否则报「IP校验失败」。
|
||||
|
||||
### 3.3 502 修复(kr宝塔)
|
||||
### 3.3 word/ai_hair/is_phone 诊断修复(宝塔 API + TAT)
|
||||
|
||||
**脚本**:`scripts/腾讯云_TAT_word_ai_hair_is_phone_诊断修复.py`
|
||||
|
||||
**执行**:通过 TAT 在服务器内调用 127.0.0.1 宝塔 API,获取项目列表与路径,查看启动日志,遇 MODULE_NOT_FOUND 则 pnpm install,最后 restart_project。
|
||||
|
||||
```bash
|
||||
./scripts/.venv_tx/bin/python scripts/腾讯云_TAT_word_ai_hair_is_phone_诊断修复.py
|
||||
```
|
||||
|
||||
### 3.4 502 修复(kr宝塔)
|
||||
|
||||
**脚本**:`scripts/kr宝塔_宝塔API_修复502.py`
|
||||
|
||||
@@ -203,6 +213,7 @@ pm2 kill
|
||||
| 脚本 | 功能 | 执行位置 |
|
||||
|------|------|----------|
|
||||
| `scripts/kr宝塔_node项目批量修复.py` | 批量 stop→清端口→start Node 项目 | 服务器内 |
|
||||
| `scripts/腾讯云_TAT_word_ai_hair_is_phone_诊断修复.py` | word/ai_hair/is_phone 日志+MODULE_NOT_FOUND+restart(宝塔 API) | 本机(TAT) |
|
||||
| `scripts/kr宝塔_宝塔API_修复502.py` | 重启 Nginx + soul 相关 Node 项目 | 本机(API) |
|
||||
| `脚本/快速检查服务器.py` | 检查多台服务器状态 | 本机(API) |
|
||||
| `scripts/kr宝塔_腾讯云带宽与CPU近24h.py` | 腾讯云监控数据 | 本机 |
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
腾讯云 TAT:在 kr宝塔 上对 word、ai_hair、is_phone 执行:
|
||||
1. 通过宝塔 API get_project_list 获取项目配置与路径
|
||||
2. 查看启动日志(cat 常见日志路径)
|
||||
3. 如发现 MODULE_NOT_FOUND,在项目目录执行 pnpm install(或 npm install)
|
||||
4. 通过宝塔 API restart_project 重启
|
||||
|
||||
全程使用宝塔 API(127.0.0.1)进行操作,凭证见 00_账号与API索引.md
|
||||
"""
|
||||
import base64
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
|
||||
KR_INSTANCE_ID = "ins-aw0tnqjo"
|
||||
REGION = "ap-guangzhou"
|
||||
TARGET_NAMES = ["word", "ai_hair", "is_phone"]
|
||||
|
||||
# 已知项目路径(API 无 path 时的后备)
|
||||
PATH_MAP = {
|
||||
"word": "/www/wwwroot/自营/word",
|
||||
"ai_hair": "/www/wwwroot/客户/ai_hair",
|
||||
"is_phone": "/www/wwwroot/自营/kr/kr-phone",
|
||||
}
|
||||
|
||||
SHELL_SCRIPT = r'''#!/bin/bash
|
||||
set -e
|
||||
echo "=== kr宝塔 word/ai_hair/is_phone 诊断修复(宝塔 API)==="
|
||||
python3 - << 'PYEOF'
|
||||
import hashlib, json, os, subprocess, time, urllib.request, urllib.parse, ssl
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
PANEL, K = "https://127.0.0.1:9988", "qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT"
|
||||
PATH_MAP = {"word": "/www/wwwroot/自营/word", "ai_hair": "/www/wwwroot/客户/ai_hair", "is_phone": "/www/wwwroot/自营/kr/kr-phone"}
|
||||
def sign():
|
||||
t = int(time.time())
|
||||
s = str(t) + hashlib.md5(K.encode()).hexdigest()
|
||||
return {"request_time": t, "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())
|
||||
|
||||
items = post("/project/nodejs/get_project_list").get("data") or post("/project/nodejs/get_project_list").get("list") or []
|
||||
by_name = {str(it.get("name","")).lower(): it for it in items}
|
||||
|
||||
for nm in ["word", "ai_hair", "is_phone"]:
|
||||
print("\n--- %s ---" % nm)
|
||||
it = by_name.get(nm) or by_name.get(nm.replace("_",""))
|
||||
if not it:
|
||||
print(" 未找到项目,跳过")
|
||||
continue
|
||||
cfg = it.get("project_config") or {}
|
||||
if isinstance(cfg, str):
|
||||
try: cfg = json.loads(cfg)
|
||||
except: cfg = {}
|
||||
path = (it.get("path") or it.get("project_path") or cfg.get("path") or
|
||||
cfg.get("project_path") or cfg.get("projectDir") or PATH_MAP.get(nm))
|
||||
if not path or not os.path.isdir(path):
|
||||
path = PATH_MAP.get(nm)
|
||||
print(" 路径:", path)
|
||||
# 尝试查看日志
|
||||
log_paths = [
|
||||
"/www/server/nodejs/vhost/log/%s.log" % it.get("name", nm),
|
||||
"/www/server/nodejs/vhost/logs/%s.log" % it.get("name", nm),
|
||||
os.path.join(path or "", "logs", "out.log"),
|
||||
os.path.join(path or "", "log", "out.log"),
|
||||
]
|
||||
log_content = ""
|
||||
for lp in log_paths:
|
||||
try:
|
||||
with open(lp, "r", encoding="utf-8", errors="ignore") as f:
|
||||
log_content = f.read()[-4000:]
|
||||
print(" 日志(%s) 尾 200 字符:" % lp)
|
||||
print(" ", repr(log_content[-200:]))
|
||||
break
|
||||
except: pass
|
||||
has_mod = "MODULE_NOT_FOUND" in log_content or "Cannot find module" in log_content
|
||||
if has_mod and path and os.path.isdir(path):
|
||||
print(" 检测到 MODULE_NOT_FOUND,执行 pnpm install...")
|
||||
try:
|
||||
subprocess.check_output("cd '%s' && (pnpm install 2>/dev/null || npm install 2>/dev/null || true)" % path, shell=True, timeout=120)
|
||||
print(" 依赖安装完成")
|
||||
except Exception as e:
|
||||
print(" 依赖安装异常:", str(e)[:100])
|
||||
# 通过 API 重启
|
||||
pname = it.get("name") or it.get("project_name") or nm
|
||||
try:
|
||||
post("/project/nodejs/stop_project", {"project_name": pname})
|
||||
time.sleep(1)
|
||||
r = post("/project/nodejs/start_project", {"project_name": pname})
|
||||
ok = r.get("status") is True or "成功" in str(r.get("msg",""))
|
||||
print(" 重启:", "OK" if ok else "FAIL", r.get("msg","")[:80])
|
||||
except Exception as e:
|
||||
print(" 重启异常:", str(e)[:100])
|
||||
time.sleep(2)
|
||||
|
||||
print("\n=== 完成 ===")
|
||||
PYEOF
|
||||
'''
|
||||
|
||||
def _read_creds():
|
||||
d = os.path.dirname(os.path.abspath(__file__))
|
||||
for _ in range(6):
|
||||
root = d
|
||||
if os.path.isfile(os.path.join(root, "运营中枢", "工作台", "00_账号与API索引.md")):
|
||||
path = os.path.join(root, "运营中枢", "工作台", "00_账号与API索引.md")
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
text = f.read()
|
||||
sid = skey = None
|
||||
in_tx = False
|
||||
for line in text.splitlines():
|
||||
if "### 腾讯云" in line:
|
||||
in_tx = True
|
||||
continue
|
||||
if in_tx and line.strip().startswith("###"):
|
||||
break
|
||||
if not in_tx:
|
||||
continue
|
||||
m = re.search(r"\|\s*[^|]*(?:SecretId|密钥)[^|]*\|\s*`([^`]+)`", line, re.I)
|
||||
if m and m.group(1).strip().startswith("AKID"):
|
||||
sid = m.group(1).strip()
|
||||
m = re.search(r"\|\s*SecretKey\s*\|\s*`([^`]+)`", line, re.I)
|
||||
if m:
|
||||
skey = m.group(1).strip()
|
||||
return sid or None, skey or None
|
||||
d = os.path.dirname(d)
|
||||
return None, None
|
||||
|
||||
|
||||
def main():
|
||||
sid = os.environ.get("TENCENTCLOUD_SECRET_ID")
|
||||
skey = os.environ.get("TENCENTCLOUD_SECRET_KEY")
|
||||
if not sid or not skey:
|
||||
sid, skey = _read_creds()
|
||||
if not sid or not skey:
|
||||
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-tat")
|
||||
return 1
|
||||
|
||||
cred = credential.Credential(sid, skey)
|
||||
client = tat_client.TatClient(cred, REGION)
|
||||
req = models.RunCommandRequest()
|
||||
req.Content = base64.b64encode(SHELL_SCRIPT.encode()).decode()
|
||||
req.InstanceIds = [KR_INSTANCE_ID]
|
||||
req.CommandType = "SHELL"
|
||||
req.Timeout = 180
|
||||
req.CommandName = "WordAiHairIsPhone_DiagFix"
|
||||
resp = client.RunCommand(req)
|
||||
print("✅ TAT 已下发 InvocationId:", resp.InvocationId)
|
||||
print(" 目标项目: word, ai_hair, is_phone")
|
||||
print(" 等待 90s...")
|
||||
time.sleep(90)
|
||||
try:
|
||||
req2 = models.DescribeInvocationTasksRequest()
|
||||
f = models.Filter()
|
||||
f.Name = "invocation-id"
|
||||
f.Values = [resp.InvocationId]
|
||||
req2.Filters = [f]
|
||||
r2 = client.DescribeInvocationTasks(req2)
|
||||
for t in (r2.InvocationTaskSet or []):
|
||||
print(" 状态:", getattr(t, "TaskStatus", ""))
|
||||
out = getattr(t, "Output", None) or ""
|
||||
if out:
|
||||
print(" 输出:\n", out[:3500])
|
||||
except Exception as e:
|
||||
print(" 查询:", e)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -80,3 +80,4 @@
|
||||
| 2026-02-22 10:56:22 | 🔄 卡若AI 同步 2026-02-22 10:56 | 更新:卡土、总索引与入口、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 8 个 |
|
||||
| 2026-02-22 10:57:44 | 🔄 卡若AI 同步 2026-02-22 10:57 | 更新:卡土、总索引与入口、运营中枢工作台 | 排除 >20MB: 8 个 |
|
||||
| 2026-02-22 11:00:29 | 🔄 卡若AI 同步 2026-02-22 11:00 | 更新:卡土、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 8 个 |
|
||||
| 2026-02-22 11:07:02 | 🔄 卡若AI 同步 2026-02-22 11:07 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 8 个 |
|
||||
|
||||
@@ -83,3 +83,4 @@
|
||||
| 2026-02-22 10:56:22 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-22 10:56 | 更新:卡土、总索引与入口、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 8 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
| 2026-02-22 10:57:44 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-22 10:57 | 更新:卡土、总索引与入口、运营中枢工作台 | 排除 >20MB: 8 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
| 2026-02-22 11:00:29 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-22 11:00 | 更新:卡土、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 8 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
| 2026-02-22 11:07:02 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-22 11:07 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 8 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
|
||||
|
||||
Reference in New Issue
Block a user