项目介绍
内网运维助手是一个基于FastAPI和SSH的内网服务器管理工具,通过Web界面实现对远程Linux服务器的监控和管理。该系统提供了类似Coze的聊天界面,用户可以通过自然语言指v令执行各种运维操作,如查看CPU、内存、磁盘使用情况等。
初级版本展示

技术栈选择
后端技术
- FastAPI:现代化的Python Web框架,提供自动API文档生成和类型提示
- Paramiko:Python的SSH实现,用于连接和操作远程服务器
- Uvicorn:ASGI服务器,用于运行FastAPI应用
前端技术
- HTML5:页面结构
- CSS3:页面样式,采用深色主题
- JavaScript:前端交互逻辑
系统架构
整体架构
┌─────────────────┐ HTTP ┌─────────────────┐ SSH ┌─────────────────┐
│ 前端页面 │ ───────────> │ 后端API │ ──────────> │ 远程Linux服务器 │
└─────────────────┘ <─────────── └─────────────────┘ <────────── └─────────────────┘
↑ ↑ ↑
│ │ │
│ │ │
聊天界面 命令处理 命令执行
模块划分
- 前端模块:负责用户界面展示和用户交互D
- 后端API模块:处理前端请求,执行SSH命令
- SSH客户端模块:负责与远程服务器建立连接并执行命令
- 配置模块:存储服务器连接信息
核心功能实现
1. 后端API实现
健康检查接口
@app.get("/health")
async def health():
"""
健康检查接口:
- 方便在 Coze 中配置 HTTP 工具前先测试服务是否可达。
"""
return {"status": "ok", "service": "intranet-ops-tools"}
通用SSH命令执行接口
@app.post("/tools/ssh/run")
async def tools_ssh_run(req: CommandRequest):
"""
通用 SSH 命令执行接口。
建议在 Coze 中只对白名单命令使用此接口。
"""
if not req.command.strip():
raise HTTPException(status_code=400, detail="command 不能为空")
try:
code, out, err = run_ssh_command(req.command)
except Exception as e:
raise HTTPException(status_code=500, detail=f"连接或执行失败: {e}")
return {
"success": code == 0,
"exit_code": code,
"stdout": out,
"stderr": err,
}
系统指标监控接口
@app.get("/tools/metrics/cpu")
async def tools_metrics_cpu():
"""
查看 CPU 情况:
- 可在 Coze 中配置为"cpu_check"工具。
"""
cmd = "top -b -n 1 | head -n 5"
try:
code, out, err = run_ssh_command(cmd)
except Exception as e:
raise HTTPException(status_code=500, detail=f"连接或执行失败: {e}")
return {
"success": code == 0,
"command": cmd,
"exit_code": code,
"stdout": out,
"stderr": err,
}
AI聊天接口
@app.post("/api/chat")
async def api_chat(req: ChatRequest):
"""
AI聊天接口:
- 接收聊天消息历史,根据最新消息内容决定调用哪个工具
- 将工具执行结果包装成AI回复
"""
if not req.messages:
raise HTTPException(status_code=400, detail="messages 不能为空")
# 获取最新的用户消息
latest_message = req.messages[-1]
if latest_message.role != "user":
raise HTTPException(status_code=400, detail="最新消息必须是用户消息")
user_input = latest_message.content.lower()
response = ""
try:
# 根据用户输入的关键词决定调用哪个工具
if any(keyword in user_input for keyword in ["cpu", "处理器", "cpu使用率"]):
# 调用CPU工具
cmd = "top -b -n 1 | head -n 5"
code, out, err = run_ssh_command(cmd)
response = f"我已查询服务器CPU使用情况:\n\n```\n{out}\n```"
elif any(keyword in user_input for keyword in ["内存", "mem", "memory"]):
# 调用内存工具
cmd = "free -h"
code, out, err = run_ssh_command(cmd)
response = f"我已查询服务器内存使用情况:\n\n```\n{out}\n```"
elif any(keyword in user_input for keyword in ["磁盘", "disk", "空间"]):
# 调用磁盘工具
cmd = "df -h"
code, out, err = run_ssh_command(cmd)
response = f"我已查询服务器磁盘使用情况:\n\n```\n{out}\n```"
elif any(keyword in user_input for keyword in ["负载", "load", "系统负载"]):
# 调用系统负载工具
cmd = "uptime"
code, out, err = run_ssh_command(cmd)
response = f"我已查询服务器系统负载情况:\n\n```\n{out}\n```"
elif any(keyword in user_input for keyword in ["hello", "你好", "hi"]):
response = "你好!我是内网运维助手,有什么可以帮你查询的吗?例如:\n- 查询CPU使用情况\n- 查看内存使用情况\n- 检查磁盘使用情况\n- 查看系统负载"
else:
response = "抱歉,我不太理解你的问题。你可以尝试询问关于CPU、内存、磁盘或系统负载的情况。"
except Exception as e:
response = f"抱歉,执行命令时出现错误:{e}"
return {"reply": response}
2. SSH客户端实现
import paramiko
from typing import Tuple
from config import SSH_HOST, SSH_PORT, SSH_USER, SSH_PASSWORD, SSH_TIMEOUT
def run_ssh_command(
command: str,
host: str = SSH_HOST,
port: int = SSH_PORT,
username: str = SSH_USER,
password: str = SSH_PASSWORD,
timeout: int = SSH_TIMEOUT,
) -> Tuple[int, str, str]:
"""
在远程 Linux 服务器上执行命令,返回 (exit_code, stdout, stderr)。
"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
client.connect(
hostname=host,
port=port,
username=username,
password=password,
timeout=timeout,
look_for_keys=False,
allow_agent=False,
)
stdin, stdout, stderr = client.exec_command(command)
exit_code = stdout.channel.recv_exit_status()
out = stdout.read().decode("utf-8", errors="ignore")
err = stderr.read().decode("utf-8", errors="ignore")
return exit_code, out, err
except Exception as e:
# 打印详细的错误信息
print(f"SSH连接错误: {type(e).__name__}: {e}")
print(f"连接信息: {host}:{port}, 用户名: {username}")
print(f"密码长度: {len(password)}")
raise
finally:
client.close()
3. 前端实现
页面结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>内网运维助手 Intranet Ops Assistant</title>
<!-- 样式代码 -->
</head>
<body>
<div class="header">
<h1>内网运维助手</h1>
<div class="status">
<div class="status-indicator"></div>
服务运行中
</div>
</div>
<div class="main-content">
<div class="sidebar">
<h3>快捷操作</h3>
<button class="quick-action" id="quickCpu">查看 CPU 使用情况</button>
<button class="quick-action" id="quickMemory">查看内存使用情况</button>
<button class="quick-action" id="quickDisk">查看磁盘使用情况</button>
<button class="quick-action" id="quickLoad">查看系统负载</button>
<h3>常用命令</h3>
<button class="quick-action" id="quickTop">执行 top 命令</button>
<button class="quick-action" id="quickPs">查看进程列表</button>
</div>
<div class="chat-container">
<div class="chat-header">
运维助手对话
</div>
<div class="chat-window" id="chatWindow">
<!-- 消息会插入到这里 -->
</div>
<div class="chat-input-area">
<div class="chat-input-container">
<textarea
class="chat-input"
id="chatInput"
placeholder="例如:查询一下当前 CPU 使用率"></textarea>
<button class="send-btn" id="sendBtn">发送</button>
</div>
</div>
</div>
</div>
<!-- JavaScript代码 -->
</body>
</html>
前端交互逻辑
async function sendChat(text) {
appendMessage("user", text);
showLoading();
sendBtn.disabled = true;
try {
const resp = await fetch("http://localhost:8007/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ messages }),
});
const data = await resp.json();
hideLoading();
if (!resp.ok) {
appendMessage("assistant", "请求失败:" + (data.detail || resp.status));
} else {
appendMessage("assistant", data.reply || "(无回复内容)");
}
} catch (e) {
hideLoading();
appendMessage("assistant", "调用异常:" + e);
} finally {
sendBtn.disabled = false;
}
}
配置管理
配置文件结构
"""
项目名称:内网运维助手(Intranet Ops Assistant)
说明:
- 这里只是配置信息,真实的测试服务器 IP / 账号 / 密码请按实际情况修改。
- 目前你的网段是 192.168.108.x,这里先放一个占位 IP。
"""
SSH_HOST = "192.168.1.1" # 需替换真实测试服务器 IP
SSH_PORT = 22
SSH_USER = "admin" # 需替换真实用户名
SSH_PASSWORD = "123456" # 需替换真实密码
SSH_TIMEOUT = 10
部署与使用
环境准备
安装依赖
pip install -r requirements.txt配置服务器信息
修改 config.py 文件,填入真实的服务器 IP、用户名和密码。
启动服务器
python -m uvicorn app:app –host 0.0.0.0 –port 8007访问前端页面
在浏览器中打开 http://localhost:8007/static/index.html。
使用方法
- 通过快捷操作:点击左侧的快捷操作按钮,如”查看 CPU 使用情况”。
- 通过自然语言:在聊天输入框中输入自然语言指令,如”帮我查看内存使用情况”。
- 执行常用命令:点击左侧的常用命令按钮,如”执行 top 命令”。
技术难点与解决方案
1. SSH连接认证问题
问题:SSH连接认证失败,无法执行命令。
解决方案:
- 确保配置文件中的用户名和密码正确
- 在SSH客户端代码中添加详细的错误信息输出
- 禁用密钥查找和代理,只使用密码认证
2. 跨域访问问题
问题:前端页面无法访问后端API,出现跨域错误。
解决方案:
- 在FastAPI中添加CORS中间件
- 允许所有来源的请求(生产环境中应限制为具体域名)
3. 端口占用问题
问题:启动服务器时出现端口被占用的错误。
解决方案:
- 使用不同的端口启动服务器
- 检查并关闭占用端口的进程
未来改进方向
1. 多机器管理系统
- 添加机器列表页面,显示所有可管理的服务器
- 按部门、功能或位置对服务器进行分组
- 为每台机器添加详细信息(配置、IP、负责人等)
- 在聊天界面中可以快速切换要操作的机器
2. 功能扩展
- 更多监控指标:网络流量、进程状态、服务运行状态等
- 文件管理:支持文件上传、下载、编辑等操作
- 服务管理:启动、停止、重启系统服务
- 定时任务:设置定时执行的运维任务
- 脚本管理:保存和管理常用的运维脚本
3. 安全性增强
- 用户认证:添加登录系统,支持不同用户权限
- 操作审计:记录所有操作日志
- 命令白名单:限制可执行的命令
- 加密传输:确保敏感数据的传输安全
4. 智能运维助手
- 集成Coze智能体:利用Coze的能力,实现更智能的对话交互
- 自然语言处理:支持更复杂的自然语言指令
- 故障诊断:根据系统状态自动诊断潜在问题
- 智能建议:基于系统状态提供优化建议
5. 数据可视化
- 实时监控仪表盘:展示关键系统指标的实时变化
- 历史趋势分析:查看系统性能的历史趋势
- 异常检测:自动标记异常的系统状态
- 报表生成:定期生成系统状态报表
总结
内网运维助手系统是一个轻量级的服务器管理工具,通过Web界面实现对远程Linux服务器的监控和管理。系统采用FastAPI作为后端框架,Paramiko实现SSH连接,前端采用HTML5、CSS3和JavaScript构建类似Coze的聊天界面。
该系统的主要特点包括:
- 简单易用:通过自然语言指令执行运维操作
- 功能丰富:支持查看CPU、内存、磁盘等系统指标
- 安全可靠:通过SSH协议连接服务器,确保操作安全
- 可扩展性:模块化设计,便于添加新功能
- 跨平台:可以在任何有浏览器的设备上使用
未来,我们将继续完善系统功能,添加多机器管理、智能运维、数据可视化等特性,使其成为一个更加全面和智能的内网运维工具。