智能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 + VitePython + 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 会用一个占位值,实际调用会失败,务必填写
maxTokens4096单次回复最大 token 数
temperature0.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 组织里,配合使用也完全没问题。

发表回复

后才能评论