🔄 卡若AI 同步 2026-02-22 05:46 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个
This commit is contained in:
@@ -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`。
|
||||
@@ -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。
|
||||
|
||||
@@ -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 改为存客宝)
|
||||
|
||||
@@ -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`。
|
||||
- 若某项目因端口占用失败,脚本会自动尝试清理端口后重试;若仍失败,需在面板中手动检查该项目配置。
|
||||
|
||||
41
01_卡资(金)/金仓_存储备份/服务器管理/scripts/存客宝_SSH修复_宝塔终端执行.sh
Normal file
41
01_卡资(金)/金仓_存储备份/服务器管理/scripts/存客宝_SSH修复_宝塔终端执行.sh
Normal file
@@ -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"
|
||||
147
01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_Node批量修复.py
Normal file
147
01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_Node批量修复.py
Normal file
@@ -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())
|
||||
165
01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_解封SSH并批量启动Node.py
Normal file
165
01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_解封SSH并批量启动Node.py
Normal file
@@ -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())
|
||||
@@ -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 个 |
|
||||
|
||||
@@ -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) |
|
||||
|
||||
Reference in New Issue
Block a user