🔄 卡若AI 同步 2026-03-09 05:51 | 更新:金仓、水桥平台对接、卡木、运营中枢工作台 | 排除 >20MB: 11 个
This commit is contained in:
@@ -51,7 +51,7 @@ kr宝塔: qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT
|
||||
|
||||
### 强制规则(每次执行必守)
|
||||
|
||||
1. **宝塔优先确认**:操作腾讯云服务器时,**先确认是否为宝塔服务器**。若是,**统一用宝塔 API + 宝塔 Node 管理,禁止使用 PM2**。所有 Node 项目启停、重启、状态查询一律通过宝塔面板 API(`/project/nodejs/start_project`、`stop_project`、`get_project_list`)。
|
||||
1. **宝塔优先确认**:操作腾讯云服务器时,**先确认是否为宝塔服务器**。若是,**彻底去除 PM2,一律使用宝塔原生 Node 管理器**。所有 Node 项目启停、重启、状态查询仅通过宝塔面板(网站 → Node 项目)及 API。脚本:`kr宝塔_彻底去除PM2_仅用宝塔Node_宝塔终端执行.sh`。
|
||||
2. **SSH 统一配置**:账号 **root**、密码 **Zhiqun1984**(Z 大写),端口 22022 或 22;或使用 id_ed25519 密钥。详见 `references/SSH登录方式与故障排查.md`。SSH 不通时用 TAT(腾讯云自动化助手)。
|
||||
3. **宝塔 443 优先**:宝塔服务器 443 不监听时,**优先**检查是否运行系统 Nginx 而非宝塔 Nginx;若是,先 `killall nginx` 后启动宝塔 Nginx。
|
||||
4. **经验沉淀**:每次涉及服务器/宝塔/部署的操作结束后,必须把经验写入 `02_卡人(水)/水溪_整理归档/经验库/待沉淀/`,防止同类问题重复出现。
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
**执行顺序(强制)**:宝塔 API 优先 → SSH → TAT。每次修改前**必须先检查目标项目及周边项目/应用**,确认不影响其他应用后再执行。详见 SKILL.md 强制规则 8、9。
|
||||
|
||||
**彻底去除 PM2,一律用宝塔 Node**:脚本 `kr宝塔_彻底去除PM2_仅用宝塔Node_宝塔终端执行.sh`,会停止并禁用 PM2、清理残留、结束高 CPU Node、修复 site.db、通过宝塔 Node 批量启动,缓解卡顿。
|
||||
|
||||
---
|
||||
|
||||
## 一、执行步骤
|
||||
|
||||
@@ -52,11 +52,11 @@ echo "=== 内存 TOP5 ===" && ps aux --sort=-%mem | head -6
|
||||
- **Nginx/应用日志**:看是否有大量请求或慢请求。
|
||||
- **带宽/流量**:宝塔面板「监控」或 `vnstat`(若已装)。
|
||||
|
||||
### 2.4 针对「服务器卡」的检查
|
||||
### 2.4 针对「服务器卡 / 负载高 / CPU 100%」的检查与处理
|
||||
|
||||
| 现象 | 检查命令/位置 | 处理思路 |
|
||||
|------------|--------------------------|------------------------------|
|
||||
| CPU 高 | `top` 或 `ps aux --sort=-%cpu` | 结束异常进程或优化程序 |
|
||||
| CPU 100% | `top` 或 `ps aux --sort=-%cpu` | 常见原因:PM2 重启循环、Node 进程异常。执行 `kr宝塔_负载CPU修复_宝塔终端执行.sh` 或 TAT `腾讯云_TAT_kr宝塔_负载CPU修复.py` |
|
||||
| 内存不足 | `free -m` | 关停非必要服务、加 swap 或升配 |
|
||||
| 磁盘满 | `df -h`、`du -sh /www/*` | 清日志、删临时文件、扩容 |
|
||||
| 磁盘 I/O 高| `iostat -x 1 3`(若已装)| 减少写操作、查大文件/日志 |
|
||||
@@ -64,25 +64,38 @@ echo "=== 内存 TOP5 ===" && ps aux --sort=-%mem | head -6
|
||||
|
||||
---
|
||||
|
||||
## 三、常见处理动作(登录后执行)
|
||||
## 三、负载与 CPU 100% 一键修复
|
||||
|
||||
**现象**:负载 77%、CPU 100%、磁盘 89%。常见原因:PM2 自动重启失败 Node 导致死循环、或多个 Node 进程抢占 CPU。
|
||||
|
||||
**执行顺序**:宝塔 API → SSH → TAT。
|
||||
|
||||
**方式一(推荐)**:在 **宝塔面板 → 终端** 打开 `01_卡资(金)/金仓_存储备份/服务器管理/scripts/kr宝塔_负载CPU修复_宝塔终端执行.sh`,全文复制粘贴到终端执行。
|
||||
|
||||
**方式二**:本机执行 TAT(需腾讯云凭证):
|
||||
```bash
|
||||
cd /Users/karuo/Documents/个人/卡若AI
|
||||
./01_卡资(金)/金仓_存储备份/服务器管理/scripts/.venv_tx/bin/python \
|
||||
"01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_kr宝塔_负载CPU修复.py"
|
||||
```
|
||||
|
||||
脚本会:PM2 清理 → 杀高 CPU Node 进程 → 停全部 Node → 修复 site.db → 批量启动。执行后刷新面板首页,负载与 CPU 应回落。
|
||||
|
||||
---
|
||||
|
||||
## 四、其他常见处理动作(登录后执行)
|
||||
|
||||
```bash
|
||||
# 清理系统日志(慎用,仅当磁盘紧张时)
|
||||
# find /var/log -name "*.log" -mtime +7 -delete
|
||||
|
||||
# 重载 Nginx
|
||||
nginx -s reload
|
||||
|
||||
# 查看宝塔/Node 相关进程
|
||||
ps aux | grep -E 'nginx|node|pm2'
|
||||
|
||||
# 若使用 PM2,查看列表
|
||||
pm2 list
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、宝塔 API 远程检查(需白名单)
|
||||
## 五、宝塔 API 远程检查(需白名单)
|
||||
|
||||
若本机 IP 已加入 kr宝塔 的「API 白名单」,可用卡若AI 脚本批量看 CPU/内存/磁盘:
|
||||
|
||||
@@ -94,7 +107,7 @@ python3 "/Users/karuo/Documents/个人/卡若AI/01_卡资(金)/金仓_存储
|
||||
|
||||
---
|
||||
|
||||
## 五、带宽使用情况(近期已查)
|
||||
## 六、带宽使用情况(近期已查)
|
||||
|
||||
kr宝塔 为腾讯云广州 CVM(实例 ID: ins-aw0tnqjo),带宽 5M。可用脚本查看近 24 小时监控:
|
||||
|
||||
@@ -112,7 +125,7 @@ kr宝塔 为腾讯云广州 CVM(实例 ID: ins-aw0tnqjo),带宽 5M。可
|
||||
|
||||
---
|
||||
|
||||
## 六、直接处理「带宽卡」——在宝塔面板终端执行
|
||||
## 七、直接处理「带宽卡」——在宝塔面板终端执行
|
||||
|
||||
以下整段复制到 **kr宝塔 宝塔面板 → 终端** 执行,用于排查并做基础限流。
|
||||
|
||||
|
||||
88
01_卡资(金)/金仓_存储备份/服务器管理/scripts/kr宝塔_全面检查与清理_宝塔终端执行.sh
Normal file
88
01_卡资(金)/金仓_存储备份/服务器管理/scripts/kr宝塔_全面检查与清理_宝塔终端执行.sh
Normal file
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# kr宝塔 全面检查:进程、病毒可疑项、卡顿,并清理
|
||||
# 执行:宝塔面板 → 终端 或 SSH
|
||||
|
||||
echo "========== 全面检查与清理 =========="
|
||||
|
||||
echo ""
|
||||
echo "【1】负载与 CPU TOP15"
|
||||
uptime
|
||||
ps aux --sort=-%cpu 2>/dev/null | head -16
|
||||
|
||||
echo ""
|
||||
echo "【2】可疑进程检测(矿机/病毒常见名)"
|
||||
for p in kdevtmpfsi kinsing xmrig miner; do
|
||||
found=$(ps aux | grep -E "$p" | grep -v grep 2>/dev/null)
|
||||
if [ -n "$found" ]; then
|
||||
echo " 可疑: $found"
|
||||
ps aux | grep -E "$p" | grep -v grep | awk '{print $2}' | xargs -r kill -9 2>/dev/null
|
||||
fi
|
||||
done
|
||||
echo " 检查完成"
|
||||
|
||||
echo ""
|
||||
echo "【3】crontab 与定时任务"
|
||||
crontab -l 2>/dev/null || echo " 无 crontab"
|
||||
ls -la /etc/cron.d/ 2>/dev/null | head -10
|
||||
grep -r "wget\|curl.*\|\|" /var/spool/cron/ /etc/cron.d/ 2>/dev/null | head -5 || true
|
||||
|
||||
echo ""
|
||||
echo "【4】/tmp 与 /var/tmp 可疑可执行文件"
|
||||
find /tmp /var/tmp -type f -executable 2>/dev/null | head -10 || true
|
||||
|
||||
echo ""
|
||||
echo "【5】PM2 与 Node 清理"
|
||||
pm2 kill 2>/dev/null || true
|
||||
systemctl stop pm2-root 2>/dev/null || true
|
||||
systemctl disable pm2-root 2>/dev/null || true
|
||||
pkill -9 -f "pm2" 2>/dev/null || true
|
||||
for pid in $(ps aux | awk '$3>80 && /node|npm|pnpm/ && !/grep/ {print $2}' 2>/dev/null); do
|
||||
kill -9 $pid 2>/dev/null
|
||||
done
|
||||
pkill -9 -f "node.*www/wwwroot" 2>/dev/null || true
|
||||
sleep 2
|
||||
|
||||
echo ""
|
||||
echo "【6】通过宝塔 Node 修复并启动"
|
||||
python3 << 'PY'
|
||||
import hashlib,json,os,sqlite3,time,urllib.request,urllib.parse,ssl
|
||||
ssl._create_default_https_context=ssl._create_unverified_context
|
||||
P,K="https://127.0.0.1:9988","qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT"
|
||||
def sg(): t=int(time.time()); return {"request_time":t,"request_token":hashlib.md5((str(t)+hashlib.md5(K.encode()).hexdigest()).encode()).hexdigest()}
|
||||
def post(p,d=None): pl=sg(); (pl.update(d) if d else None); r=urllib.request.Request(P+p,data=urllib.parse.urlencode(pl).encode()); return json.loads(urllib.request.urlopen(r,timeout=25).read().decode())
|
||||
PATH_FB={"玩值大屏":["/www/wwwroot/self/wanzhi/玩值大屏","/www/wwwroot/self/wanzhi/玩值"],"tongzhi":["/www/wwwroot/self/wanzhi/tongzhi","/www/wwwroot/self/wanzhi/tong"],"神射手":["/www/wwwroot/self/kr/kr-use","/www/wwwroot/self/kr/kr-users"],"AITOUFA":["/www/wwwroot/ext/tools/AITOUFA","/www/wwwroot/ext/tools/AITOL"]}
|
||||
items=post("/project/nodejs/get_project_list").get("data")or[]
|
||||
for it in items:
|
||||
if it.get("name"): post("/project/nodejs/stop_project",{"project_name":it["name"]}); time.sleep(0.3)
|
||||
time.sleep(3)
|
||||
db="/www/server/panel/data/db/site.db"
|
||||
if os.path.isfile(db):
|
||||
c=sqlite3.connect(db); cur=c.cursor(); cur.execute("SELECT id,name,path,project_config FROM sites WHERE project_type='Node'")
|
||||
for row in cur.fetchall():
|
||||
sid,name,path,cfg=row[0],row[1],row[2],row[3]or"{}"
|
||||
path=(path or"").strip(); cfg=json.loads(cfg) if cfg else {}
|
||||
proj=cfg.get("path")or cfg.get("project_path")or path
|
||||
if not proj or not os.path.isdir(proj):
|
||||
for p in PATH_FB.get(name,[]):
|
||||
if os.path.isdir(p): proj=p; break
|
||||
if proj and os.path.isdir(proj):
|
||||
cmd="cd %s && (pnpm start 2>/dev/null || npm run start)"%proj
|
||||
cfg["project_script"]=cfg["run_cmd"]=cmd; cfg["path"]=proj
|
||||
cur.execute("UPDATE sites SET path=?,project_config=? WHERE id=?",(proj,json.dumps(cfg,ensure_ascii=False),sid))
|
||||
c.commit(); c.close()
|
||||
for rnd in range(3):
|
||||
items=post("/project/nodejs/get_project_list").get("data")or[]
|
||||
to_start=[it for it in items if it.get("name") and not it.get("run")]
|
||||
if not to_start: break
|
||||
for it in to_start:
|
||||
if it.get("name"): post("/project/nodejs/start_project",{"project_name":it["name"]}); time.sleep(1.5)
|
||||
time.sleep(8)
|
||||
run=sum(1 for x in (post("/project/nodejs/get_project_list").get("data")or[]) if x.get("run"))
|
||||
print(" 运行 %d 个 Node" % run)
|
||||
PY
|
||||
|
||||
echo ""
|
||||
echo "【7】清理后负载"
|
||||
uptime
|
||||
echo ""
|
||||
echo "========== 完成 =========="
|
||||
30
01_卡资(金)/金仓_存储备份/服务器管理/scripts/kr宝塔_强制降负载_宝塔终端执行.sh
Normal file
30
01_卡资(金)/金仓_存储备份/服务器管理/scripts/kr宝塔_强制降负载_宝塔终端执行.sh
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
# 强制降负载:先停所有 Node/PM2,等负载回落后再手动启动
|
||||
echo "========== 强制降负载 =========="
|
||||
echo "【1】停 PM2"
|
||||
pm2 kill 2>/dev/null || true
|
||||
systemctl stop pm2-root 2>/dev/null || true
|
||||
systemctl disable pm2-root 2>/dev/null || true
|
||||
pkill -9 -f pm2 2>/dev/null || true
|
||||
echo "【2】结束全部 Node 进程"
|
||||
pkill -9 -f "node" 2>/dev/null || true
|
||||
pkill -9 -f "npm" 2>/dev/null || true
|
||||
pkill -9 -f "pnpm" 2>/dev/null || true
|
||||
pkill -9 -f "next-server" 2>/dev/null || true
|
||||
sleep 3
|
||||
echo "【3】通过宝塔 API 停止所有 Node 项目"
|
||||
python3 -c "
|
||||
import hashlib,json,time,urllib.request,urllib.parse,ssl
|
||||
ssl._create_default_https_context=ssl._create_unverified_context
|
||||
P,K='https://127.0.0.1:9988','qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT'
|
||||
def sg(): t=int(time.time()); return {'request_time':t,'request_token':hashlib.md5((str(t)+hashlib.md5(K.encode()).hexdigest()).encode()).hexdigest()}
|
||||
def post(p,d=None): pl=sg(); pl.update(d or {}); r=urllib.request.Request(P+p,data=urllib.parse.urlencode(pl).encode()); return json.loads(urllib.request.urlopen(r,timeout=20).read().decode())
|
||||
for it in post('/project/nodejs/get_project_list').get('data')or[]:
|
||||
n=it.get('name')
|
||||
if n: post('/project/nodejs/stop_project',{'project_name':n}); time.sleep(0.5)
|
||||
print('已停止全部')
|
||||
"
|
||||
sleep 5
|
||||
echo "【4】当前负载"
|
||||
uptime
|
||||
echo "========== 完成。负载应已下降。需启动的项目请到宝塔 Node 项目里手动点启动 =========="
|
||||
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
# kr宝塔 彻底去除 PM2,一律使用宝塔原生 Node 管理器
|
||||
# 执行:宝塔面板 → 终端 或 SSH,全文复制粘贴运行
|
||||
|
||||
echo "========== 彻底去除 PM2,仅用宝塔 Node =========="
|
||||
|
||||
echo "【1】停止并禁用 PM2"
|
||||
pm2 kill 2>/dev/null || true
|
||||
systemctl stop pm2-root 2>/dev/null || true
|
||||
systemctl disable pm2-root 2>/dev/null || true
|
||||
systemctl mask pm2-root 2>/dev/null || true
|
||||
rm -f /etc/systemd/system/pm2-root.service 2>/dev/null
|
||||
rm -f /usr/lib/systemd/system/pm2-root.service 2>/dev/null
|
||||
systemctl daemon-reload 2>/dev/null || true
|
||||
echo " PM2 已停止并禁用"
|
||||
|
||||
echo ""
|
||||
echo "【2】清理 PM2 残留进程与配置"
|
||||
pkill -9 -f "pm2" 2>/dev/null || true
|
||||
rm -rf /root/.pm2 2>/dev/null
|
||||
crontab -l 2>/dev/null | grep -v pm2 | crontab - 2>/dev/null || true
|
||||
echo " PM2 残留已清理"
|
||||
|
||||
echo ""
|
||||
echo "【3】结束高 CPU 与全部 Node 进程(解决卡顿)"
|
||||
for pid in $(ps aux | awk '$3>80 && /node|npm|pnpm/ && !/grep/ {print $2}' 2>/dev/null); do
|
||||
echo " kill 高CPU $pid"; kill -9 $pid 2>/dev/null
|
||||
done
|
||||
pkill -9 -f "node.*www/wwwroot" 2>/dev/null || true
|
||||
sleep 2
|
||||
echo " Node 进程已清理"
|
||||
|
||||
echo ""
|
||||
echo "【4】修复 site.db 启动命令并停止残留"
|
||||
python3 << 'FIX'
|
||||
import hashlib,json,os,re,sqlite3,subprocess,time,urllib.request,urllib.parse,ssl
|
||||
ssl._create_default_https_context=ssl._create_unverified_context
|
||||
P,K="https://127.0.0.1:9988","qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT"
|
||||
def sg(): t=int(time.time()); return {"request_time":t,"request_token":hashlib.md5((str(t)+hashlib.md5(K.encode()).hexdigest()).encode()).hexdigest()}
|
||||
def post(p,d=None): pl=sg(); (pl.update(d) if d else None); r=urllib.request.Request(P+p,data=urllib.parse.urlencode(pl).encode()); return json.loads(urllib.request.urlopen(r,timeout=25).read().decode())
|
||||
PATH_FB={"玩值大屏":["/www/wwwroot/self/wanzhi/玩值大屏","/www/wwwroot/self/wanzhi/玩值"],"tongzhi":["/www/wwwroot/self/wanzhi/tongzhi","/www/wwwroot/self/wanzhi/tong"],"神射手":["/www/wwwroot/self/kr/kr-use","/www/wwwroot/self/kr/kr-users"],"AITOUFA":["/www/wwwroot/ext/tools/AITOUFA","/www/wwwroot/ext/tools/AITOL"]}
|
||||
items=post("/project/nodejs/get_project_list").get("data")or post("/project/nodejs/get_project_list").get("list")or[]
|
||||
for it in items:
|
||||
n=it.get("name")
|
||||
if n:
|
||||
try: post("/project/nodejs/stop_project",{"project_name":n}); print(" 停:",n)
|
||||
except: pass
|
||||
time.sleep(0.4)
|
||||
time.sleep(3)
|
||||
db="/www/server/panel/data/db/site.db"
|
||||
if os.path.isfile(db):
|
||||
c=sqlite3.connect(db); cur=c.cursor(); cur.execute("SELECT id,name,path,project_config FROM sites WHERE project_type='Node'")
|
||||
fixed=0
|
||||
for row in cur.fetchall():
|
||||
sid,name,path,cfg=row[0],row[1],row[2],row[3]or"{}"
|
||||
path=(path or"").strip(); cfg=json.loads(cfg) if cfg else {}
|
||||
proj=cfg.get("path")or cfg.get("project_path")or path
|
||||
if not proj or not os.path.isdir(proj):
|
||||
for p in PATH_FB.get(name,[]):
|
||||
if os.path.isdir(p): proj=p; break
|
||||
if not proj or not os.path.isdir(proj): continue
|
||||
cmd="cd %s && (pnpm start 2>/dev/null || npm run start)"%proj
|
||||
cfg["project_script"]=cfg["run_cmd"]=cmd; cfg["path"]=proj
|
||||
cur.execute("UPDATE sites SET path=?,project_config=? WHERE id=?",(proj,json.dumps(cfg,ensure_ascii=False),sid)); fixed+=1
|
||||
c.commit(); c.close()
|
||||
print(" site.db 修复 %d 个" % fixed)
|
||||
FIX
|
||||
|
||||
echo ""
|
||||
echo "【5】通过宝塔 Node 管理器批量启动"
|
||||
python3 << 'PY'
|
||||
import hashlib,json,time,urllib.request,urllib.parse,ssl
|
||||
ssl._create_default_https_context=ssl._create_unverified_context
|
||||
P,K="https://127.0.0.1:9988","qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT"
|
||||
def sg(): t=int(time.time()); return {"request_time":t,"request_token":hashlib.md5((str(t)+hashlib.md5(K.encode()).hexdigest()).encode()).hexdigest()}
|
||||
def post(p,d=None): pl=sg(); (pl.update(d) if d else None); r=urllib.request.Request(P+p,data=urllib.parse.urlencode(pl).encode()); return json.loads(urllib.request.urlopen(r,timeout=25).read().decode())
|
||||
items=post("/project/nodejs/get_project_list").get("data")or post("/project/nodejs/get_project_list").get("list")or[]
|
||||
to_start=[it for it in items if it.get("name") and not it.get("run")]
|
||||
print(" 待启动 %d 个" % len(to_start))
|
||||
for it in to_start:
|
||||
n=it.get("name")
|
||||
if n:
|
||||
try: post("/project/nodejs/start_project",{"project_name":n}); print(" 启:",n)
|
||||
except: pass
|
||||
time.sleep(1.5)
|
||||
items2=post("/project/nodejs/get_project_list").get("data")or post("/project/nodejs/get_project_list").get("list")or[]
|
||||
run=sum(1 for x in items2 if x.get("run"))
|
||||
print(" 运行 %d / %d" % (run,len(items2)))
|
||||
PY
|
||||
|
||||
echo ""
|
||||
echo "【6】负载检查"
|
||||
uptime
|
||||
echo ""
|
||||
echo "========== 完成:PM2 已去除,仅用宝塔 Node 管理器,卡顿应缓解 =========="
|
||||
90
01_卡资(金)/金仓_存储备份/服务器管理/scripts/kr宝塔_负载CPU修复_宝塔终端执行.sh
Normal file
90
01_卡资(金)/金仓_存储备份/服务器管理/scripts/kr宝塔_负载CPU修复_宝塔终端执行.sh
Normal file
@@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
# kr宝塔 负载与 CPU 过载修复 - 宝塔面板「终端」或 SSH 执行
|
||||
# 1. PM2 清理 2. 杀高 CPU 进程 3. 停 Node 4. 修复 site.db 5. 批量启动
|
||||
|
||||
echo "========== kr宝塔 负载与 CPU 修复 =========="
|
||||
echo "【0】PM2 清理(防止重启循环导致 CPU 100%)"
|
||||
pm2 kill 2>/dev/null || true
|
||||
systemctl stop pm2-root 2>/dev/null || true
|
||||
systemctl disable pm2-root 2>/dev/null || true
|
||||
echo " PM2 已清理"
|
||||
echo ""
|
||||
echo "【1】负载与 CPU 诊断"
|
||||
uptime
|
||||
echo "--- CPU TOP10 ---"
|
||||
ps aux --sort=-%cpu | head -11
|
||||
echo ""
|
||||
echo "【2】结束高 CPU Node 进程(CPU>80%)"
|
||||
for pid in $(ps aux | awk '$3>80 && /node|npm|pnpm/ && !/grep/ {print $2}' 2>/dev/null); do
|
||||
echo " kill -9 $pid"; kill -9 $pid 2>/dev/null
|
||||
done
|
||||
echo "--- 清理异常 Node 进程 ---"
|
||||
pkill -9 -f "node.*www/wwwroot" 2>/dev/null || true
|
||||
sleep 3
|
||||
echo ""
|
||||
echo "【3】通过宝塔 API 停止全部 Node 并修复 site.db,然后批量启动"
|
||||
python3 << 'PY'
|
||||
import hashlib,json,os,re,sqlite3,subprocess,time,urllib.request,urllib.parse,ssl
|
||||
ssl._create_default_https_context=ssl._create_unverified_context
|
||||
P,K="https://127.0.0.1:9988","qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT"
|
||||
def sg(): t=int(time.time()); return {"request_time":t,"request_token":hashlib.md5((str(t)+hashlib.md5(K.encode()).hexdigest()).encode()).hexdigest()}
|
||||
def post(p,d=None): pl=sg(); (pl.update(d) if d else None); r=urllib.request.Request(P+p,data=urllib.parse.urlencode(pl).encode()); return json.loads(urllib.request.urlopen(r,timeout=25).read().decode())
|
||||
def pids(port):
|
||||
try: return {int(x) for x in re.findall(r"pid=(\d+)",subprocess.check_output("ss -tlnp 2>/dev/null | grep ':%s ' || true"%port,shell=True).decode())}
|
||||
except: return set()
|
||||
def ports(it):
|
||||
cfg=it.get("project_config") or {}
|
||||
if isinstance(cfg,str): cfg=json.loads(cfg) if cfg else {}
|
||||
p=[]; [p.append(int(cfg["port"])) if cfg.get("port") else None]
|
||||
p.extend(int(m) for m in re.findall(r"-p\s*(\d+)",str(cfg.get("project_script",""))))
|
||||
return sorted(set(p))
|
||||
PATH_FB={"玩值大屏":["/www/wwwroot/self/wanzhi/玩值大屏","/www/wwwroot/self/wanzhi/玩值"],"tongzhi":["/www/wwwroot/self/wanzhi/tongzhi","/www/wwwroot/self/wanzhi/tong"],"神射手":["/www/wwwroot/self/kr/kr-use","/www/wwwroot/self/kr/kr-users"],"AITOUFA":["/www/wwwroot/ext/tools/AITOUFA","/www/wwwroot/ext/tools/AITOL"]}
|
||||
items=post("/project/nodejs/get_project_list").get("data")or post("/project/nodejs/get_project_list").get("list")or[]
|
||||
print("停止 Node 项目")
|
||||
for it in items:
|
||||
n=it.get("name")
|
||||
if n:
|
||||
try:
|
||||
for port in ports(it): [subprocess.call("kill -9 %s 2>/dev/null"%pid,shell=True) for pid in pids(port)]
|
||||
pf="/www/server/nodejs/vhost/pids/%s.pid"%n
|
||||
if os.path.exists(pf): open(pf,"w").write("0")
|
||||
post("/project/nodejs/stop_project",{"project_name":n}); print(" 停:",n)
|
||||
except: pass
|
||||
time.sleep(0.4)
|
||||
time.sleep(4)
|
||||
print("\n修复 site.db")
|
||||
db="/www/server/panel/data/db/site.db"; fixed=0
|
||||
if os.path.isfile(db):
|
||||
c=sqlite3.connect(db); cur=c.cursor(); cur.execute("SELECT id,name,path,project_config FROM sites WHERE project_type='Node'")
|
||||
for row in cur.fetchall():
|
||||
sid,name,path,cfg=row[0],row[1],row[2],row[3]or"{}"
|
||||
path=(path or"").strip(); cfg=json.loads(cfg) if cfg else {}
|
||||
proj=cfg.get("path")or cfg.get("project_path")or path
|
||||
if not proj or not os.path.isdir(proj):
|
||||
for p in PATH_FB.get(name,[]):
|
||||
if os.path.isdir(p): proj=p; break
|
||||
if not proj or not os.path.isdir(proj): continue
|
||||
cmd="cd %s && (pnpm start 2>/dev/null || npm run start)"%proj
|
||||
cfg["project_script"]=cfg["run_cmd"]=cmd; cfg["path"]=proj
|
||||
cur.execute("UPDATE sites SET path=?,project_config=? WHERE id=?",(proj,json.dumps(cfg,ensure_ascii=False),sid)); fixed+=1
|
||||
print(" 修复:",name,"->",proj)
|
||||
c.commit(); c.close()
|
||||
print(" 共修复 %d 个"%fixed)
|
||||
print("\n批量启动 Node")
|
||||
for rnd in range(3):
|
||||
items=post("/project/nodejs/get_project_list").get("data")or post("/project/nodejs/get_project_list").get("list")or[]
|
||||
to_start=[it for it in items if it.get("name") and not it.get("run")]
|
||||
if not to_start: print(" 全部已运行"); break
|
||||
print(" 第%d轮: %d 个"%(rnd+1,len(to_start)))
|
||||
for it in to_start:
|
||||
n=it.get("name")
|
||||
if n:
|
||||
try: post("/project/nodejs/start_project",{"project_name":n}); print(" 启:",n)
|
||||
except: pass
|
||||
time.sleep(1.5)
|
||||
time.sleep(10)
|
||||
items2=post("/project/nodejs/get_project_list").get("data")or post("/project/nodejs/get_project_list").get("list")or[]
|
||||
run=sum(1 for x in items2 if x.get("run"))
|
||||
print("\n运行 %d / %d"%(run,len(items2)))
|
||||
print("========== 完成 ==========")
|
||||
PY
|
||||
53
01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_kr宝塔_彻底去除PM2.py
Normal file
53
01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_kr宝塔_彻底去除PM2.py
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""TAT:kr宝塔 彻底去除 PM2,仅用宝塔 Node 管理器"""
|
||||
import base64, os, re, sys, time
|
||||
KR_INSTANCE_ID, REGION = "ins-aw0tnqjo", "ap-guangzhou"
|
||||
SCRIPT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "kr宝塔_彻底去除PM2_仅用宝塔Node_宝塔终端执行.sh")
|
||||
|
||||
def _creds():
|
||||
d = os.path.dirname(os.path.abspath(__file__))
|
||||
for _ in range(6):
|
||||
p = os.path.join(d, "运营中枢", "工作台", "00_账号与API索引.md")
|
||||
if os.path.isfile(p):
|
||||
t = open(p).read()
|
||||
sid = skey = None
|
||||
for L in t.splitlines():
|
||||
m = re.search(r"SecretId[^|]*\|\s*`([^`]+)`", L, re.I)
|
||||
if m and "AKID" in m.group(1): sid = m.group(1).strip()
|
||||
m = re.search(r"SecretKey\s*\|\s*`([^`]+)`", L, re.I)
|
||||
if m: skey = m.group(1).strip()
|
||||
return sid or os.environ.get("TENCENTCLOUD_SECRET_ID"), skey or os.environ.get("TENCENTCLOUD_SECRET_KEY")
|
||||
d = os.path.dirname(d)
|
||||
return None, None
|
||||
|
||||
def main():
|
||||
sid, skey = _creds()
|
||||
if not sid or not skey: print("❌ 未配置凭证"); return 1
|
||||
with open(SCRIPT, "r", encoding="utf-8") as f:
|
||||
shell = f.read()
|
||||
from tencentcloud.common import credential
|
||||
from tencentcloud.tat.v20201028 import tat_client, models
|
||||
cred = credential.Credential(sid, skey)
|
||||
cli = tat_client.TatClient(cred, REGION)
|
||||
req = models.RunCommandRequest()
|
||||
req.Content = base64.b64encode(shell.encode("utf-8")).decode()
|
||||
req.InstanceIds = [KR_INSTANCE_ID]
|
||||
req.CommandType = "SHELL"
|
||||
req.Timeout = 120
|
||||
req.CommandName = "kr宝塔_彻底去除PM2"
|
||||
r = cli.RunCommand(req)
|
||||
print("✅ TAT 已下发")
|
||||
time.sleep(100)
|
||||
req2 = models.DescribeInvocationTasksRequest()
|
||||
f = models.Filter()
|
||||
f.Name, f.Values = "invocation-id", [r.InvocationId]
|
||||
req2.Filters = [f]
|
||||
for t in (cli.DescribeInvocationTasks(req2).InvocationTaskSet or []):
|
||||
tr = getattr(t, "TaskResult", None)
|
||||
if tr and getattr(tr, "Output", None):
|
||||
try: print(base64.b64decode(tr.Output).decode("utf-8", errors="replace"))
|
||||
except: pass
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__": sys.exit(main())
|
||||
65
01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_kr宝塔_负载CPU修复.py
Normal file
65
01_卡资(金)/金仓_存储备份/服务器管理/scripts/腾讯云_TAT_kr宝塔_负载CPU修复.py
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""TAT:kr宝塔 负载与 CPU 过载修复(PM2 清理 + 杀高 CPU Node + 停/修/启 Node)"""
|
||||
import base64, os, re, sys, time
|
||||
|
||||
KR_INSTANCE_ID, REGION = "ins-aw0tnqjo", "ap-guangzhou"
|
||||
SCRIPT_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "kr宝塔_负载CPU修复_宝塔终端执行.sh")
|
||||
|
||||
|
||||
def _creds():
|
||||
d = os.path.dirname(os.path.abspath(__file__))
|
||||
for _ in range(6):
|
||||
p = os.path.join(d, "运营中枢", "工作台", "00_账号与API索引.md")
|
||||
if os.path.isfile(p):
|
||||
t = open(p).read()
|
||||
sid = skey = None
|
||||
for L in t.splitlines():
|
||||
m = re.search(r"SecretId[^|]*\|\s*`([^`]+)`", L, re.I)
|
||||
if m and "AKID" in m.group(1): sid = m.group(1).strip()
|
||||
m = re.search(r"SecretKey\s*\|\s*`([^`]+)`", L, re.I)
|
||||
if m: skey = m.group(1).strip()
|
||||
return sid or os.environ.get("TENCENTCLOUD_SECRET_ID"), skey or os.environ.get("TENCENTCLOUD_SECRET_KEY")
|
||||
d = os.path.dirname(d)
|
||||
return None, None
|
||||
|
||||
|
||||
def main():
|
||||
sid, skey = _creds()
|
||||
if not sid or not skey:
|
||||
print("❌ 未配置凭证"); return 1
|
||||
with open(SCRIPT_PATH, "r", encoding="utf-8") as f:
|
||||
shell = f.read()
|
||||
from tencentcloud.common import credential
|
||||
from tencentcloud.tat.v20201028 import tat_client, models
|
||||
cred = credential.Credential(sid, skey)
|
||||
cli = tat_client.TatClient(cred, REGION)
|
||||
req = models.RunCommandRequest()
|
||||
req.Content = base64.b64encode(shell.encode("utf-8")).decode()
|
||||
req.InstanceIds = [KR_INSTANCE_ID]
|
||||
req.CommandType = "SHELL"
|
||||
req.Timeout = 120
|
||||
req.CommandName = "kr宝塔_负载CPU修复"
|
||||
r = cli.RunCommand(req)
|
||||
print("✅ TAT inv:", r.InvocationId)
|
||||
time.sleep(100)
|
||||
req2 = models.DescribeInvocationTasksRequest()
|
||||
f = models.Filter()
|
||||
f.Name, f.Values = "invocation-id", [r.InvocationId]
|
||||
req2.Filters = [f]
|
||||
r2 = cli.DescribeInvocationTasks(req2)
|
||||
for t in (r2.InvocationTaskSet or []):
|
||||
print("状态:", getattr(t, "TaskStatus", ""))
|
||||
tr = getattr(t, "TaskResult", None)
|
||||
if tr:
|
||||
out = getattr(tr, "Output", tr.__dict__.get("Output", ""))
|
||||
if out:
|
||||
try:
|
||||
print(base64.b64decode(out).decode("utf-8", errors="replace"))
|
||||
except Exception:
|
||||
print(str(out)[:2000])
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user