# TOOLS管理 ## 统一SSH管理 - **所有服务器**: 包括macmini、ubuntu1、ubuntu2、NAS - **管理方式**: 通过SSH统一管理,不存储sudo密码 - **权限原则**: 遵循最小权限原则 ## 管理流程 1. 所有服务器操作都通过SSH进行 2. 不存储任何服务器的sudo密码 3. 需要sudo权限的操作通过SSH执行 4. 保持所有服务器的管理方式一致 ## Docker命令路径 - **macmini**: `/usr/local/bin/docker` 或 `/opt/homebrew/bin/docker`(SSH时PATH不包含docker) - **NAS**: `/usr/local/bin/docker`(使用 `docker-compose` 而非 `docker compose`) - **ubuntu1/ubuntu2**: 直接用 `docker` ## 文件编辑注意事项 - **所有重要文件**: 使用 `exec + echo` 追加内容,避免 edit 工具在文件末尾无换行时失败 - **edit工具使用准则**: edit依赖精确文本匹配,任何空白字符差异都会导致失败。建议:先 read 文件确认内容,用 write 重写整个文件更可靠(特别是 memory、SOUL、IDENTITY 等重要文件) ## FRP (frpc 客户端) 管理 ### 安装目录 | 服务器 | FRP目录 | | ------- | -------------------------------- | | macmini | /opt/frp/frp_0.65.0_darwin_arm64 | | ubuntu1 | /opt/frp/frp_0.65.0_linux_amd64 | | ubuntu2 | /opt/frp/frp_0.65.0_linux_amd64 | ### 配置文件 - **文件名**: `frpc.toml`(在FRP目录下) - **作用**: 定义所有通过frp反向代理的应用及端口映射 (localPort ↔ remotePort) ### 管理方式(通过tmux) 1. 切换到root用户: `sudo su` 2. 进入FRP目录: `cd /opt/frp/frp_xxx` 3. 连接到tmux会话: `tmux attach -t frpc` 4. 停止进程: `Ctrl+C` 5. 重启frpc: `./frpc -c frpc.toml` 6. 查看启动是否成功 ### 查看配置 ```bash # 读取frpc.toml了解端口映射 cat /opt/frp/frp_0.65.0_xxx/frpc.toml ``` ## FRP端口映射查询格式 (2026-03-14) 用户会这样提问: - "ubuntu1上frp的列表" - "macmini的frp配置" - "查看ubuntu2的frpc.toml" 格式: 扫描frpc.toml文件,列出proxies相关配置 输出格式: 表格 (名称 | 类型 | localPort | remotePort) 查询示例: ssh到对应服务器 -> cat /opt/frp/frp_0.65.0_xxx/frpc.toml ## FRP状态检查 (2026-03-14) 用户可能说: "检查frp状态" **检查方法**: 1. SSH到对应服务器 2. 切换root: `sudo su` 3. 进入FRP目录: `cd /opt/frp/frp_xxx` 4. 如果是macmini服务器连接tmux: `tmux attach -t frpc` 5. 如果是ubuntu服务器:`systemctl status frpc` 6. 查看日志输出 **正常状态标志**: - 所有 proxy 启动成功时会显示: `[xxx] [name] start proxy success` - 例如: `2026-03-14 20:49:36.007 [I] [client/control.go:172] [65f4a34a064fae9e] [transmission] start proxy success` **重启命令** (如果需要): 1. 如果是macmini服务器: - `Ctrl+C` 停止当前进程 - `./frpc -c frpc.toml` 重启 2. 如果是ubuntu服务器 - `systemctl stop frpc` `systemctl start frpc` `systemctl restart frpc` ## VPS2 (x-UI 科学上网) - **IP**: 104.194.92.188 - **SSH**: `ssh vps2` - **管理命令**: `x-ui` - **用途**: x-UI 面板管理,用于科学上网 - 结果展示用列表方式,方便阅读 ## 笔记系统 用户可能说: "请帮我记笔记"、"帮我把这篇文章保存在笔记目录"、"请读取知识库笔记目录下的这篇笔记" 使用obsidian skill 读取/保存/修改Markdown笔记 Macmini服务器上 - **Obsidian笔记目录**: `/Users/weishen/Workspace/nexus` - **Openclaw笔记目录**: `/Users/weishen/Workspace/nexus/openclaw` - **知识库笔记目录**: `/Users/weishen/Workspace/nexus/openclaw/knowledgebase` - **云策专属笔记目录**: `/Users/weishen/Workspace/nexus/openclaw/yunce` ## 网络测试策略 (2026-03-15) 用户可能说: "网络测试"、"检查服务器科学上网" **测试项目**: 1. 国内直连baidu (https://www.baidu.com) 2. 国外直连 Google (https://www.google.com) 3. 国外通过代理访问 Google (socks5://127.0.0.1:10808) **测试命令模板**: **国内访问直连** ``` curl -v https://www.baidu.com ``` **国外访问直连** ``` curl -v https://www.google.com ``` **国外访问通过代理连** 这是最快、最直接的方法。我们可以强制 `curl` 使用 SOCKS5 代理去访问 Google 的状态页。 **执行命令:** ``` curl -x socks5h://127.0.0.1:10808 -v https://www.google.com ``` - **参数解释:**     - `-x socks5h://`:指定使用 SOCKS5 代理。注意加个 `h`,这表示让代理服务器去解析域名(防止本地 DNS 污染导致测试失败)。     - `-v`:(Verbose) 显示详细连接过程。 - **判断标准:**         - 如果看到 `HTTP/2 200` 或者大量的 HTML 文本,说明**代理成功**。     - 如果显示 `Connection refused` 或 `Timeout`,说明**端口未开放或 V2Ray 未运行**。 **服务器列表与代理端口**: | 服务器 | IP | 代理端口 | 备注 | |--------|-----|---------|------| | MacMini | 192.168.3.189 | 10808 | V2RayN | | Ubuntu1 | 192.168.3.47 | 10808 | 需SSH后测试 | | Ubuntu2 | 192.168.3.45 | 10808 | 需SSH后测试 | | NAS | 192.168.3.17 | 20170 | 仅监听127.0.0.1 | | VPS1 | 192.227.222.142 | - | 直连正常 | | VPS2 | 104.194.92.188 | - | 直连正常 | **输出格式**: 列表方式,方便阅读 **网络测试输出格式** 用户要求格式示例: • 服务器名   • 国内访问直连: ✅/❌   • 国外访问直连: ✅/❌   • 国外访问通过代理XXX连: ✅/❌   ## Telegram 配置注意事项 (2026-03-15) - groupPolicy=allowlist 时必须配置 groupAllowFrom,否则群消息被静默丢弃 - 中国访问Telegram API需要配置代理 (proxy) - 代理协议必须是 http:// 或 socks5:// - Bot 的 has_topics_enabled: false,不支持 Telegram Topics 功能 ## OpenClaw 命令路径 (2026-03-27) | 服务器 | OpenClaw 路径 | | -------- | ---------------------------------------- | | Mac mini | `/opt/homebrew/bin/openclaw` | | Ubuntu1 | `/home/shenwei/.npm-global/bin/openclaw` | | Ubuntu2 | `/home/shenwei/.npm-global/bin/openclaw` | ## NAS Docker 代理配置 (2026-03-27) - **配置文件**: `/etc/systemd/system/pkg-ContainerManager-dockerd.service.d/http-proxy.conf` - **用途**: Synology NAS 上 Docker 守护进程的代理设置 - **修改后需执行**: `sudo systemctl daemon-reload && sudo systemctl restart docker` **使用方式**: - SSH 到对应服务器后,使用完整路径执行命令 - 例如: `ssh ubuntu1 '/home/shenwei/.npm-global/bin/openclaw status'` ## sag (TTS 语音生成) (2026-03-27) ### 安装 ```bash brew install steipete/tap/sag ``` ### API Key 配置 - 位置: `~/.openclaw/.env` - 环境变量: `ELEVENLABS_API_KEY` ### 生成语音并发送到 Telegram ```bash # 1. 生成 MP3 文件 source ~/.openclaw/.env sag --api-key "$ELEVENLABS_API_KEY" -o /tmp/voice.mp3 "要转换的文字" # 2. 发送到 Telegram (voice note) message --account --chatId --filePath /tmp/voice.mp3 --message "文字" --buttons [] ``` ### 使用规则 - 所有用 sag 生成的语音都必须通过 Telegram voice note 发送给我 - 使用 当前agent对应的telegram bot 账号发送 - 文件临时保存在 /tmp/ 目录 ### OpenCode - **路径**: `/Users/weishen/.opencode/bin/opencode` - **版本**: 1.2.27 - **用法**: 开发任务必须通过它执行 ## Nexus Git 仓库配置 当用户说 "请帮我把这个笔记push到Git" 用于提交Obsidian笔记目录里的笔记,进行版本控制管理 - **Remote URL**: `ssh://git@192.168.3.189:2222/admin/nexus.git` - **SSH认证**: 已配置(osxkeychain),无需输入用户名密码 - **可直接执行**: git add → git commit → git push - **用户名**: weishen - **邮箱**: ishenwei@gmail.com ## AgentMail (邮件收发与自动化) (2026-03-28) ### 安装 ``` npm install -g @clawhub/agentmail ``` ### API Key / 账号配置 - 位置: `~/.openclaw/.env` - 环境变量: AGENTMAIL_API_KEY=your_api_key AGENTMAIL_EMAIL=your_email@example.com AGENTMAIL_PROVIDER=imap_smtp # 或 gmail / outlook AGENTMAIL_IMAP_HOST=imap.example.com AGENTMAIL_SMTP_HOST=smtp.example.com AGENTMAIL_PASSWORD=your_password_or_app_password > ⚠️ 建议使用 **App Password**(如 Gmail / Outlook),避免主密码暴露 ### 发送邮件 ``` agentmail send \ --to "target@example.com" \ --subject "测试邮件" \ --body "这是一封由 Agent 自动发送的邮件" ``` #### 带附件发送 ``` agentmail send \ --to "target@example.com" \ --subject "报告文件" \ --body "请查收附件" \ --attachments "/tmp/report.pdf,/tmp/log.txt" ``` ### 收取邮件 ``` agentmail fetch \ --limit 10 \ --unread true ``` #### 输出为 JSON(方便 Agent 处理) ``` agentmail fetch \ --limit 20 \ --format json > /tmp/mails.json ``` ### 搜索邮件 ``` agentmail search \ --query "from:boss@example.com subject:urgent" \ --limit 5 ``` ### 自动化处理(典型 Agent 场景) #### 1️⃣ 拉取未读邮件并分类 ``` agentmail fetch --unread true --format json > /tmp/unread.json ``` #### 2️⃣ 解析后自动回复 ``` agentmail send \ --to "" \ --subject "Re: " \ --body "已收到您的邮件,我们会尽快处理" ``` #### 3️⃣ 保存关键邮件到 Markdown(用于知识库 / Daily Notes) ``` agentmail fetch --limit 10 --format markdown > /tmp/mails.md ``` ### 与 Telegram 联动(通知类) ``` agentmail fetch --unread true --format text > /tmp/mail.txt ``` ``` message \ --account \ --chatId \ --message "$(cat /tmp/mail.txt)" ``` ### 使用规则 - 所有 **重要邮件(如告警 / 客户 / 商机)必须同步到 Telegram** - 邮件正文必须经过摘要处理(避免噪音信息) - 附件文件统一下载到 `/tmp/` 目录再处理 - 自动回复必须符合上下文语义,避免机械回复 - 对于批量邮件处理,优先输出 JSON 供 Agent 决策 - 敏感邮件(如包含凭证 / 密钥)禁止自动转发 ## Obsidian笔记同步 (2026-03-28) 用户可能说: "请帮我同步一下Obsidian笔记"、"请帮我把这篇笔记push到Git"、"请同步iCloud Obsidian笔记目录" ### 使用规则 1. 打开Macmini上的终端 2. 先把Obsidian笔记目录(`/Users/weishen/Workspace/nexus`)里新增内容添加到Git, 并添加备注,并push到Git 3. 再做一次`git pull`把Git上最新的内容同步到Obsidian笔记目录(`/Users/weishen/Workspace/nexus`) 4. 进入iCloud Obsidian目录 `/Users/weishen/Library/Mobile\ Documents/iCloud~md~obsidian/Documents/nexus` 5. 再执行一次`git pull` 6. 如果push成功,可以把commit id告诉用户。 7. 如果pull成功,也可以告诉用户目录已经更新。 ### 异常处理 如果在处理git命令过程中出现任何问题,请第一时间联系用户。并把错误消息贴给用户看。 ## N8N 工作流管理 (2026-03-29) 用户可能说: "帮我看看n8n上的工作流"、"触发n8n工作流"、"查看n8n执行记录" ### 连接配置 | 配置项 | 值 | |--------|-----| | **Base URL** | `https://n8n.ishenwei.online` | | **API Key** | `~/.openclaw/.env` 中的 `N8N_API_KEY` | | **管理界面** | https://n8n.ishenwei.online | ### 核心脚本路径 - **技能位置**: `~/.openclaw/skills/n8n/` - **n8n_api.py**: 工作流管理、触发执行、查看状态 - **n8n_tester.py**: 验证工作流、dry-run 测试 - **n8n_optimizer.py**: 性能分析与优化建议 ### 环境变量(已在 `~/.openclaw/.env`) ``` N8N_API_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... N8N_BASE_URL=https://n8n.ishenwei.online ``` ### 常用操作 ```bash # 查看工作流列表 python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py list-workflows --pretty # 查看执行记录 python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py list-executions --id --limit 20 --pretty # 手动触发工作流 python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py execute --id # 带数据触发 python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py execute --id --data '{"key": "value"}' # 激活/停用 python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py activate --id python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py deactivate --id ``` ### 测试与验证 ```bash # 验证工作流结构 python3 ~/.openclaw/skills/n8n/scripts/n8n_tester.py validate --id --pretty # Dry Run 测试 python3 ~/.openclaw/skills/n8n/scripts/n8n_tester.py dry-run --id --data '{}' ``` ### 创建工作流 ```bash # 从 JSON 文件创建 python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py create --from-file workflow.json # 创建后激活 python3 ~/.openclaw/skills/n8n/scripts/n8n_api.py activate --id ``` ### 性能分析 ```bash # 分析性能 python3 ~/.openclaw/skills/n8n/scripts/n8n_optimizer.py analyze --id --pretty # 获取优化建议 python3 ~/.openclaw/skills/n8n/scripts/n8n_optimizer.py suggest --id --pretty ``` ### Webhook 触发 ```bash # 直接调用 Webhook curl -X POST "https://n8n.ishenwei.online/webhook/" \ -H "Content-Type: application/json" \ -d '{"key": "value"}' ``` --- ## N8N 内容翻译流水线 (2026-03-29) **用途**:英文文章 → 中文(公众号Markdown + HTML)+ Twitter文案 + 视频脚本 **架构说明**: - n8n 只能读写容器内的 `/home/node/.n8n-files/` 目录 - OpenClaw 负责文件搬运:复制到 n8n → 触发 → 复制回 Obsidian - 完整设计文档:`~/Obsidian/shenwei/openclaw/yunce/n8n-content-pipeline-workflow.md` ### 工作流版本 | 版本 | ID | 状态 | 说明 | |------|-----|------|------| | **v5(最新)** | `iOf32aOKvTjfTDSM` | 未激活 | 双输出:Markdown + HTML | | v3 | `tOGMiC6qOJPOY89E` | 活跃 | 单输出(Markdown) | ### 调用前的文件准备 n8n 的 Read/Write File 节点使用 `/home/node/.n8n-files/` 目录,**不是** Obsidian 目录。 ``` n8n 容器内路径: /home/node/.n8n-files/ MacMini Obsidian: /Users/weishen/Workspace/nexus/openclaw/ ``` ### OpenClaw 完整调用流程 #### 第一步:复制原文到 n8n-files ```bash # SSH 到 MacMini,将源文件复制到 n8n 容器可访问的目录 scp /Users/weishen/Workspace/nexus/openclaw/content-queue/{文件名}.md \ macmini:/home/node/.n8n-files/{文件名}.md ``` #### 第二步:触发 Webhook ```bash # 注意:v5 使用 /content-translation-v5 # note_name = n8n-files 里的文件名 # output_name = 输出的文件名(不含扩展名) # source_path = Obsidian 原文路径(用于记录溯源) curl -X POST "https://n8n.ishenwei.online/webhook/content-translation-v5" \ -H "Content-Type: application/json" \ -d "{ \"note_name\": \"{文件名}.md\", \"output_name\": \"{文件名}\", \"source_path\": \"/Users/weishen/Workspace/nexus/openclaw/content-queue/{文件名}.md\", \"callback_url\": \"http://192.168.3.189:18789/webhook/yunce\" }" ``` #### 第三步:等待 Telegram 通知 - Telegram Bot (`y1NdRSaJwl0LoY37`) 会发送完成消息 - 消息格式:`✅ 文章转换完成!📝 标题:xxx` #### 第四步:复制输出回 Obsidian ```bash # 复制 Markdown 成品 scp macmini:/home/node/.n8n-files/{output_name}_output.md \ /Users/weishen/Workspace/nexus/openclaw/content-output/{output_name}.md # 复制 HTML 成品(公众号用) scp macmini:/home/node/.n8n-files/{output_name}_output.html \ /Users/weishen/Workspace/nexus/openclaw/content-output/{output_name}.html ``` #### 第五步:清理 n8n-files 临时文件 ```bash ssh macmini "rm /home/node/.n8n-files/{文件名}.md \ /home/node/.n8n-files/{output_name}_output.md \ /home/node/.n8n-files/{output_name}_output.html" ``` ### 完整 Python 调用示例 ```python import subprocess import time import json def trigger_content_translation(source_note_name, source_path, output_name): """完整的内容翻译流水线调用""" n8n_files_dir = "/home/node/.n8n-files" obsidian_root = "/Users/weishen/Workspace/nexus/openclaw" # ========== 第一步:复制原文到 n8n ========== source_full_path = f"{obsidian_root}/content-queue/{source_note_name}" print(f"[1/5] 复制原文到 n8n-files: {source_note_name}") subprocess.run([ 'scp', source_full_path, f'macmini:{n8n_files_dir}/{source_note_name}' ], check=True) # ========== 第二步:触发 Webhook ========== print(f"[2/5] 触发 n8n 工作流...") webhook_url = "https://n8n.ishenwei.online/webhook/content-translation-v5" payload = json.dumps({ "note_name": source_note_name, "output_name": output_name, "source_path": source_path, "callback_url": "http://192.168.3.189:18789/webhook/yunce" }) subprocess.run([ 'curl', '-X', 'POST', webhook_url, '-H', 'Content-Type: application/json', '-d', payload ], check=True) # ========== 第三步:等待处理 ========== print("[3/5] 等待 Telegram 完成通知...") # Agent 应等待 Telegram 消息后再继续 time.sleep(5) # 示意用,实际应监听 Telegram # ========== 第四步:复制输出回 Obsidian ========== print(f"[4/5] 复制输出到 content-output...") output_md = f"{n8n_files_dir}/{output_name}_output.md" output_html = f"{n8n_files_dir}/{output_name}_output.html" dest_root = f"{obsidian_root}/content-output" subprocess.run(['scp', f'macmini:{output_md}', f'{dest_root}/{output_name}.md'], check=True) subprocess.run(['scp', f'macmini:{output_html}', f'{dest_root}/{output_name}.html'], check=True) # ========== 第五步:清理 ========== print(f"[5/5] 清理 n8n-files...") subprocess.run(['ssh', 'macmini', f'rm {n8n_files_dir}/{source_note_name} {output_md} {output_html}']) print(f"✅ 完成!输出: {dest_root}/{output_name}.md + .html") # 调用示例 trigger_content_translation( source_note_name="article-2026-03-29.md", source_path="/Users/weishen/Workspace/nexus/openclaw/content-queue/article-2026-03-29.md", output_name="article-2026-03-29" ) ``` ### Obsidian 目录结构 ``` ~/Workspace/nexus/openclaw/ ├── content-queue/ # 原始英文文章 │ └── article-2026-03-29.md │ └── content-output/ # 翻译成品(Markdown + HTML) ├── article-2026-03-29.md # 中文 Markdown(留存溯源) └── article-2026-03-29.html # 公众号 HTML(直接复制粘贴) ``` ### 输出文件说明 | 文件 | 格式 | 用途 | |------|------|------| | `*.md` | 中文 Markdown | Obsidian 留存、溯源、可修改 | | `*.html` | 带样式 HTML | 复制到公众号编辑器,几乎零调整 | ### 常见问题 **Q: n8n API 返回 401?** A: 检查 `~/.openclaw/.env` 里的 `N8N_API_KEY` 是否完整(应为 3 段 JWT) **Q: 文件复制到 n8n-files 失败?** A: 确认 MacMini 上 `/home/node/.n8n-files/` 目录存在且有写权限 **Q: 如何查看工作流状态?** A: 用 `n8n_api.py list-executions --id --limit 10 --pretty` 查看最近执行