智能SSH终端教程:Electron + AI 助手的远程运维桌面客户端
桌面 SSH 客户端有很多,但能把 AI 助手做到“可审批、可中断、可感知服务器环境”这个程度的不多。智能SSH终端(仓库名 ssh-client,包名 ssh-ai-agent)是 git.cnbugs.com 上 AI-Agent 组织的一个 Electron 桌面应用:用 Electron + React + TypeScript 写成,内置 xterm.js 终端,SSH 连接用 ssh2 库,AI 走 OpenAI 兼容接口,支持 5 个工具调用,高风险操作要你点审批卡片才能执行。本文从架构、安装、打包到 AI 运维实战完整讲一遍,并说明它和另一个名字很像的 PyQt5 项目 SSHClient 有什么区别。
一、项目简介与定位
智能SSH终端(ssh-client)的自我定位写在 package.json 的 description 里:“智能SSH终端 - 集成 AI 助手的远程运维桌面客户端”。它是一个面向 Windows 的桌面安装包(NSIS 安装器),用 Electron 打包,界面是 React + Tailwind,终端是 xterm.js,核心卖点是 AI 助手能直接操作远程主机,而不是只能聊天。
- 仓库:git.cnbugs.com/AI-Agent/ssh-client
- 包名:ssh-ai-agent,当前版本 0.1.0
- 技术栈:Electron 30 + React 18 + TypeScript + Vite + Tailwind CSS
- 终端:xterm.js(@xterm/xterm 5.5 + fit 与 web-links 插件)
- SSH:ssh2(Node.js 的 SSH2 客户端库)
- AI:openai 官方 SDK,走 OpenAI 兼容接口
- 状态与存储:zustand(前端状态)+ electron-store(本地持久化)
- 打包:electron-builder,输出 Windows NSIS 安装包
二、它和 SSHClient 是两个不同的项目
AI-Agent 组织里有两个名字很像的 SSH 客户端,很容易混淆,这里先说清楚:ssh-client(带连字符,本文主角)与 sshclient(不带连字符,PyQt5 写的那个)是两个独立的项目,代码、技术栈、AI 实现都不一样。
| 对比项 | ssh-client(本文) | sshclient(另一篇教程) |
|---|---|---|
| 技术栈 | Electron + React + TypeScript + Vite | Python + PyQt5 + paramiko |
| 终端 | xterm.js(浏览器终端组件) | PyQt5 自绘交互式终端面板 |
| SSH 库 | ssh2(Node.js) | paramiko(Python) |
| AI 接入 | openai 官方 SDK,OpenAI 兼容接口 | requests 直调 OpenAI 兼容 HTTP API |
| AI 工具数 | 5 个(执行命令、读文件、写文件、列目录、系统信息) | 5 个(执行命令、系统指标、列文件、读文件、上传文件) |
| 审批机制 | 高风险工具要用户点审批卡片,5 分钟超时自动取消 | 系统提示词要求破坏性操作先确认 |
| 监控 | 环境探测 + system_info 工具(无独立监控面板) | 实时监控面板 + 进程管理 + 趋势迷你图 |
| SFTP | 未在源码中体现文件浏览面板 | 完整的 SFTP 文件浏览 |
| 打包产物 | Windows NSIS 安装包(安装器) | PyInstaller 单文件 exe(免安装) |
| 适用平台 | 以 Windows 安装包为主 | Windows / macOS / Linux |
选哪个取决于你的偏好:喜欢 Electron + React 技术栈、想要审批卡片这种强安全控制,选 ssh-client;想要单文件免安装、带 SFTP 与实时监控面板,选 sshclient。两个项目的 AI 都能操作远程主机,思路相通,日常用法也类似。
三、功能特性
- 多会话 SSH 连接:密码与私钥两种认证,连接超时 15 秒、30 秒保活,支持多会话并存。
- xterm.js 交互终端:xterm-256color,80x24 默认尺寸,支持窗口大小调整。
- 非交互命令执行:AI 与后台任务可直接 exec 命令并取 stdout、stderr 与退出码。
- 服务器环境探测:连接后自动探测操作系统、主机名、Docker 是否安装及版本、运行中的服务、家目录内容、CPU/内存/磁盘信息,交给 AI 做上下文。
- AI 助手:OpenAI 兼容接口,流式回复,ReAct 多轮工具调用,最多 10 轮迭代。
- 5 个 AI 工具:执行命令、读文件、写文件(自动备份)、列目录、系统信息。
- 审批卡片:高风险工具(执行命令、写文件)执行前弹出审批卡片,用户确认后才执行,5 分钟超时自动取消。
- 中断:对话过程中可随时中断 AI,等待中的审批也会一并拒绝。
- 模型与会话持久化:模型配置与会话配置本地存储(electron-store),重启后还在。
- 中文安装器:NSIS 安装包中文界面,可选安装目录、桌面与开始菜单快捷方式。
四、技术架构
项目是标准的 Electron 三层结构,主进程、预加载脚本、渲染进程分工明确,类型定义集中在 src/shared/types 里,主进程与渲染进程共用:
ssh-client/
├── index.html
├── package.json # 构建、依赖、electron-builder 配置
├── pack.js
├── vite.config.ts # 渲染进程构建(Vite + React)
├── tsconfig.main.json # 主进程 TS 配置
├── tsconfig.renderer.json # 渲染进程 TS 配置
├── resources/icon.ico
├── resources/icon.png
└── src/
├── main/ # 主进程(Electron)
│ ├── index.ts
│ ├── preload.ts
│ ├── handlers/ # IPC 处理:ai / model / session / terminal
│ └── services/
│ ├── ai/ # modelProvider(模型调用)、toolRegistry(工具注册)
│ ├── ssh/ # sshManager(SSH 连接与命令执行)
│ └── storage/ # modelStore、sessionStore(本地持久化)
└── shared/types/ # 主进程与渲染进程共用的类型:ai / ipc / session
数据流是这样的:渲染进程(React 界面)通过 IPC 把“发消息给 AI”发给主进程;主进程的 aiHandler 维护每个会话的对话历史,调用 ModelProvider(openai SDK)做流式对话;模型返回工具调用时,aiHandler 查 toolRegistry 拿到工具定义,高风险工具先发审批卡片等用户确认,低风险工具直接执行;工具执行通过 sshManager.exec 在远程主机上跑命令,结果回填给模型继续 ReAct 循环,直到模型给出最终文本回复或达到 10 轮上限。
五、适用场景
- 日常运维:终端 + AI 助手在一个窗口,查日志、看状态、改配置都能用自然语言驱动。
- 排障:CPU 高、磁盘满、服务起不来,让 AI 先探测环境、再一步步排查,最后给出结论。
- 配置变更:让 AI 读配置文件、改好写回去,写文件前自动备份原文件,改错了能恢复。
- 内网 + 本地模型:模型走 OpenAI 兼容接口,可以接内网部署的兼容服务或 Ollama,数据不出内网。
- 对安全控制要求高的场景:执行命令与写文件必须点审批卡片,AI 不能悄悄执行高风险操作。
六、安装与开发运行
开发环境需要 Node.js 与 npm。先装依赖,再启动开发模式:
# 克隆仓库
git clone https://git.cnbugs.com/AI-Agent/ssh-client.git
cd ssh-client
# 安装依赖
npm install
# 开发运行:先编译主进程,再启动 Electron
npm run dev
# 带监听的开发模式:主进程改动自动重编译
npm run dev:watch
npm run dev 背后做的是 tsc -p tsconfig.main.json 编译主进程,然后 electron . 启动。开发模式下改渲染进程代码,Vite 会热更新;改主进程代码需要重新编译(dev:watch 会自动做这件事)。
七、构建与打包
# 只构建(主进程 + 渲染进程)
npm run build
# 构建并打包成目录版(不打安装包,用于调试)
npm run pack
# 构建并打 NSIS 安装包(产物在 release/ 目录)
npm run dist
打包配置在 package.json 的 build 字段里:应用 ID 是 com.ssh-ai-agent.app,产品名“智能SSH终端”,输出目录 release/,Windows 目标是 x64 的 NSIS 安装包。安装器是中文界面(zh_CN),默认非单文件安装,可以选安装目录,会创建桌面快捷方式与开始菜单快捷方式,卸载时不删除用户数据(deleteAppDataOnUninstall 为 false,配置与会话记录会保留)。
八、会话管理与终端使用
会话配置的字段(以源码 sshManager.ts 中实际使用的为准)如下:
{
"id": "a-unique-id",
"host": "192.168.1.10",
"port": 22,
"username": "root",
"authType": "password",
"password": "your-password",
"customContext": "这是一台生产环境的 Web 服务器,跑 Nginx + Docker"
}
- authType:password 或 privateKey;用私钥时 password 字段换成 privateKey(私钥内容)。
- customContext:自定义环境上下文,会拼进 AI 的系统提示词里,告诉 AI 这台服务器是干什么的,AI 回答时会结合这个背景。
- 连接参数:连接超时 15 秒,保活间隔 30 秒(keepaliveCountMax 为 3),空闲断线能及时发现;终端是 xterm-256color,默认 80 列 24 行,窗口变了会自适应调整。
连接成功后,sshManager 会自动探测服务器环境,探测命令都是只读的:
# 环境探测实际执行的命令(src/main/services/ssh/sshManager.ts)
cat /etc/os-release 2>/dev/null | head -5 # 操作系统
hostname 2>/dev/null # 主机名
docker --version 2>/dev/null # Docker 是否安装及版本
systemctl list-units --type=service --state=running 2>/dev/null | grep -oP "\S+\.service" | head -20
ls -la ~ 2>/dev/null | tail -20 # 家目录内容
nproc 2>/dev/null # CPU 核心数
free -h 2>/dev/null | head -2 # 内存
df -h / 2>/dev/null | tail -1 # 磁盘
探测结果(操作系统、主机名、Docker、运行中的服务等)会放进 AI 的系统提示词,AI 回答时会结合这台机器的实际情况,而不是泛泛而谈。
九、AI 助手配置
AI 走 OpenAI 兼容接口,配置一个模型只需要三样东西:endpoint(兼容端点地址)、model(模型名)、apiKey。支持自定义请求头,适合需要额外鉴权的自建网关。模型配置存在本地(modelStore),可以配多个模型来回切换。
{
"endpoint": "https://api.deepseek.com/v1",
"model": "deepseek-chat",
"apiKey": "sk-xxxx",
"maxTokens": 4096,
"temperature": 0.7
}
| 参数 | 默认值 | 说明 |
|---|---|---|
| endpoint | - | OpenAI 兼容接口地址,如 DeepSeek、OpenAI、通义千问兼容模式、Ollama(http://127.0.0.1:11434/v1) |
| model | - | 模型名,按 endpoint 支持的模型填 |
| apiKey | - | API Key;没填时 SDK 会用一个占位值,实际调用会失败,务必填写 |
| maxTokens | 4096 | 单次回复最大 token 数 |
| temperature | 0.7 | 采样温度,越低回答越确定,越高越发散 |
| customHeaders | - | 自定义请求头(可选) |
调用是流式(stream: true)的,AI 的回复一个字一个字往外吐,不用等整段生成完。模型必须支持 function calling(工具调用),否则 AI 只能聊天、不能操作远程主机;选模型时确认它支持工具调用。
十、AI 工具详解
AI 能调用的工具一共 5 个,全部在 src/main/services/ai/toolRegistry.ts 里注册。每个工具有风险等级:low(低风险,自动执行)、high(高风险,执行前要你点审批卡片)。
| 工具 | 作用 | 风险等级 | 实现方式 |
|---|---|---|---|
| execute_command | 在远程服务器执行 Shell 命令,返回 stdout、stderr 与退出码;支持 sudo(需预先配置 sudo 密码) | high(需审批) | sshManager.exec;输出超过 8000 字符截断;非 0 退出码会附带 exit code |
| read_file | 读取远程文件内容,支持指定行范围 | low(自动批准) | cat 全文,或 sed -n '起始行,结束行p' 按行读;输出超过 8000 字符截断 |
| write_file | 写入或创建远程文件,写之前自动备份原文件 | high(需审批) | 先 cp 原文件为 文件名.bak.时间戳,再用 base64 解码写入,避免特殊字符问题 |
| list_directory | 列出远程目录内容,支持递归 | low(自动批准) | 默认 ls -la;递归时 find 目录 -maxdepth 3,取前 200 条 |
| system_info | 获取远程系统状态:CPU、内存、磁盘、网络、进程 | low(自动批准) | cpu 用 top -bn1 | head -5;memory 用 free -h;disk 用 df -h;network 用 ss -tulnp | head -30;processes 用 ps aux --sort=-%mem | head -20 |
注意两个细节:第一,工具调用没有活跃 SSH 会话时会直接报错“没有活跃的 SSH 会话”,所以用 AI 之前要先连上目标主机;第二,write_file 的备份是 cp 原文件加时间戳后缀(如 nginx.conf.bak.1731234567),改错了可以手动 cp 回去。
十一、AI 对话与 ReAct 工作流
AI 的对话是 ReAct 循环:模型先思考要不要调工具,调完工具看结果,再决定下一步,最多循环 10 轮。每一轮的文本是流式推送到界面的,工具调用会实时展示。整个过程由主进程的 aiHandler 驱动,会话级别的对话历史按 SSH 会话分别保存,换台主机就是新的对话上下文。
系统提示词(写在 aiHandler.ts 里)给 AI 定了规矩,值得了解,因为它决定了 AI 的行为边界:
- 先用自然语言回复用户,除非用户明确要求执行操作,否则先口头回复。
- 闲聊与打招呼(你好、哈喽、hi 等)必须直接用文字回复,绝对不要调用任何工具。
- 只有当用户明确要求“执行命令”“查看”“读取”“写入”“列出”等操作时,才调用相应工具。
- 执行任何危险操作前,必须先告知用户风险。
- 修改文件前要自动备份。
- 不要执行 rm -rf / 等极端危险命令。
- 如果不确定用户意图,先询问确认。
- 命令输出可能被截断,可以用 read_file 查看完整内容。
- 使用 sudo 命令时,用户已预配置 sudo 密码,可以直接使用。
高风险工具的审批流程是这样的:AI 要调 execute_command 或 write_file 时,界面弹出审批卡片,显示要执行的命令或要编辑的文件,你点确认才执行,点取消则告诉模型“用户取消了此操作”;如果 5 分钟没人点,自动取消。执行过程中随时可以点中断,正在等待的审批也会一并拒绝。
举个完整的例子。你问:“帮我看一下这台服务器的磁盘为什么满了”:
- AI 先调 system_info(disk)看各分区使用率,发现 / 满了。
- 再调 execute_command 执行 du -sh /var/* 找大目录(这一步要你点审批卡片)。
- 定位到 /var/log 占了几十 GB 后,调 list_directory 看日志目录,再读几个大日志的头几行确认是不是日志没轮转。
- 最后汇总告诉你:根因是某个服务的日志没做 logrotate,给出清理与配置轮转的命令,等你确认后再执行。
十二、常见问题
| 问题 | 原因与处理 |
|---|---|
| AI 只聊天,不调用工具 | 模型不支持 function calling,换一个支持工具调用的模型;或你的问题没明确要求操作,AI 按提示词先口头回复,改成明确的操作指令再问 |
| 工具调用报“没有活跃的 SSH 会话” | 先连上目标主机再问 AI;AI 的工具是绑在当前 SSH 会话上的 |
| 审批卡片一直不出现 | 只有 high 风险工具(执行命令、写文件)才弹审批,读文件、列目录、系统信息是自动批准的 |
| AI 回复里内存与磁盘显示“未知” | 当前版本的环境探测虽然采集了内存与磁盘命令,但返回给 AI 的环境信息里没有解析这两个字段,提示词里会显示未知;不影响 AI 调 system_info 工具实时查询 |
| AI 调用失败 | 检查 endpoint 是否可访问、API Key 是否正确、模型名是否与 endpoint 匹配;本地 Ollama 要确认服务在跑且模型已拉取 |
| SSH 连接超时 | 连接超时 15 秒,检查主机地址、端口、防火墙与 sshd 状态;内网主机确认网络可达 |
| 打包后安装包打不开 | 确认是按 npm run dist 打的 NSIS 安装包,输出在 release/ 目录;开发调试用 npm run pack 打目录版 |
十三、安全与运维建议
- 审批卡片不要跳过:执行命令与写文件必须点确认,这是 AI 不能悄悄改生产环境的最后防线;不要为了省事去改源码绕过审批。
- 先在测试机上用:AI 的行为取决于模型与提示词,先在测试机跑顺了,确认它不会乱执行命令,再用到生产主机。
- API Key 保管:模型配置存在本地 electron-store 里,API Key 不要写进代码或提交到仓库;共用电脑时注意本地配置的访问权限。
- 私钥认证优先:生产主机优先用私钥认证,禁密码登录;私钥文件本身也要设好权限。
- 写文件有备份:write_file 会自动备份原文件,但备份在远程主机上,重要配置文件改之前自己再存一份到本地。
- 模型选择:日常排障用便宜且支持工具调用的模型即可;复杂任务再切强模型;内网与隐私场景用 Ollama 本地模型。
- 版本还很早期:当前版本是 0.1.0,功能还在演进,升级前备份好本地的模型与会话配置。
智能SSH终端把 Electron 桌面客户端与 AI Agent 结合起来:终端是 xterm.js 的完整交互体验,AI 是带审批与中断的 ReAct 助手,环境探测让 AI 一上来就知道这台机器是什么情况。它和 PyQt5 的 SSHClient 是两个不同的项目,选哪个看你的技术栈偏好与功能需求:要审批卡片与 Electron 生态,选 ssh-client;要单文件免安装、SFTP 与监控面板,选 sshclient。两个项目都在 AI-Agent 组织里,配合使用也完全没问题。






