diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/scripts/kr宝塔_node项目批量修复.py b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/kr宝塔_node项目批量修复.py new file mode 100644 index 00000000..8d942e8b --- /dev/null +++ b/01_卡资(金)/金仓_存储备份/服务器管理/scripts/kr宝塔_node项目批量修复.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +kr宝塔:仅使用宝塔 Node 项目接口,批量修复 run=False 项目。 + +策略: +1) 拉取 Node 项目列表 +2) 对 run=False 项目: + - stop_project + - 杀掉其目标端口上的冲突进程(EADDRINUSE) + - 清理 pid 文件 + - start_project +3) 回查 run/listen_ok +""" + +import hashlib +import json +import os +import re +import ssl +import subprocess +import time +import urllib.parse +import urllib.request + +ssl._create_default_https_context = ssl._create_unverified_context + +PANEL = "https://127.0.0.1:9988" +API_KEY = "qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT" + + +def sign(): + now = int(time.time()) + s = str(now) + hashlib.md5(API_KEY.encode("utf-8")).hexdigest() + return { + "request_time": now, + "request_token": hashlib.md5(s.encode("utf-8")).hexdigest(), + } + + +def post(path, data=None, timeout=25): + payload = sign() + if data: + payload.update(data) + req = urllib.request.Request( + PANEL + path, data=urllib.parse.urlencode(payload).encode("utf-8") + ) + with urllib.request.urlopen(req, timeout=timeout) as resp: + txt = resp.read().decode("utf-8", errors="ignore") + try: + return json.loads(txt) + except Exception: + return {"raw": txt[:800]} + + +def fetch_list(): + result = post("/project/nodejs/get_project_list") + items = result.get("data") if isinstance(result, dict) else None + if not isinstance(items, list): + items = result.get("list") if isinstance(result, dict) else None + if not isinstance(items, list): + raise RuntimeError("获取 Node 项目列表失败: %s" % str(result)[:300]) + return items + + +def pids_on_port(port): + cmd = "ss -tlnp | grep ':%s ' || true" % port + out = subprocess.check_output(cmd, shell=True, universal_newlines=True) + return sorted({int(x) for x in re.findall(r"pid=(\d+)", out)}) + + +def collect_ports(item): + ports = [] + cfg = item.get("project_config") or {} + p = cfg.get("port") + if p: + try: + ports.append(int(p)) + except Exception: + pass + script = str(cfg.get("project_script") or "") + for m in re.findall(r"-p\s*(\d+)", script): + try: + ports.append(int(m)) + except Exception: + pass + return sorted(set(ports)) + + +def main(): + items = fetch_list() + operations = [] + + for it in items: + name = it.get("name") + if not name or it.get("run") is True: + continue + + ports = collect_ports(it) + post("/project/nodejs/stop_project", {"project_name": name}) + + killed = [] + for port in ports: + for pid in pids_on_port(port): + subprocess.call("kill -9 %s" % pid, shell=True) + killed.append((port, pid)) + + pid_file = "/www/server/nodejs/vhost/pids/%s.pid" % name + try: + if os.path.exists(pid_file): + with open(pid_file, "w", encoding="utf-8") as f: + f.write("0") + except Exception: + pass + + r = post("/project/nodejs/start_project", {"project_name": name}) + ok = isinstance(r, dict) and ( + r.get("status") is True or "成功" in str(r.get("msg", "")) + ) + msg = str(r.get("msg", r) if isinstance(r, dict) else r)[:220] + operations.append((name, ports, killed, ok, msg)) + time.sleep(1) + + print("=== 操作结果 ===") + for row in operations: + print(row) + + time.sleep(4) + items2 = fetch_list() + run_cnt = sum(1 for x in items2 if x.get("run") is True) + stop_cnt = sum(1 for x in items2 if x.get("run") is not True) + + print("\n=== 回查(run/listen_ok) ===") + for x in items2: + print((x.get("name"), x.get("run"), x.get("listen_ok"))) + print("\nSUMMARY", run_cnt, stop_cnt) + + +if __name__ == "__main__": + main() diff --git a/02_卡人(水)/水桥_平台对接/Soul文章上传/SKILL.md b/02_卡人(水)/水桥_平台对接/Soul文章上传/SKILL.md new file mode 100644 index 00000000..5b14fcc9 --- /dev/null +++ b/02_卡人(水)/水桥_平台对接/Soul文章上传/SKILL.md @@ -0,0 +1,147 @@ +--- +name: Soul文章上传 +description: 《一场soul的创业实验》第9章文章写入小程序后端,写好即传,id 已存在则更新不重复 +triggers: Soul文章上传、Soul派对文章、第9章上传、soul 上传、写soul文章 +owner: 水桥 +group: 水 +version: "1.0" +updated: "2026-02-20" +--- + +# Soul文章上传 Skill + +> 写好文章直接上传到 Soul 小程序,id 已存在则更新,保持不重复。 —— 水桥 + +--- + +## 触发条件 + +用户说以下关键词时自动激活: +- Soul文章上传、Soul派对文章、第9章上传 +- soul 上传、写soul文章、上传到soul +- 写好文章上传、文章写好了上传 + +--- + +## 核心配置 + +| 项目 | 路径/值 | +|:---|:---| +| Soul 项目根目录 | `/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验` | +| 第9章文章目录 | `/Users/karuo/Documents/个人/2、我写的书/《一场soul的创业实验》/第四篇|真实的赚钱/第9章|我在Soul上亲访的赚钱案例/` | +| 上传脚本 | `一场soul的创业实验/scripts/upload_soul_article.sh` | +| 底层工具 | `一场soul的创业实验/content_upload.py` | +| 第9章固定参数 | part-4(第四篇|真实的赚钱), chapter-9(第9章|我在Soul上亲访的赚钱案例) | + +--- + +## 执行步骤 + +### 1. 写好文章 + +文章放在第9章目录,文件名格式:`9.xx 第X场|主题.md` + +示例:`9.18 第105场|创业社群、直播带货与程序员.md` + +### 2. 执行上传 + +```bash +/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/scripts/upload_soul_article.sh "/Users/karuo/Documents/个人/2、我写的书/《一场soul的创业实验》/第四篇|真实的赚钱/第9章|我在Soul上亲访的赚钱案例/9.xx 第X场|标题.md" +``` + +### 3. 一键命令(替换为实际文件路径) + +```bash +cd /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验 +./scripts/upload_soul_article.sh "<文章完整路径>" +``` + +--- + +## 输出说明 + +| 返回 | 含义 | +|:---|:---| +| `"action": "创建"` | 新章节已写入 | +| `"action": "更新"` | 同 id 已存在,内容已更新(不重复) | + +--- + +## 配套脚本 + +| 脚本 | 用途 | +|:---|:---| +| `content_upload.py` | 直连数据库,创建/更新章节(依赖 pymysql) | +| `scripts/upload_soul_article.sh` | 从文件名提取 id、title,调用 content_upload | + +### 手动调用 content_upload(高级) + +```bash +cd /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验 + +# 上传指定文章 +python3 content_upload.py --id 9.18 --title "9.18 第105场|主题" \ + --content-file "<文章路径>" --part part-4 --chapter chapter-9 --price 1.0 + +# 查看篇章结构 +python3 content_upload.py --list-structure + +# 列出所有章节 +python3 content_upload.py --list-chapters +``` + +--- + +## API 接口(备用) + +管理后台 API(需 Token): + +| 接口 | 说明 | +|:---|:---| +| `POST /api/admin` | 登录获取 Token,Body: `{"username":"admin","password":"admin123"}` | +| `POST /api/db/book` | 创建/更新章节,Header: `Authorization: Bearer {token}` | + +正式环境:`https://soulapi.quwanzhi.com` +开发环境:`https://souldev.quwanzhi.com` + +--- + +## 经验与注意 + +### 1. 不重复机制 + +- 以 `id`(如 9.18)为唯一键 +- id 已存在 → **更新**;不存在 → **创建** +- 同一场次多次上传不会重复,只会覆盖 + +### 2. 文件名规范 + +- 格式:`9.xx 第X场|主题.md` +- id 从文件名提取,必须形如 `9.18`(章.节) + +### 3. 环境依赖 + +```bash +pip3 install pymysql +``` + +### 4. 与书的对应关系 + +- 书稿目录:`个人/2、我写的书/《一场soul的创业实验》/第四篇|真实的赚钱/第9章|...` +- 小程序内容来源:腾讯云 MySQL `soul_miniprogram.chapters` +- content_upload 直连数据库,与 API 共用同一数据源 + +### 5. 工作流建议 + +1. 根据 Soul 派对 TXT 写好文章(按书格式:一句一行、金句开头、日期、`---` 分段) +2. 保存为 `9.xx 第X场|主题.md` 到第9章目录 +3. 执行 `upload_soul_article.sh "<文章路径>"` +4. 检查返回为「创建」或「更新」即完成 + +--- + +## 版本记录 + +| 版本 | 日期 | 说明 | +|:---|:---|:---| +| 1.0 | 2026-02-20 | 初版,从 Soul 项目抽取为独立技能 | diff --git a/SKILL_REGISTRY.md b/SKILL_REGISTRY.md index f61a6b8e..e096dc09 100644 --- a/SKILL_REGISTRY.md +++ b/SKILL_REGISTRY.md @@ -1,7 +1,7 @@ # 卡若AI 技能注册表(Skill Registry) > **一张表查所有技能**。任何 AI 拿到这张表,就能按关键词找到对应技能的 SKILL.md 路径并执行。 -> 46 技能 | 14 成员 | 5 负责人 +> 47 技能 | 14 成员 | 5 负责人 > 版本:5.0 | 更新:2026-02-16 --- @@ -52,6 +52,7 @@ | W07 | 飞书管理 | 水桥 | 飞书日志、写入飞书 | `02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md` | 飞书日志/文档自动化 | | W08 | 智能纪要 | 水桥 | 会议纪要、产研纪要、**飞书妙记、飞书链接、妙记下载、第几场、指定场次、批量下载妙记、cunkebao.feishu.cn、meetings.feishu.cn/minutes** | `02_卡人(水)/水桥_平台对接/智能纪要/SKILL.md` | 会议录音转结构化纪要;飞书妙记识别与下载(单条/批量),完毕用复盘格式回复 | | W09 | 小程序管理 | 水桥 | 小程序、微信小程序 | `02_卡人(水)/水桥_平台对接/小程序管理/SKILL.md` | 微信小程序发布与维护 | +| W10 | Soul文章上传 | 水桥 | **Soul文章上传、Soul派对文章、第9章上传、soul上传** | `02_卡人(水)/水桥_平台对接/Soul文章上传/SKILL.md` | 《一场soul的创业实验》第9章文章写好后上传到小程序,id 已存在则更新不重复 | ## 木组 · 卡木(产品内容创造) @@ -109,8 +110,8 @@ | 组 | 负责人 | 成员数 | 技能数 | |:--|:---|:--|:--| | 金 | 卡资 | 2 | 20 | -| 水 | 卡人 | 3 | 9 | +| 水 | 卡人 | 3 | 10 | | 木 | 卡木 | 3 | 6 | | 火 | 卡火 | 4 | 13 | | 土 | 卡土 | 4 | 6 | -| **合计** | **5** | **14** | **54** | +| **合计** | **5** | **14** | **55** | diff --git a/运营中枢/工作台/gitea_push_log.md b/运营中枢/工作台/gitea_push_log.md index 020c1355..0453c09b 100644 --- a/运营中枢/工作台/gitea_push_log.md +++ b/运营中枢/工作台/gitea_push_log.md @@ -43,3 +43,4 @@ | 2026-02-20 18:17:38 | 🔄 卡若AI 同步 2026-02-20 18:17 | 更新:水桥平台对接、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 5 个 | | 2026-02-20 18:29:55 | 🔄 卡若AI 同步 2026-02-20 18:29 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 5 个 | | 2026-02-20 18:38:29 | 🔄 卡若AI 同步 2026-02-20 18:38 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 | +| 2026-02-21 13:04:58 | 🔄 卡若AI 同步 2026-02-21 13:04 | 更新:金仓、水桥平台对接、运营中枢工作台 | 排除 >20MB: 5 个 | diff --git a/运营中枢/工作台/代码管理.md b/运营中枢/工作台/代码管理.md index 4d9c4da0..e82cf285 100644 --- a/运营中枢/工作台/代码管理.md +++ b/运营中枢/工作台/代码管理.md @@ -46,3 +46,4 @@ | 2026-02-20 18:17:38 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-20 18:17 | 更新:水桥平台对接、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | | 2026-02-20 18:29:55 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-20 18:29 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | | 2026-02-20 18:38:29 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-20 18:38 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | +| 2026-02-21 13:04:58 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-21 13:04 | 更新:金仓、水桥平台对接、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | diff --git a/运营中枢/工作台/存客宝_卡若AI磁盘清理脚本.sh b/运营中枢/工作台/存客宝_卡若AI磁盘清理脚本.sh new file mode 100644 index 00000000..b9263e17 --- /dev/null +++ b/运营中枢/工作台/存客宝_卡若AI磁盘清理脚本.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# 存客宝 42.194.245.239 磁盘清理 · 卡若AI 生成 +# 在宝塔面板【终端】中粘贴本脚本内容执行,或上传后 bash 本脚本 + +set -e +echo "========== 存客宝 卡若AI 磁盘清理 ==========" +echo "--- 清理前 ---" +df -h / +echo "" +echo "--- 大目录 TOP15 ---" +du -sh /www/* /var/log /tmp 2>/dev/null | sort -rh | head -15 +echo "" + +# 1. 清理系统日志(保留结构) +echo "[1/6] 清理系统旧日志..." +journalctl --vacuum-time=3d 2>/dev/null || true +find /var/log -type f -name "*.log" -mtime +7 -exec truncate -s 0 {} \; 2>/dev/null || true +find /var/log -type f -name "*.gz" -mtime +7 -delete 2>/dev/null || true + +# 2. 清理 apt 缓存(Ubuntu) +echo "[2/6] 清理 apt 缓存..." +apt-get clean 2>/dev/null || true +apt-get autoremove -y 2>/dev/null || true + +# 3. 清理临时目录 +echo "[3/6] 清理 /tmp /var/tmp..." +rm -rf /tmp/* 2>/dev/null || true +rm -rf /var/tmp/* 2>/dev/null || true + +# 4. 宝塔面板日志截断(不删文件) +echo "[4/6] 截断宝塔 request 日志..." +for f in /www/server/panel/logs/request/*.log; do [ -f "$f" ] && truncate -s 0 "$f"; done 2>/dev/null || true + +# 5. 网站日志截断(会清空当前日志内容,慎选) +echo "[5/6] 检查网站日志大小..." +du -sh /www/wwwlogs/ 2>/dev/null || true +# 若需清空网站日志,取消下一行注释: +# truncate -s 0 /www/wwwlogs/*.log 2>/dev/null || true + +# 6. 回收站(需在面板【文件】里手动清空,此处仅提示) +echo "[6/6] 请在面板【文件】→【回收站】中清空回收站以释放空间。" +echo "" +echo "--- 清理后 ---" +df -h / +echo "" +echo "--- 大目录 TOP15 ---" +du -sh /www/* /var/log /tmp 2>/dev/null | sort -rh | head -15 +echo "========== 清理完成 =========="