--- name: ops-tools description: DevOps 运维工具。用于 SSH 连接服务器、部署应用、健康检查、日志查看、服务重启和系统监控。当用户提到服务器操作、部署、运维、Jenkins、Gitea、ai-proj 相关任务时自动激活。 --- # DevOps Skill ## 子文档索引 | 文档 | 说明 | |------|------| | [ai-proj-deploy.md](ai-proj-deploy.md) | AI-Proj 部署流程 | | [coolbuy-deploy.md](coolbuy-deploy.md) | Coolbuy-PaaS 部署流程 | | [db-backup.md](db-backup.md) | ⚠️ **数据库备份与恢复(迁移前必读)** | | [mcp-config.md](mcp-config.md) | Claude Code MCP 配置 | | [incidents.md](incidents.md) | 重大事件记录 | > ⚠️ **重要提醒**:执行任何数据库 UPDATE/DELETE/ALTER 或数据迁移操作前,**必须先备份**! > 详见 [db-backup.md](db-backup.md) 的「迁移前快速备份」章节。 --- ## 服务器清单 | 别名 | IP | 用户 | SSH 密钥 | 用途 | |------|-----|------|----------|------| | tools-jenkins | 101.200.136.200 | root | ~/.ssh/tools.pem | Jenkins CI/CD | | tools-gitea | 123.56.89.187 | root | ~/.ssh/tools.pem | Gitea 代码托管 | | tools_ai_proj | 152.136.104.251 | root | ~/.ssh/tools_ai_proj.pem | AI项目生产服务器 | | singapore | 43.134.28.147 | ubuntu | ~/.ssh/singpore.pem | AI项目测试环境 & 跳板机 | | siyuan | 47.93.23.182 | root | ~/Downloads/siyuan.pem | 思源笔记服务器 (阿里云, Ubuntu 24.04) | | lvkai | 124.223.196.74 | root | ~/.ssh/lvkai | 通用服务器 (腾讯云, OpenCloudOS) | | coolbuy-dev | 100.112.161.79 | coolbuy-dev | ~/.ssh/id_ed25519_coolbuy_dev | Coolbuy 开发服务器 (Tailscale) | | melbourne | 100.85.65.39 | coolbuy-dev | ~/.ssh/id_ed25519_coolbuy_dev | Melbourne 开发电脑 (Tailscale) | | cn-dev | 100.92.148.46 | johnqiu | ~/.ssh/id_ed25519_cn_dev | 北京 MacBook Pro (Tailscale) | | chengdu-mac-mini | 100.105.50.115 | coolbuy | ~/.ssh/id_ed25519 | 成都 Mac Mini (Tailscale, SOCKS5 代理节点) | | au-dev | 当前电脑 | coolbuy-dev | - | 澳洲开发电脑 (本机) | | adelaide-dev-mini | 100.114.124.68 | donglinlai | ~/.ssh/id_ed25519 | Adelaide Mac Mini (Tailscale, 密钥存储) | | cn-bj-lazycat | 100.115.52.119 / haiqing.heiyu.space | root | 密码认证 (zhiyun2026) | 北京算力仓服务器 (Debian 6.5.0, 懒猫微服) | ### SSH 快捷连接 ```bash ssh tools-jenkins # Jenkins 服务器 ssh tools-gitea # Gitea 服务器 ssh tools_ai_proj # AI项目生产服务器 ssh singapore # 新加坡测试环境 ssh siyuan # 思源笔记服务器 ssh lvkai # LvKai 通用服务器 ssh coolbuy-dev # Coolbuy 开发服务器 (Tailscale) ssh melbourne # Melbourne 开发电脑 (Tailscale) ssh cn-dev # 北京 MacBook Pro (Tailscale) - iOS 开发 ssh adelaide-dev-mini # Adelaide Mac Mini (密钥存储) ``` ### 密钥存储机器 **adelaide-dev-mini** (100.114.124.68) 存储了所有服务器的 SSH 密钥: ```bash # 查看可用密钥 ssh adelaide-dev-mini "ls ~/.ssh/*.pem" # 可用密钥列表: # - singpore.pem → Singapore staging 服务器 # - tools_ai_proj.pem → 生产服务器 # - tools.pem → Jenkins/Gitea 服务器 # - coolbuy3.pem → Coolbuy 相关服务器 ``` **密钥同步到本机**: ```bash # 下载缺失的密钥 ssh adelaide-dev-mini "cat ~/.ssh/singpore.pem" > ~/.ssh/singpore.pem chmod 600 ~/.ssh/singpore.pem ``` --- ## 凭据配置 凭据存储在 `~/.config/devops/credentials.env`(权限 600): ```bash source ~/.config/devops/credentials.env # Jenkins API curl -s "$JENKINS_URL/api/json" \ -u "$JENKINS_USER:$JENKINS_TOKEN" ``` | 服务 | 变量 | |------|------| | Jenkins | `$JENKINS_USER:$JENKINS_TOKEN` | | OSS | `$OSS_ACCESS_KEY_ID`, `$OSS_ACCESS_KEY_SECRET` | > Gitea 操作统一使用 `tea` CLI,详见 `pull-request` 技能。 --- ## 服务地址 | 服务 | URL | 备注 | |------|-----|------| | Gitea Web | https://gitea.pipexerp.com | 代码仓库 | | Gitea SSH | git@gitea.pipexerp.com:10022 | Git SSH | | Jenkins | https://jenkins.pipexerp.com | CI/CD | | AI-Proj | https://ai.pipexerp.com | 生产环境 | | AI-Proj Staging | http://staging.ai.pipexerp.com | 测试环境 | | 思源笔记 | http://47.93.23.182 | 访问码: SiYuan@2026 | --- ## 常用命令 ### 系统状态 ```bash # 服务器概况 ssh "uptime && free -h && df -h && docker ps" # Docker 资源 ssh "docker stats --no-stream" # CPU/内存 Top 进程 ssh "ps aux --sort=-%cpu | head -10" ``` ### AI-Proj 操作 ```bash # 健康检查 curl -s https://ai.pipexerp.com/api/v1/health | jq . # 查看日志 ssh tools_ai_proj "docker logs -f ai_backend_prod --tail 100" # 重启服务 ssh tools_ai_proj "docker restart ai_backend_prod" # 生产部署(用户手动在终端执行,Claude 不要自动运行) # 详见 ai-proj-deploy.md「部署到生产环境」章节 # docker buildx build --platform linux/amd64 -t saltthing123/ai-proj-frontend:latest -f frontend/Dockerfile.prod --push ./frontend # docker buildx build --platform linux/amd64 -t saltthing123/ai-proj-backend:latest --push ./backend # ssh tools_ai_proj "cd /opt/ai-project && docker compose -f docker-compose.dockerhub.yml pull && docker compose -f docker-compose.dockerhub.yml up -d" # iOS TestFlight 部署 → 详见 dev-coding 技能「TestFlight 部署」章节 # 构建机器: cn-dev | Apple ID: 6205365@qq.com | Team: 5NHLK8SPHB ``` ### 思源笔记操作 ```bash # 查看容器状态 ssh siyuan "docker ps | grep siyuan" # 查看日志 ssh siyuan "docker logs -f siyuan --tail 100" # 重启服务 ssh siyuan "docker restart siyuan" # 停止服务 ssh siyuan "docker stop siyuan" # 启动服务 ssh siyuan "docker start siyuan" # 查看数据目录大小 ssh siyuan "du -sh /opt/siyuan/workspace" # 备份数据 ssh siyuan "tar -czf /root/siyuan-backup-\$(date +%Y%m%d).tar.gz /opt/siyuan/workspace" # 下载备份到本地 scp siyuan:/root/siyuan-backup-*.tar.gz ~/Downloads/ # 升级思源笔记(拉取最新镜像) ssh siyuan "docker pull b3log/siyuan:latest && docker restart siyuan" # 访问测试 curl -I http://47.93.23.182 ``` ### 数据库操作(迁移前必备份) ```bash # ⚠️ 迁移前备份(AI-Proj 生产) ssh tools_ai_proj 'docker exec ai_postgres_prod pg_dump -U ai_prod_user -Fc ai_project_prod \ > /backup/ai-project/database/ai_project_$(date +%Y%m%d_%H%M%S)_pre_migration.dump' # 查看备份列表 ssh tools_ai_proj 'ls -lht /backup/ai-project/database/*.dump | head -5' # 快速恢复 ssh tools_ai_proj 'docker exec ai_postgres_prod pg_restore \ -U ai_prod_user -d ai_project_prod --clean --if-exists -Fc \ /backup/ai-project/database/BACKUP_FILE.dump' # 执行 SQL 文件 scp /tmp/migration.sql tools_ai_proj:/tmp/ ssh tools_ai_proj 'docker cp /tmp/migration.sql ai_postgres_prod:/tmp/ && \ docker exec ai_postgres_prod psql -U ai_prod_user -d ai_project_prod -f /tmp/migration.sql' ``` > 详细文档见 [db-backup.md](db-backup.md) ### Gitea 操作 ```bash # PR / 代码评审 → 使用 tea CLI(pull-request 技能) tea pr list tea pr create ... # 查看容器(服务器运维) ssh tools-gitea "docker ps | grep gitea" ssh tools-gitea "docker logs -f gitea --tail 100" ``` ### Jenkins 操作 ```bash source ~/.config/devops/credentials.env # 构建状态 curl -s "$JENKINS_URL/job/coolbuy-paas/lastBuild/api/json" \ -u "$JENKINS_USER:$JENKINS_TOKEN" | jq '.result, .building' # 触发部署 curl -X POST "$JENKINS_URL/job/coolbuy-paas/buildWithParameters" \ -u "$JENKINS_USER:$JENKINS_TOKEN" \ --data "ACTION=deploy-prod&IMAGE_TAG=latest" ``` --- ## 双电脑同步 (au-dev / cn-dev) ### 项目目录 | 电脑 | new-ai-proj 路径 | |------|------------------| | au-dev | /Users/coolbuy-dev/coding/new-ai-proj | | cn-dev | /Users/johnqiu/workspace/new-ai-proj | ### sync-leave(离开前) ```bash git add -A git commit -m "WIP: sync from $(hostname)" || echo "Nothing to commit" git push origin $(git branch --show-current) ``` ### sync-arrive(到达后) ```bash git fetch origin git pull origin $(git branch --show-current) ``` ### sync-merge(合并 WIP 提交) ```bash git reset --soft HEAD~ git add -A git commit -m "feat: 实际功能描述" git push origin $(git branch --show-current) --force-with-lease ``` --- ## 故障排查 ### 服务无响应 ```bash systemctl status journalctl -u --since "5 minutes ago" netstat -tlnp | grep ``` ### 磁盘空间不足 ```bash df -h docker system prune -af journalctl --vacuum-size=500M ``` ### 内存不足 ```bash free -h ps aux --sort=-%mem | head -10 ``` --- ## 安全注意事项 - SSH 密钥权限必须是 600 - 不要在命令中明文包含密码 - 生产环境操作需要二次确认 - **生产数据库操作必须先备份** - **docker compose down 前检查 volumes 配置** --- ## AI-Proj 用户管理 ### 创建系统用户 > **重要**: AI-Proj 后端使用 bcrypt **cost 12** 进行密码哈希。不要使用 cost 10 或其他值。 #### 完整流程 由于 bcrypt 哈希包含 `$` 字符,在 shell 中直接执行会导致变量替换问题。正确流程如下: **步骤 1: 生成密码哈希(cost 12)** ```bash # 在 backend 目录下执行,使用 Go 生成哈希 cd /path/to/new-ai-proj/backend # 创建临时 Go 脚本 cat > /tmp/genhash.go << 'EOF' package main import ( "fmt" "golang.org/x/crypto/bcrypt" ) func main() { hash, err := bcrypt.GenerateFromPassword([]byte("用户密码"), 12) if err != nil { panic(err) } fmt.Println(string(hash)) } EOF # 执行生成哈希 go run /tmp/genhash.go # 输出示例: $2a$12$E5KVmMDiJPi61kThzgDEdeRiIHqTtZ2yB5F0ccIoE3wfRPIH7hHRG ``` **步骤 2: 创建 SQL 文件** ```bash # 将哈希写入 SQL 文件(避免 shell 转义问题) cat > /tmp/create_user.sql << 'EOF' INSERT INTO users ( username, email, password_hash, user_type, role, status, created_at, updated_at ) VALUES ( 'newuser', 'newuser@example.com', '$2a$12$E5KVmMDiJPi61kThzgDEdeRiIHqTtZ2yB5F0ccIoE3wfRPIH7hHRG', 'system', 'admin', 'active', NOW(), NOW() ); EOF ``` **步骤 3: 传输并执行 SQL** ```bash # 复制 SQL 文件到服务器 scp /tmp/create_user.sql tools_ai_proj:/tmp/ # 在服务器上执行 ssh tools_ai_proj "docker cp /tmp/create_user.sql ai_postgres_prod:/tmp/ && \ docker exec ai_postgres_prod psql -U ai_prod_user -d ai_project_prod -f /tmp/create_user.sql" ``` **步骤 4: 验证用户创建** ```bash # 检查用户是否创建成功 ssh tools_ai_proj "docker exec ai_postgres_prod psql -U ai_prod_user -d ai_project_prod \ -c \"SELECT id, username, email, user_type, role, status, length(password_hash) as hash_len FROM users WHERE username = 'newuser';\"" # 测试登录 curl -s -X POST "https://ai.pipexerp.com/api/v1/auth/login" \ -H "Content-Type: application/json" \ -d '{"username":"newuser","password":"用户密码"}' | jq '.success' ``` ### 用户角色说明 | user_type | role | 说明 | |-----------|------|------| | system | admin | 系统管理员(最高权限) | | system | user | 系统用户 | | tenant | admin | 租户管理员 | | tenant | user | 租户用户 | ### 重置用户密码 ```bash # 1. 生成新密码哈希 cd /path/to/new-ai-proj/backend cat > /tmp/genhash.go << 'EOF' package main import ( "fmt" "golang.org/x/crypto/bcrypt" ) func main() { hash, _ := bcrypt.GenerateFromPassword([]byte("新密码"), 12) fmt.Println(string(hash)) } EOF NEW_HASH=$(go run /tmp/genhash.go) # 2. 创建更新 SQL cat > /tmp/reset_pwd.sql << EOF UPDATE users SET password_hash = '$NEW_HASH' WHERE username = 'targetuser'; EOF # 3. 执行更新 scp /tmp/reset_pwd.sql tools_ai_proj:/tmp/ ssh tools_ai_proj "docker cp /tmp/reset_pwd.sql ai_postgres_prod:/tmp/ && \ docker exec ai_postgres_prod psql -U ai_prod_user -d ai_project_prod -f /tmp/reset_pwd.sql" ``` ### 常见问题 | 问题 | 原因 | 解决方案 | |------|------|----------| | 登录失败,密码错误 | 哈希 cost 不匹配(使用了 cost 10) | 使用 Go 重新生成 cost 12 的哈希 | | SQL 执行失败 | `$` 字符被 shell 解释 | 使用 heredoc 或文件传输方式 | | 哈希被截断 | 直接在命令行执行 SQL | 使用文件方式避免转义问题 | ## 本地开发环境配置 (au-dev) ### 前置条件 ```bash # PostgreSQL 16 (Homebrew) brew install postgresql@16 brew services start postgresql@16 # Redis brew install redis brew services start redis # Tailscale (用于访问 cn-dev / au-dev-mini) # 从 App Store 安装或 brew install tailscale ``` ### 从 Staging 同步数据库 当本地需要测试数据时,从 Singapore staging 环境同步: ```bash # 1. 确保有 singpore.pem 密钥 ls ~/.ssh/singpore.pem || ssh au-dev-mini "cat ~/.ssh/singpore.pem" > ~/.ssh/singpore.pem chmod 600 ~/.ssh/singpore.pem # 2. 导出 staging 数据库 ssh singapore "docker exec ai_postgres_staging pg_dump -U ai_staging_user ai_project_staging --no-owner --no-acl --clean --if-exists | gzip > /tmp/staging_backup.sql.gz" # 3. 下载到本地 scp singapore:/tmp/staging_backup.sql.gz /tmp/ # 4. 重建本地数据库 psql postgres -c "DROP DATABASE IF EXISTS ai_project_local;" psql postgres -c "DROP USER IF EXISTS ai_local;" psql postgres -c "CREATE USER ai_local WITH PASSWORD 'ai_local_pass' SUPERUSER;" psql postgres -c "CREATE DATABASE ai_project_local OWNER ai_local;" # 5. 恢复数据 gunzip -c /tmp/staging_backup.sql.gz | psql -U ai_local ai_project_local # 6. 验证 psql -U ai_local ai_project_local -c "SELECT COUNT(*) FROM tasks;" ``` ### 后端 .env 配置 ```bash # 创建 backend/.env cat > /Users/coolbuy-dev/coding/new-ai-proj/backend/.env << 'EOF' ENV=development APP_ENV=development GIN_MODE=debug DB_HOST=localhost DB_PORT=5432 DB_USER=ai_local DB_PASSWORD=ai_local_pass DB_NAME=ai_project_local DB_SSL_MODE=disable REDIS_HOST=localhost REDIS_PORT=6379 REDIS_PASSWORD= REDIS_DB=0 BACKEND_PORT=8080 JWT_SECRET=local_dev_jwt_secret_key_32chars JWT_EXPIRATION=168h CORS_ORIGIN=http://localhost:3000 FEATURE_SUPERADMIN_ENABLE=true SUPER_ADMIN_USERNAMES=admin EOF ``` ### 启动本地服务 ```bash # 终端 1: 后端 cd /Users/coolbuy-dev/coding/new-ai-proj/backend go run main.go # 终端 2: 前端 cd /Users/coolbuy-dev/coding/new-ai-proj/frontend npm start # 验证 curl -s http://localhost:8080/api/v1/health | jq . # 访问 http://localhost:3000 ``` ### 本地服务状态检查 ```bash # PostgreSQL pg_isready -h localhost # Redis redis-cli ping # 后端健康检查 curl -s http://localhost:8080/api/v1/health # 前端 (检查端口) lsof -i :3000 ``` --- ## 跨境网络代理 (SSH SOCKS5 隧道) 当从澳洲访问国内网站(如 ai.pipexerp.com)速度慢时,可通过国内 Tailscale 节点建立 SSH 隧道。 ### 问题诊断 ```bash # 1. 检查延迟和丢包 ping -c 3 ai.pipexerp.com # 2. 确认出口 IP 位置 curl -s ipinfo.io # 3. 测试访问速度 curl -I --connect-timeout 10 https://ai.pipexerp.com ``` ### Tailscale 国内节点 | 节点 | IP | 用户 | 用途 | |------|-----|------|------| | chengdu-mac-mini | 100.105.50.115 | coolbuy | 成都 Mac Mini (推荐) | | cn-bj-qiu-macbook-portable | 100.92.148.46 | - | 北京 MacBook | | cn-tj-pve-fnos | 100.118.62.18 | - | 天津 Linux | ### 手动启动 SOCKS5 代理 ```bash # 通过成都节点建立隧道 (端口 1080) ssh -D 1080 -C -N -f coolbuy@100.105.50.115 # 测试代理 curl -x socks5://localhost:1080 -I https://ai.pipexerp.com ``` ### 开机自启动配置 plist 文件: `~/Library/LaunchAgents/com.socks.chengdu.plist` ```xml Label com.socks.chengdu ProgramArguments /usr/bin/ssh -D 1080 -C -N -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes coolbuy@100.105.50.115 RunAtLoad KeepAlive StandardErrorPath /tmp/socks-chengdu.err StandardOutPath /tmp/socks-chengdu.log ``` ### 服务管理 ```bash # 查看状态 launchctl list | grep socks.chengdu # 停止服务 launchctl unload ~/Library/LaunchAgents/com.socks.chengdu.plist # 启动服务 launchctl load ~/Library/LaunchAgents/com.socks.chengdu.plist # 查看日志 cat /tmp/socks-chengdu.err # 验证隧道运行 lsof -i :1080 ``` ### 浏览器配置 (SwitchyOmega) 1. 安装 Chrome/Edge 扩展 SwitchyOmega 2. 新建情景模式 → 代理服务器 → SOCKS5 → `127.0.0.1:1080` 3. 自动切换规则: - `*.pipexerp.com` → 国内代理 - `*.cn` → 国内代理 - 其他 → 直连 --- ## SSH 跳板与反向隧道 当 Tailscale 直连不稳定或反向连接失败时,可通过公网服务器建立 SSH 跳板解决。 ### 问题场景 **典型问题**: - 本机可以 ping 通远程机器(如 cn-bj-lazycat) - 本机可以 SSH 到远程机器 - 但远程机器无法 SSH 回本机(连接超时) **原因分析**: 1. Tailscale 使用 DERP 中继,连接不稳定 2. NAT 穿透失败,反向连接无法建立 3. 网络延迟高(200-700ms+),TCP 连接容易超时 ### 解决方案架构 ``` 远程机器 (cn-bj-lazycat) ↓ SSH 公网跳板 (Singapore) ↓ 反向隧道 localhost:2222 本机 (au-melbourne-coolbuy-dev) ``` **优势**: - ✅ 利用稳定的公网服务器作为中继 - ✅ 绕过 Tailscale DERP 不稳定问题 - ✅ 自动重连,无需手动维护 - ✅ 安全:隧道只监听 localhost,需通过跳板访问 ### 配置步骤 #### 步骤 1: 本机建立反向隧道 **手动启动**(测试用): ```bash ssh -fN -R 2222:localhost:22 singapore ``` **配置自动重连服务**(推荐): 创建 `~/Library/LaunchAgents/com.ssh.singapore-tunnel.plist`: ```xml Label com.ssh.singapore-tunnel ProgramArguments /usr/bin/ssh -N -R 2222:localhost:22 -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes singapore RunAtLoad KeepAlive StandardErrorPath /tmp/singapore-tunnel.err StandardOutPath /tmp/singapore-tunnel.log ``` 启动服务: ```bash launchctl load ~/Library/LaunchAgents/com.ssh.singapore-tunnel.plist launchctl list | grep singapore-tunnel ``` #### 步骤 2: 配置 SSH 密钥认证 **在跳板服务器上生成密钥**(如果还没有): ```bash ssh singapore "ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N '' -C 'singapore-jump'" ``` **将跳板公钥添加到本机**: ```bash ssh singapore "cat ~/.ssh/id_ed25519.pub" >> ~/.ssh/authorized_keys ``` **测试反向隧道**: ```bash ssh singapore "ssh -p 2222 -o StrictHostKeyChecking=no <本机用户>@localhost 'hostname'" ``` #### 步骤 3: 远程机器配置 **传输跳板 SSH 密钥到远程机器**: ```bash # 在远程机器上创建 SSH 目录 ssh "mkdir -p ~/.ssh && chmod 700 ~/.ssh" # 传输密钥(通过管道避免 scp 密码问题) cat ~/.ssh/singpore.pem | ssh "cat > ~/.ssh/singpore.pem && chmod 600 ~/.ssh/singpore.pem" ``` **配置 SSH config**(在远程机器上): ```bash ssh "cat > ~/.ssh/config << 'EOFCONFIG' # Singapore 跳板服务器 Host singapore HostName 43.134.28.147 User ubuntu IdentityFile ~/.ssh/singpore.pem ServerAliveInterval 60 ServerAliveCountMax 3 # 通过 Singapore 访问目标机器 Host HostName localhost Port 2222 User ProxyJump singapore ServerAliveInterval 60 ServerAliveCountMax 3 EOFCONFIG chmod 600 ~/.ssh/config" ``` **配置远程机器的 SSH 密钥认证**: ```bash # 在远程机器上生成密钥 ssh "ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N '' -C ''" # 将远程机器公钥添加到本机 ssh "cat ~/.ssh/id_ed25519.pub" >> ~/.ssh/authorized_keys ``` #### 步骤 4: 测试连接 **从远程机器测试**: ```bash # 连接到跳板 ssh "ssh singapore 'hostname'" # 通过跳板连接到本机 ssh "ssh 'hostname && whoami'" ``` ### 实际案例:cn-bj-lazycat 配置 **场景**:从 cn-bj-lazycat (懒猫算力仓) 稳定访问 Melbourne 开发机 **服务器信息**: - **cn-bj-lazycat**: 100.115.52.119 / haiqing.heiyu.space - 系统: Debian GNU/Linux (Kernel 6.5.0) - 用户: root(密码: zhiyun2026) - 用途: 北京算力仓服务器(懒猫微服) - **Melbourne**: au-melbourne-coolbuy-dev (100.112.161.78) - 系统: macOS Darwin 25.2.0 - 用户: coolbuy-dev - 用途: 澳洲开发电脑 **配置详情**: ```bash # 1. Melbourne 本机 - 反向隧道已自动运行 launchctl list | grep singapore-tunnel # 输出: 10349 0 com.ssh.singapore-tunnel # 2. cn-bj-lazycat 上的完整配置 ssh root@haiqing.heiyu.space # 密码: zhiyun2026 # SSH config 已配置: Host singapore HostName 43.134.28.147 User ubuntu IdentityFile ~/.ssh/singpore.pem ServerAliveInterval 60 ServerAliveCountMax 3 Host au-melbourne au-dev melbourne HostName localhost Port 2222 User coolbuy-dev ProxyJump singapore ServerAliveInterval 60 ServerAliveCountMax 3 # 3. 使用方式(支持 3 个别名) ssh melbourne "hostname && whoami" ssh au-melbourne "ls -la" ssh au-dev "uname -a" # 文件传输 scp file.txt melbourne:/tmp/ scp melbourne:/path/to/file ./ # 4. 验证连接 ssh melbourne 'echo "✅ 连接成功!当前在 $(hostname)"' ``` **连接测试结果**: ```bash # 所有别名测试通过 ssh au-melbourne # ✅ 成功 ssh melbourne # ✅ 成功 ssh au-dev # ✅ 成功 ``` ### 管理命令 **本机管理反向隧道**: ```bash # 查看状态 launchctl list | grep singapore-tunnel ps aux | grep "ssh.*singapore" # 重启服务 launchctl unload ~/Library/LaunchAgents/com.ssh.singapore-tunnel.plist launchctl load ~/Library/LaunchAgents/com.ssh.singapore-tunnel.plist # 查看日志 cat /tmp/singapore-tunnel.err # 验证隧道端口 ssh singapore "netstat -tlnp | grep :2222" ``` **远程机器管理**: ```bash # 测试连接质量 ssh "time echo 'test'" # 查看 SSH 配置 ssh "cat ~/.ssh/config" # 测试 ProxyJump ssh "ssh -v 'hostname' 2>&1 | grep -i 'proxy\|jump'" ``` ### 故障排查 | 问题 | 可能原因 | 解决方案 | |------|---------|----------| | 反向隧道断开 | 网络波动、服务器重启 | 检查 LaunchAgent 服务是否运行 | | 认证失败 | 密钥权限错误、公钥未添加 | 确保密钥权限 600,公钥在 authorized_keys | | 连接超时 | 跳板服务器网络问题 | 测试到跳板的连接:`ping singapore` | | ProxyJump 失败 | SSH config 语法错误 | 检查 config 文件格式和缩进 | ### 安全注意事项 - ✅ 反向隧道只监听 localhost,外部无法直接访问 - ✅ SSH 密钥权限必须是 600 - ✅ 定期检查 authorized_keys,移除不需要的密钥 - ✅ 跳板服务器应启用 fail2ban 等安全措施 - ⚠️ 避免在公共网络下使用密码认证,优先使用密钥 --- ## MCP 配置(快速参考) **配置文件**: `~/.claude/.mcp.json` ```json { "mcpServers": { "ai-proj": { "type": "stdio", "command": "node", "args": ["/Users/coolbuy-dev/coding/new-ai-proj/mcp-task-bridge/dist/index.js"], "env": { "TASK_API_BASE": "https://ai.pipexerp.com/api/v1", "TASK_API_TOKEN": "aiproj_pk_2ecf8f8728b70afd4420af3875f4f7505c9fe8231a4771972b0f385aa1c75099", "NODE_ENV": "production" } } } } ``` **前置条件**: `cd mcp-task-bridge && npm run build` **详细说明**: 见 [mcp-config.md](mcp-config.md) --- ## OpenClaw 配置(懒猫算力仓) OpenClaw 运行在懒猫算力仓的容器环境中,需要特殊配置才能访问 skills。 ### 问题与解决方案 **问题**:OpenClaw 运行在容器内,无法访问宿主机的 `~/.claude/skills/` 目录 **原因**:容器和宿主机文件系统隔离,skills 目录未挂载到容器内 **解决方案**:将 skills 复制到容器内的标准路径 ### 配置步骤 #### 1. 连接到懒猫算力仓 ```bash # 添加 SSH 配置(首次配置) cat >> ~/.ssh/config << 'EOF' Host cn-bj-lazycat lazycat HostName haiqing.heiyu.space User root IdentityFile ~/.ssh/id_lazycat ServerAliveInterval 60 ServerAliveCountMax 3 EOF # 生成并配置 SSH 密钥 ssh-keygen -t ed25519 -f ~/.ssh/id_lazycat -N "" -C "au-dev-to-lazycat" ssh-copy-id -i ~/.ssh/id_lazycat root@haiqing.heiyu.space # 密码: zhiyun2026 # 测试连接 ssh lazycat "whoami && hostname" ``` #### 2. 查找 OpenClaw 容器 ```bash # 查看运行的容器 ssh lazycat "/lzcsys/bin/lzc-docker ps --format 'table {{.ID}}\t{{.Names}}'" # 找到 OpenClaw 容器 ID(通常是固定的) CONTAINER_ID="5f3bf33e090b" # 懒猫算力仓的 OpenClaw 容器 ``` #### 3. 复制 skills 到容器内 ```bash # 在容器内创建目录 ssh lazycat "/lzcsys/bin/lzc-docker exec $CONTAINER_ID mkdir -p /root/.claude/skills" # 复制 skills(从宿主机到容器) ssh lazycat "/lzcsys/bin/lzc-docker cp /root/.claude/skills/. $CONTAINER_ID:/root/.claude/skills/" # 验证复制结果 ssh lazycat "/lzcsys/bin/lzc-docker exec $CONTAINER_ID ls -la /root/.claude/skills/ | head -20" ssh lazycat "/lzcsys/bin/lzc-docker exec $CONTAINER_ID ls /root/.claude/skills/ | wc -l" ``` #### 4. 重启 OpenClaw ```bash # 重启容器使配置生效 ssh lazycat "/lzcsys/bin/lzc-docker restart $CONTAINER_ID" # 检查容器状态 ssh lazycat "/lzcsys/bin/lzc-docker ps | grep $CONTAINER_ID" ``` ### 更新 Skills 当本地更新了 skills 后,需要重新同步到懒猫算力仓: ```bash # 步骤 1: 同步 skills 到宿主机 ssh lazycat "mkdir -p ~/.claude" cd ~/.dotfiles tar -czf - claude-skills/ | ssh lazycat "cd ~/.claude && rm -rf skills && tar -xzf - && mv claude-skills skills" # 步骤 2: 复制到 OpenClaw 容器 ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b rm -rf /root/.claude/skills" ssh lazycat "/lzcsys/bin/lzc-docker cp /root/.claude/skills/. 5f3bf33e090b:/root/.claude/skills/" # 步骤 3: 重启 OpenClaw ssh lazycat "/lzcsys/bin/lzc-docker restart 5f3bf33e090b" ``` ### 验证配置 ```bash # 检查容器内的 skills 数量 ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b ls /root/.claude/skills/ | wc -l" # 应该显示: 41 # 检查特定 skill 内容 ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b cat /root/.claude/skills/ai-proj/SKILL.md | head -30" # 检查 OpenClaw 配置 ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b cat /home/node/.openclaw/openclaw.json | grep -A 3 workspace" ``` ### 懒猫算力仓环境信息 | 项目 | 信息 | |------|------| | **宿主机** | Debian GNU/Linux (Kernel 6.5.0) | | **容器 ID** | 5f3bf33e090b (固定) | | **Docker 命令** | `/lzcsys/bin/lzc-docker` (懒猫专用) | | **OpenClaw 配置** | `/home/node/.openclaw/openclaw.json` | | **Skills 路径** | `/root/.claude/skills/` (容器内) | | **宿主 Skills** | `/root/.claude/skills/` (宿主机) | ### 自动化脚本 创建 `~/.local/bin/sync-skills-to-lazycat.sh`: ```bash #!/bin/bash # 同步 skills 到懒猫算力仓 OpenClaw set -e echo "=== 同步 skills 到懒猫算力仓 ===" # 1. 同步到宿主机 echo "步骤 1: 同步到宿主机..." cd ~/.dotfiles tar -czf - claude-skills/ | ssh lazycat "cd ~/.claude && rm -rf skills && tar -xzf - && mv claude-skills skills" # 2. 复制到容器 echo "步骤 2: 复制到 OpenClaw 容器..." ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b rm -rf /root/.claude/skills || true" ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b mkdir -p /root/.claude/skills" ssh lazycat "/lzcsys/bin/lzc-docker cp /root/.claude/skills/. 5f3bf33e090b:/root/.claude/skills/" # 3. 验证 echo "步骤 3: 验证..." SKILL_COUNT=$(ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b ls /root/.claude/skills/ | wc -l") echo "✅ 同步完成!共 $SKILL_COUNT 个 skills" # 4. 重启 OpenClaw echo "步骤 4: 重启 OpenClaw..." ssh lazycat "/lzcsys/bin/lzc-docker restart 5f3bf33e090b" echo "✅ OpenClaw 已重启" ``` 使用方法: ```bash chmod +x ~/.local/bin/sync-skills-to-lazycat.sh sync-skills-to-lazycat.sh ``` ### Agent-Swarm 多智能体技能部署 **agent-swarm** 是基于 OpenAI Swarm 设计模式的多智能体协作系统,用于复杂开发任务的智能分解与协调。 #### 技能概述 | 项目 | 信息 | |------|------| | **技能名称** | agent-swarm | | **版本** | 1.0.0 | | **文档大小** | 9.1KB (450+ 行) | | **预定义 Agent** | 5 个 (Architect, Coder, Tester, Reviewer, Deployer) | | **部署日期** | 2026-02-16 | | **部署位置** | 懒猫算力仓 OpenClaw 容器 | #### 快速部署 **从本地部署到懒猫算力仓**: ```bash # 1. 确保本地有 agent-swarm 技能 ls ~/.claude/skills/agent-swarm/ # skill.yaml SKILL.md README.md # 2. 打包技能 cd /tmp tar -czf agent-swarm-skill.tar.gz -C ~/.claude/skills agent-swarm # 3. 上传到懒猫算力仓宿主机 sshpass -p 'zhiyun2026' scp -o StrictHostKeyChecking=no \ agent-swarm-skill.tar.gz root@haiqing.heiyu.space:/tmp/ # 4. 在宿主机解压并部署到容器 sshpass -p 'zhiyun2026' ssh -o StrictHostKeyChecking=no root@haiqing.heiyu.space " cd /tmp && tar -xzf agent-swarm-skill.tar.gz && \ cp -r agent-swarm /root/.claude/skills/ && \ /lzcsys/bin/lzc-docker cp /root/.claude/skills/agent-swarm 5f3bf33e090b:/root/.claude/skills/ " # 5. 重启 OpenClaw sshpass -p 'zhiyun2026' ssh -o StrictHostKeyChecking=no root@haiqing.heiyu.space \ "/lzcsys/bin/lzc-docker restart 5f3bf33e090b" # 6. 验证安装 sshpass -p 'zhiyun2026' ssh -o StrictHostKeyChecking=no root@haiqing.heiyu.space \ "/lzcsys/bin/lzc-docker exec 5f3bf33e090b ls /root/.claude/skills/ | wc -l" # 应该显示: 43 (42 + agent-swarm) ``` #### 使用方法 在飞书中 @OpenClaw 使用以下命令: ```bash # 查看所有 Agent /swarm agents # 启动完整开发工作流(从架构设计开始) /swarm start "在 new-ai-proj 中实现任务批量删除功能" # 从特定 Agent 开始 /swarm coder "修复 backend/handlers/task_handler.go 的空指针 bug" # 并行执行多个任务 /swarm parallel "实现后端API" "实现前端UI" "编写测试" # 查看执行轨迹 /swarm trace # 显示配置 /swarm config ``` #### Agent 工作流 ``` 用户请求 → Architect (需求分析、架构设计) ↓ handoff Coder (编写代码、实现功能) ↓ handoff Tester (编写测试、运行测试) ↓ handoff Reviewer (代码审查、安全检查) ↓ handoff Deployer (部署服务、监控上线) ↓ 完成 ✅ ``` #### 5 个预定义 Agent | Agent | 职责 | Tools | Handoff to | |-------|------|-------|------------| | **Architect** | 需求分析、架构设计、技术选型 | Read, Grep, Glob | Coder, Reviewer | | **Coder** | 编写代码、实现功能、Bug 修复 | Edit, Write, Bash | Tester, Architect | | **Tester** | 编写测试、运行测试、验证功能 | Bash, Write | Deployer, Coder | | **Reviewer** | 代码审查、安全检查、质量把关 | Read, Grep | Coder, Deployer | | **Deployer** | 部署服务、监控上线、健康检查 | Bash, SSH | Monitor, Coder | #### 配置自定义 Agent (可选) 在项目根目录创建 `swarm.yaml`: ```yaml agents: architect: instructions: | 你是系统架构师,专注于 Go + Vue.js 技术栈。 遵循 RESTful API 设计原则。 max_turns: 5 coder: instructions: | 你是全栈工程师。 编写清晰、简洁、高性能的代码。 max_turns: 10 context_variables: project_root: /Users/coolbuy-dev/coding/new-ai-proj backend_lang: Go 1.21 frontend_framework: Vue 3 database: PostgreSQL 15 ``` #### 实际应用场景 **场景 1: 新功能开发** ```bash /swarm start "为 AI-Proj 实现需求批量导出为 Excel 功能,支持自定义字段和筛选条件" ``` 自动执行:Architect 设计 → Coder 实现 → Tester 测试 → Reviewer 审查 → Deployer 部署 **场景 2: Bug 修复 + 性能优化** ```bash /swarm coder "优化任务详情页加载性能,从 3s 降到 300ms 以内" ``` 自动执行:Coder 优化 → Tester 验证 → Deployer 灰度发布 **场景 3: 代码审查** ```bash /swarm reviewer "审查 PR #123 的代码质量和安全性" ``` 自动执行:Reviewer 分析 → Coder 修改 → Deployer 部署 #### 参考资料 - **完整文档**: 容器内 `/root/.claude/skills/agent-swarm/SKILL.md` - **OpenAI Swarm**: https://github.com/openai/swarm - **部署日期**: 2026-02-16 - **当前技能总数**: 43 个 ### MCP 服务器配置 OpenClaw 支持 MCP (Model Context Protocol),可以连接 ai-proj 等服务。 #### 配置位置 容器内配置文件:`/root/.claude/.mcp.json` #### 配置步骤 **1. 部署 mcp-task-bridge** ```bash # 从本地传输 mcp-task-bridge(包含编译产物和依赖) cd /Users/coolbuy-dev/coding/new-ai-proj tar -czf - mcp-task-bridge/dist mcp-task-bridge/package.json mcp-task-bridge/node_modules | \ ssh lazycat "cd /root && tar -xzf -" # 复制到容器内 ssh lazycat "/lzcsys/bin/lzc-docker cp /root/mcp-task-bridge 5f3bf33e090b:/root/" # 验证 ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b ls -la /root/mcp-task-bridge/" ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b node --version" ``` **2. 创建 MCP 配置文件** ```bash # 创建配置文件 cat > /tmp/mcp-config.json << 'EOF' { "mcpServers": { "ai-proj-prod": { "type": "stdio", "command": "node", "args": ["/root/mcp-task-bridge/dist/index.js"], "env": { "NODE_ENV": "production", "TASK_API_BASE": "https://ai.pipexerp.com/api/v1", "TASK_API_TOKEN": "aiproj_pk_2ecf8f8728b70afd4420af3875f4f7505c9fe8231a4771972b0f385aa1c75099", "DEV_LOGIN_USERNAME": "qiudl", "MCP_SERVER_NAME": "ai-proj-prod" } }, "ai-proj-staging": { "type": "stdio", "command": "node", "args": ["/root/mcp-task-bridge/dist/index.js"], "env": { "NODE_ENV": "staging", "TASK_API_BASE": "https://staging.ai.pipexerp.com/api/v1", "TASK_API_TOKEN": "aiproj_pk_ff1ee5478268fd8fe3f9eeb7dd28c8a35f32026b3a3846715f0a40cad542bdd6", "DEV_LOGIN_USERNAME": "qiudl", "MCP_SERVER_NAME": "ai-proj-staging" } } } } EOF # 复制到容器内 scp /tmp/mcp-config.json lazycat:/tmp/ ssh lazycat "/lzcsys/bin/lzc-docker cp /tmp/mcp-config.json 5f3bf33e090b:/root/.claude/.mcp.json" # 验证配置 ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b cat /root/.claude/.mcp.json" | jq . ``` **3. 重启 OpenClaw** ```bash ssh lazycat "/lzcsys/bin/lzc-docker restart 5f3bf33e090b" ``` #### 测试 MCP 连接 ```bash # 测试 mcp-task-bridge 可执行性 ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b node /root/mcp-task-bridge/dist/index.js --version" # 检查配置文件 ssh lazycat "/lzcsys/bin/lzc-docker exec 5f3bf33e090b cat /root/.claude/.mcp.json" ``` #### 更新 MCP 配置 当 mcp-task-bridge 或 API token 更新时: ```bash # 1. 更新 mcp-task-bridge cd /Users/coolbuy-dev/coding/new-ai-proj/mcp-task-bridge npm run build cd /Users/coolbuy-dev/coding/new-ai-proj tar -czf - mcp-task-bridge/dist | ssh lazycat "cd /root && tar -xzf -" ssh lazycat "/lzcsys/bin/lzc-docker cp /root/mcp-task-bridge/dist 5f3bf33e090b:/root/mcp-task-bridge/" # 2. 更新配置文件(重复上面的步骤 2) # 3. 重启 OpenClaw ssh lazycat "/lzcsys/bin/lzc-docker restart 5f3bf33e090b" ``` #### 可用的 MCP 服务器 | MCP 服务器 | 环境 | API 地址 | 用途 | |-----------|------|----------|------| | ai-proj-prod | 生产 | https://ai.pipexerp.com/api/v1 | 生产数据管理 | | ai-proj-staging | 测试 | https://staging.ai.pipexerp.com/api/v1 | 测试环境验证 | #### 故障排查 | 问题 | 可能原因 | 解决方案 | |------|---------|----------| | MCP 连接失败 | node 命令不存在 | 检查容器内 node: `docker exec ... which node` | | Token 认证失败 | API token 过期或错误 | 更新 .mcp.json 中的 TASK_API_TOKEN | | 找不到模块 | node_modules 缺失 | 重新传输完整的 mcp-task-bridge | | 网络连接超时 | 容器网络问题 | 检查容器网络:`docker exec ... curl -I https://ai.pipexerp.com` | --- ## OpenClaw 特殊说明 ### MCP 协议不兼容 **重要发现**:OpenClaw **不支持**标准的 MCP (Model Context Protocol) 配置。 - ❌ 不识别 `~/.claude/.mcp.json` - ❌ 不支持 `openclaw.json` 中的 `mcpServers` 字段 - ✅ 使用自己的 **Plugins** 和 **Skills** 系统 ### OpenClaw 工具集成方式 | 集成方式 | 说明 | 适用场景 | |---------|------|----------| | **Plugins(插件)** | TypeScript 模块,在 Gateway 进程内运行 | 复杂工具、需要注册 RPC 方法 | | **Skills(技能)** | Markdown + YAML frontmatter,指导 AI 使用工具 | 调用外部 API、CLI 工具 | | **Web Tools** | 网络工具集成 | 网页操作、浏览器自动化 | ### ai-proj 在 OpenClaw 上的配置 由于 OpenClaw 不支持 MCP,ai-proj 功能通过 **Skill + REST API 调用**实现: **Skill 位置**:`/root/.claude/skills/ai-proj/SKILL.md`(容器内) **工作原理**: 1. Skill 文件提供 API 调用示例(curl 命令) 2. OpenClaw AI 根据 skill 指导执行 bash 命令 3. 直接调用 ai-proj REST API,无需 MCP bridge **示例操作**: ```bash # 在 OpenClaw 容器内执行 # 列出项目 curl -s -H "Authorization: Bearer aiproj_pk_2ecf8f8728b70afd4420af3875f4f7505c9fe8231a4771972b0f385aa1c75099" \ "https://ai.pipexerp.com/api/v1/projects?page=1&page_size=10" | jq ".data.data[] | {id, name}" # 创建任务 curl -s -X POST \ -H "Authorization: Bearer aiproj_pk_2ecf8f8728b70afd4420af3875f4f7505c9fe8231a4771972b0f385aa1c75099" \ -H "Content-Type: application/json" \ -d '{"title":"测试任务","project_id":161}' \ "https://ai.pipexerp.com/api/v1/tasks" | jq . ``` ### OpenClaw 容器 SSH 访问本机(au-dev) OpenClaw 容器可以通过 Singapore 跳板的反向隧道 SSH 到澳洲开发机(au-dev)。 **链路架构**: ``` OpenClaw容器(node@5f3bf33e090b) → ssh au-dev → ProxyJump singapore(43.134.28.147) → 反向隧道 localhost:2222 → 本机(coolbuy-dev@Coolbuy-dev.local) ``` **前置条件**: 1. 本机反向隧道服务运行中:`launchctl list | grep singapore-tunnel` 2. Singapore 端口 2222 监听中:`ssh singapore "ss -tlnp | grep :2222"` **容器内 SSH 配置**(已配置,路径 `/home/node/.ssh/`): | 文件 | 说明 | 所有者 | |------|------|--------| | `id_ed25519` | 容器 SSH 私钥 | node:node | | `id_ed25519.pub` | 公钥 (`openclaw@iamxiaoe`) | node:node | | `singpore.pem` | Singapore 跳板密钥 | node:node | | `config` | SSH 配置(含 ProxyJump) | node:node | **容器内 SSH config 内容**: ``` Host lazycat cn-bj-lazycat HostName 172.28.3.1 User root StrictHostKeyChecking no ServerAliveInterval 60 ServerAliveCountMax 3 Host singapore HostName 43.134.28.147 User ubuntu IdentityFile /home/node/.ssh/singpore.pem StrictHostKeyChecking no ServerAliveInterval 60 ServerAliveCountMax 3 Host au-dev melbourne HostName localhost Port 2222 User coolbuy-dev ProxyJump singapore StrictHostKeyChecking no ServerAliveInterval 60 ServerAliveCountMax 3 ``` **authorized_keys 配置**: | 目标机器 | 需包含的公钥 | |---------|-------------| | au-dev 本机 `~/.ssh/authorized_keys` | `openclaw@iamxiaoe` + `root@cn-bj-lazycat` | | 宿主机 `/root/.ssh/authorized_keys` | `openclaw@iamxiaoe` | **使用方式(在容器内以 node 用户执行)**: ```bash # 连接宿主机(通过 Docker 网关 172.28.3.1) ssh lazycat 'hostname && whoami' ssh cn-bj-lazycat '/lzcsys/bin/lzc-docker ps' # 连接 au-dev(通过 Singapore 反向隧道) ssh au-dev 'hostname && whoami' ssh melbourne 'cd /Users/coolbuy-dev/coding/new-ai-proj && git log --oneline -5' # 传输文件 scp au-dev:/path/to/file /tmp/ scp /tmp/file lazycat:/tmp/ ``` **重新配置(容器重建后)**: ```bash LAZYCAT="sshpass -p 'zhiyun2026' ssh -o StrictHostKeyChecking=no -o PubkeyAuthentication=no root@haiqing.heiyu.space" # 1. 复制 Singapore 密钥到容器 $LAZYCAT "/lzcsys/bin/lzc-docker cp /root/.ssh/singpore.pem 5f3bf33e090b:/home/node/.ssh/singpore.pem" # 2. 将容器公钥加入宿主机 authorized_keys $LAZYCAT "grep -q 'openclaw@iamxiaoe' ~/.ssh/authorized_keys || echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJsGNfvdmA4wCs57O9+tgbSJovDSO5esDyefVJHIoBXg openclaw@iamxiaoe' >> ~/.ssh/authorized_keys" # 3. 创建 SSH config(含宿主机 + Singapore + au-dev) $LAZYCAT "/lzcsys/bin/lzc-docker exec 5f3bf33e090b sh -c 'cat > /home/node/.ssh/config << EOF Host lazycat cn-bj-lazycat HostName 172.28.3.1 User root StrictHostKeyChecking no ServerAliveInterval 60 ServerAliveCountMax 3 Host singapore HostName 43.134.28.147 User ubuntu IdentityFile /home/node/.ssh/singpore.pem StrictHostKeyChecking no ServerAliveInterval 60 ServerAliveCountMax 3 Host au-dev melbourne HostName localhost Port 2222 User coolbuy-dev ProxyJump singapore StrictHostKeyChecking no ServerAliveInterval 60 ServerAliveCountMax 3 EOF'" # 4. 修复权限 $LAZYCAT "/lzcsys/bin/lzc-docker exec 5f3bf33e090b sh -c 'chown -R node:node /home/node/.ssh && chmod 700 /home/node/.ssh && chmod 600 /home/node/.ssh/id_ed25519 /home/node/.ssh/config /home/node/.ssh/singpore.pem'" # 5. 测试宿主机连接 $LAZYCAT "/lzcsys/bin/lzc-docker exec -u node 5f3bf33e090b ssh -o ConnectTimeout=10 lazycat 'hostname && whoami'" # 6. 测试 au-dev 连接 $LAZYCAT "/lzcsys/bin/lzc-docker exec -u node 5f3bf33e090b ssh -o ConnectTimeout=15 au-dev 'hostname && whoami'" ``` **故障排查**: | 问题 | 可能原因 | 解决方案 | |------|---------|----------| | Permission denied (publickey) to au-dev | 公钥未加入本机 authorized_keys | 将 `openclaw@iamxiaoe` 公钥加入本机 `~/.ssh/authorized_keys` | | Permission denied (publickey) to lazycat | 公钥未加入宿主机 authorized_keys | 将 `openclaw@iamxiaoe` 公钥加入宿主机 `/root/.ssh/authorized_keys` | | Connection timed out (au-dev) | 反向隧道断开 | 检查本机 `launchctl list \| grep singapore-tunnel`,重启服务 | | Could not resolve hostname | SSH config 权限错误或缺失 | 检查 `/home/node/.ssh/config` 权限为 600,所有者为 node | | ProxyJump 失败 | singpore.pem 缺失或权限错误 | 重新从宿主机复制密钥到容器 | | 容器连宿主机失败 | Docker 网关 IP 变化 | 容器内 `ip route \| grep default` 查看网关,更新 SSH config | ### 文档参考 - **OpenClaw 插件系统**:https://docs.openclaw.ai/tools/plugin.md - **OpenClaw Skills**:https://docs.openclaw.ai/tools/skills.md - **OpenClaw 配置**:https://docs.openclaw.ai/cli/config