From f63045803ab25d23bfd613f66f90615fbf105ab9 Mon Sep 17 00:00:00 2001 From: karuo Date: Sun, 22 Feb 2026 05:46:08 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=84=20=E5=8D=A1=E8=8B=A5AI=20=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=202026-02-22=2005:46=20|=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=EF=BC=9A=E9=87=91=E4=BB=93=E3=80=81=E8=BF=90=E8=90=A5=E4=B8=AD?= =?UTF-8?q?=E6=9E=A2=E5=B7=A5=E4=BD=9C=E5=8F=B0=20|=20=E6=8E=92=E9=99=A4?= =?UTF-8?q?=20>20MB:=205=20=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../references/Node项目未启动_MODULE_NOT_FOUND修复指南.md | 70 ++++++++ .../服务器管理/references/SSH登录方式与故障排查.md | 14 +- .../服务器管理/references/存客宝_宝塔管理SKILL.md | 10 +- .../references/宝塔面板终端_Node批量启动指南.md | 2 +- .../服务器管理/scripts/存客宝_SSH修复_宝塔终端执行.sh | 41 +++++ .../服务器管理/scripts/腾讯云_TAT_Node批量修复.py | 147 ++++++++++++++++ .../scripts/腾讯云_TAT_解封SSH并批量启动Node.py | 165 ++++++++++++++++++ 运营中枢/工作台/gitea_push_log.md | 1 + 运营中枢/工作台/代码管理.md | 1 + 9 files changed, 447 insertions(+), 4 deletions(-) create mode 100644 01_卡资(金)/金仓_存储备份/服务器管理/references/Node项目未启动_MODULE_NOT_FOUND修复指南.md create mode 100644 01_卡资(金)/金仓_存储备份/服务器管理/scripts/存客宝_SSH修复_宝塔终端执行.sh create mode 100644 01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_Node批量修复.py create mode 100644 01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_解封SSH并批量启动Node.py diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/references/Node项目未启动_MODULE_NOT_FOUND修复指南.md b/01_卡资(金)/金仓_存储备份/服务器管理/references/Node项目未启动_MODULE_NOT_FOUND修复指南.md new file mode 100644 index 00000000..10b7242c --- /dev/null +++ b/01_卡资(金)/金仓_存储备份/服务器管理/references/Node项目未启动_MODULE_NOT_FOUND修复指南.md @@ -0,0 +1,70 @@ +# Node 项目未启动 · MODULE_NOT_FOUND 修复指南 + +> 针对 kr宝塔 43.139.27.93 多个 Node 项目「未启动」及「启动失败 MODULE_NOT_FOUND」的处理。 + +--- + +## 一、批量启动(先执行) + +在 **宝塔面板 → 终端** 执行 `references/宝塔面板终端_Node批量启动指南.md` 中的脚本,先尝试批量启动所有未运行项目。 + +--- + +## 二、MODULE_NOT_FOUND 原因 + +错误示例: +``` +Error: Cannot find module '/www/wwwroot/自营/玩值/玩值大屏' +Error: Cannot find module '/www/wwwroot/自营/wzdj' +``` + +**原因**:启动命令配置错误,把**目录路径**当成了入口文件。Node 无法把目录当模块执行。 + +--- + +## 三、按项目修复(宝塔 Node 项目 → 编辑) + +| 项目 | 根目录 | 建议启动命令 | 说明 | +|------|--------|--------------|------| +| **玩值大屏** | /www/wwwroot/自营/玩值/玩值大屏 | `cd /www/wwwroot/自营/玩值/玩值大屏 && node server.js` 或 `npm run start` | 先确认目录内有 server.js / package.json 的 scripts.start | +| **wzdj** | /www/wwwroot/自营/wzdj | `cd /www/wwwroot/自营/wzdj && node server.js` 或 `npm run start` | 同上 | +| **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 | 同上 | 同上 | +| **AITOUFA** | /www/wwwroot/扩展/小工具/AITOUFA | `cd /www/wwwroot/扩展/小工具/AITOUFA && npm run start` | 参考 Skill §4.6 | +| **zhiji** | /www/wwwroot/... | 同上 | 按实际结构 | +| **ymao** | /www/wwwroot/扩展/ymao | 同上 | 同上 | +| **zhaoping** | /www/wwwroot/客户/zhaoping | 同上 | 同上 | + +--- + +## 四、启动命令规则 + +1. **Next.js**:`cd 项目根目录 && npm run start` 或 `pnpm start`;若用 standalone:`node .next/standalone/server.js` +2. **Express / 普通 Node**:`cd 项目根目录 && node server.js` 或 `node index.js` +3. **禁止**:`node /www/wwwroot/xxx/项目名`(目录不能当入口) + +--- + +## 五、修复步骤(每个失败项目) + +1. 宝塔 → **网站** → **Node 项目** → 找到该项目 → **设置** 或 **编辑** +2. 找到「启动文件」或「启动命令」配置 +3. 改为:`cd /项目根目录 && node server.js` 或 `npm run start`(按项目类型选) +4. **Node 版本**:与 package.json 的 engines 一致(多数 v18.20.0,wzdj/zhiji 用 v20.18.0) +5. 保存后点击 **重启** + +--- + +## 六、先确认项目结构 + +在宝塔终端执行,确认各项目有入口文件: + +```bash +for d in /www/wwwroot/自营/玩值/玩值大屏 /www/wwwroot/自营/wzdj /www/wwwroot/自营/玩值/tongzhi /www/wwwroot/自营/kr/kr-phone; do + echo "=== $d ===" + ls -la "$d/" 2>/dev/null | grep -E "server\.js|index\.js|package\.json|\.next" || echo " (无常见入口)" +done +``` + +根据输出选择 `node server.js`、`node index.js` 或 `npm run start`。 diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/references/SSH登录方式与故障排查.md b/01_卡资(金)/金仓_存储备份/服务器管理/references/SSH登录方式与故障排查.md index 752dd6dd..defecddb 100644 --- a/01_卡资(金)/金仓_存储备份/服务器管理/references/SSH登录方式与故障排查.md +++ b/01_卡资(金)/金仓_存储备份/服务器管理/references/SSH登录方式与故障排查.md @@ -1,6 +1,7 @@ -# kr宝塔 SSH 登录方式与故障排查 +# 宝塔 SSH 登录方式与故障排查 > 当一种方式失败时,依次尝试其他方式。终极备选:**宝塔面板 → 终端**(无需 SSH)。 +> **存客宝 SSH 修复**:在存客宝宝塔终端执行 `scripts/存客宝_SSH修复_宝塔终端执行.sh` 内容。 --- @@ -132,3 +133,14 @@ fail2ban-client set ssh-iptables unbanip 你的公网IP ``` **一键脚本**:`scripts/宝塔_IP封禁解封与优化命令.sh`,在服务器上执行 `bash 脚本路径 你的公网IP` + +--- + +## 七、存客宝 SSH 修复(Permission denied 时) + +存客宝若密码/密钥均 Permission denied,需在**存客宝宝塔面板 → 终端**执行修复: + +1. 打开 https://42.194.245.239:9988 → 登录 ckb/zhiqun1984 → 左侧「终端」 +2. 复制 `scripts/存客宝_SSH修复_宝塔终端执行.sh` 的**全部内容**,粘贴到终端执行 + +脚本会:添加本机公钥、允许密码登录、`PermitRootLogin yes`、重置 root 密码为 Zhiqun1984、解封 IP 140.245.37.56、重载 sshd。执行完成后本机即可 SSH。 diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/references/存客宝_宝塔管理SKILL.md b/01_卡资(金)/金仓_存储备份/服务器管理/references/存客宝_宝塔管理SKILL.md index 91ba5854..18db7d3b 100644 --- a/01_卡资(金)/金仓_存储备份/服务器管理/references/存客宝_宝塔管理SKILL.md +++ b/01_卡资(金)/金仓_存储备份/服务器管理/references/存客宝_宝塔管理SKILL.md @@ -10,8 +10,8 @@ |------|-----| | IP | 42.194.245.239 | | SSH 端口 | 22022 | -| SSH 账号 | ckb | -| SSH 密码 | zhiqun1984 | +| SSH 账号 | root(面板账号 ckb 仅用于 Web) | +| SSH 密码 | Zhiqun1984(大写 Z,与 kr宝塔一致) | | 宝塔面板 | https://42.194.245.239:9988 | | 面板账号 | ckb | | 面板密码 | zhiqun1984 | @@ -19,6 +19,12 @@ --- +## SSH 修复(Permission denied 时) + +在宝塔面板 → 终端执行 `scripts/存客宝_SSH修复_宝塔终端执行.sh` 全部内容,修复后 root/Zhiqun1984 可登录。 + +--- + ## 快速操作 - **Node 项目**:若有 Node 项目,可参考 `references/宝塔Node项目管理_SKILL.md` 编写存客宝版批量修复脚本(PANEL、API_KEY 改为存客宝) diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/references/宝塔面板终端_Node批量启动指南.md b/01_卡资(金)/金仓_存储备份/服务器管理/references/宝塔面板终端_Node批量启动指南.md index 32bab8f6..99ddc826 100644 --- a/01_卡资(金)/金仓_存储备份/服务器管理/references/宝塔面板终端_Node批量启动指南.md +++ b/01_卡资(金)/金仓_存储备份/服务器管理/references/宝塔面板终端_Node批量启动指南.md @@ -124,5 +124,5 @@ python3 /tmp/kr_node_batch_fix.py ## 注意事项 -- **AITOUFA** 若仍报 `MODULE_NOT_FOUND`,需在宝塔 **Node 项目 → 编辑 AITOUFA** 中修正启动命令(例如改为 `npm start` 或正确入口文件)。 +- **MODULE_NOT_FOUND**:玩值大屏、wzdj、tongzhi 等若报此错,需在 **Node 项目 → 编辑** 中把启动命令改为 `cd /项目根目录 && node server.js` 或 `npm run start`,勿用目录路径当入口。详见 `references/Node项目未启动_MODULE_NOT_FOUND修复指南.md`。 - 若某项目因端口占用失败,脚本会自动尝试清理端口后重试;若仍失败,需在面板中手动检查该项目配置。 diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/scripts/存客宝_SSH修复_宝塔终端执行.sh b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/存客宝_SSH修复_宝塔终端执行.sh new file mode 100644 index 00000000..c8082503 --- /dev/null +++ b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/存客宝_SSH修复_宝塔终端执行.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# 存客宝 42.194.245.239 SSH 修复 · 在宝塔面板【终端】复制整段粘贴执行 +# 修复后:root 密码 Zhiqun1984,支持密钥与密码登录 + +PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBY/abEb3JpB/CP3jFqN9KqXspSGgAzHzYlsQzXLmPOt karuo@example.com" +MY_IP="140.245.37.56" + +echo "========== 存客宝 SSH 修复 ==========" + +# 1. 添加公钥 +mkdir -p /root/.ssh +chmod 700 /root/.ssh +grep -qF "$PUBKEY" /root/.ssh/authorized_keys 2>/dev/null || echo "$PUBKEY" >> /root/.ssh/authorized_keys +chmod 600 /root/.ssh/authorized_keys +echo "[1/5] 公钥已写入" + +# 2. 允许密码登录 +cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%s) +sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config +sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config +grep -q "^PasswordAuthentication" /etc/ssh/sshd_config || echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config +grep -q "^PermitRootLogin" /etc/ssh/sshd_config || echo "PermitRootLogin yes" >> /etc/ssh/sshd_config +echo "[2/5] sshd 已允许密码与 root 登录" + +# 3. 重置 root 密码 +echo "root:Zhiqun1984" | chpasswd +echo "[3/5] root 密码已设为 Zhiqun1984" + +# 4. 解封 IP +for j in sshd ssh-iptables; do + fail2ban-client set "$j" unbanip "$MY_IP" 2>/dev/null && echo " ✅ $j 已解封 $MY_IP" +done +echo "[4/5] IP 解封已执行" + +# 5. 重载 sshd +systemctl reload sshd 2>/dev/null || systemctl reload ssh 2>/dev/null || service sshd reload 2>/dev/null +echo "[5/5] sshd 已重载" +echo "" +echo "========== 完成 ==========" +echo "本机测试: sshpass -p 'Zhiqun1984' ssh -p 22022 -o PubkeyAuthentication=no root@42.194.245.239 'whoami'" +echo "或密钥: ssh -p 22022 -i Steam/id_ed25519 root@42.194.245.239" diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_Node批量修复.py b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_Node批量修复.py new file mode 100644 index 00000000..4116e2b0 --- /dev/null +++ b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_Node批量修复.py @@ -0,0 +1,147 @@ +#!/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: + name = it.get("name") + if not name or it.get("run") is True: continue + for port in ports(it): + for pid in pids(port): subprocess.call("kill -9 %s" % pid, shell=True) + pf = "/www/server/nodejs/vhost/pids/%s.pid" % name + if os.path.exists(pf): open(pf,"w").write("0") + 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")) + 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()) diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_解封SSH并批量启动Node.py b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_解封SSH并批量启动Node.py new file mode 100644 index 00000000..8fa6b57c --- /dev/null +++ b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_解封SSH并批量启动Node.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +腾讯云 TAT:在 kr宝塔 CVM 上解封 fail2ban SSH + 批量启动 Node(免 SSH) + +凭证:00_账号与API索引.md 或环境变量 TENCENTCLOUD_SECRET_ID / TENCENTCLOUD_SECRET_KEY +依赖:pip install tencentcloud-sdk-python-common tencentcloud-sdk-python-tat + +用法:python3 腾讯云_TAT_解封SSH并批量启动Node.py [本机IP] + 不传 IP 时默认 211.156.92.72 +""" +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 批量修复 Python 脚本(与 腾讯云_TAT_Node批量修复.py 一致) +NODE_FIX_B64 = base64.b64encode(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: + name = it.get("name") + if not name or it.get("run") is True: continue + for port in ports(it): + for pid in pids(port): subprocess.call("kill -9 %s" % pid, shell=True) + pf = "/www/server/nodejs/vhost/pids/%s.pid" % name + if os.path.exists(pf): open(pf,"w").write("0") + 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(name, "OK" if ok else "FAIL") + 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:", run_c, "STOP:", len(items2)-run_c) +'''.encode()).decode() + +def build_shell(unban_ip: str) -> str: + return f'''#!/bin/bash +set -e +echo "=== 1. 解封 fail2ban SSH (unbanip {unban_ip}) ===" +fail2ban-client set sshd unbanip {unban_ip} 2>/dev/null || echo " (fail2ban 未启用或已解封)" +echo "=== 2. Node 批量启动 ===" +echo "{NODE_FIX_B64}" | base64 -d | python3 - +echo "=== 完成 ===" +''' + +def main(): + unban_ip = (sys.argv[1:] or ["211.156.92.72"])[0] + + 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(环境变量或 00_账号与API索引.md)") + 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 + + shell = build_shell(unban_ip) + cred = credential.Credential(secret_id, secret_key) + client = tat_client.TatClient(cred, REGION) + req = models.RunCommandRequest() + req.Content = base64.b64encode(shell.encode()).decode() + req.InstanceIds = [KR_INSTANCE_ID] + req.CommandType = "SHELL" + req.Timeout = 180 + req.CommandName = "UnbanSSH_NodeBatchFix" + resp = client.RunCommand(req) + inv_id = resp.InvocationId + print("✅ 腾讯云 TAT 执行已下发") + print(" InvocationId:", inv_id) + print(" 解封 IP:", unban_ip) + print(" 等待 60s 后查询结果...") + time.sleep(60) + 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, "TaskStatus", "N/A")) + if hasattr(t, "Output") and t.Output: + print(" 输出:\n", t.Output or "") + except Exception as e: + print(" 查询异常:", e) + print("=" * 50) + return 0 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/运营中枢/工作台/gitea_push_log.md b/运营中枢/工作台/gitea_push_log.md index 1fee974a..87909746 100644 --- a/运营中枢/工作台/gitea_push_log.md +++ b/运营中枢/工作台/gitea_push_log.md @@ -49,3 +49,4 @@ | 2026-02-21 21:06:44 | 🔄 卡若AI 同步 2026-02-21 21:06 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 | | 2026-02-22 05:04:01 | 🔄 卡若AI 同步 2026-02-22 05:03 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 | | 2026-02-22 05:11:04 | 🔄 卡若AI 同步 2026-02-22 05:11 | 更新:金仓、水溪整理归档、运营中枢工作台 | 排除 >20MB: 5 个 | +| 2026-02-22 05:25:32 | 🔄 卡若AI 同步 2026-02-22 05:25 | 更新:金仓、卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 5 个 | diff --git a/运营中枢/工作台/代码管理.md b/运营中枢/工作台/代码管理.md index 97300365..67a4e699 100644 --- a/运营中枢/工作台/代码管理.md +++ b/运营中枢/工作台/代码管理.md @@ -52,3 +52,4 @@ | 2026-02-21 21:06:44 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-21 21:06 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | | 2026-02-22 05:04:01 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-22 05:03 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | | 2026-02-22 05:11:04 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-22 05:11 | 更新:金仓、水溪整理归档、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | +| 2026-02-22 05:25:32 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-22 05:25 | 更新:金仓、卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |