一、项目简介
在中小型团队的日常运维工作中,服务器资产、巡检脚本、部署命令和执行记录经常分散在 Excel、聊天记录或个人终端历史中。这样做虽然初期简单,但随着服务器数量增加,会逐渐出现以下问题:
- 服务器信息不统一,环境、账号、端口等资料难以追踪;
- 常用命令依赖个人经验,脚本复用率低;
- 运维任务执行后缺少审计记录;
- 新人接手项目时,不清楚有哪些机器、哪些脚本、哪些任务执行过。
本文实现一个轻量级的 Python 自动化运维工具 ,采用 FastAPI + SQLite + 原生 HTML/CSS/JavaScript 构建一个完整全栈项目。系统支持服务器资产管理、运维脚本管理、任务执行、任务历史记录和仪表盘统计。为了保证演示安全,项目中的命令执行器采用"模拟执行"方式,仅允许 date、df -h、uptime、free -m 等安全命令;真实生产环境可扩展为 SSH、Paramiko、Ansible Runner 或 Kubernetes API。
项目源码目录:
text
project/
├── backend/
│ ├── app/
│ │ ├── main.py
│ │ ├── database.py
│ │ ├── models.py
│ │ ├── schemas.py
│ │ └── crud.py
│ └── requirements.txt
├── frontend/
│ ├── index.html
│ ├── style.css
│ └── app.js
└── README.md
二、技术栈
| 层次 | 技术 | 说明 |
|---|---|---|
| 后端框架 | FastAPI | 提供 RESTful API,自动生成 Swagger 文档 |
| 数据库 | SQLite | 轻量、无需额外安装数据库服务,适合教学与原型开发 |
| ORM | SQLAlchemy | 定义数据模型并完成数据库 CRUD |
| 数据校验 | Pydantic | 定义请求参数和响应结构 |
| 前端 | HTML/CSS/JavaScript | 不依赖 Vue/React,便于初学者理解全栈交互 |
| 接口通信 | Fetch API | 前端调用后端 REST 接口 |
| 部署运行 | Uvicorn | FastAPI ASGI 运行服务器 |
三、系统架构
系统采用经典前后端分离架构:
text
浏览器前端
│ Fetch API
▼
FastAPI 路由层 main.py
│
├── schemas.py:请求/响应数据校验
├── crud.py:业务逻辑与任务执行
├── models.py:SQLAlchemy ORM 模型
▼
SQLite 数据库 ops_tool.db
前端负责表单录入、列表展示和任务触发;后端负责接口暴露、数据校验、业务处理和数据库持久化。运行任务时,后端会读取目标服务器和脚本内容,生成一条任务记录,然后返回模拟执行结果。
四、功能模块
1. 仪表盘统计
仪表盘展示服务器数量、脚本数量、任务数量、成功任务数量和失败任务数量,帮助运维人员快速掌握平台状态。
2. 服务器资产管理
支持添加服务器资产,包括名称、主机地址、SSH 端口、用户名、环境和备注。执行成功的任务会把服务器状态更新为 online。
3. 运维脚本管理
支持添加脚本名称、脚本分类、脚本内容和启用状态。示例项目中支持的安全命令包括:
text
date
df -h
uptime
free -m
4. 任务执行
用户选择一台服务器和一个脚本,点击"立即执行"后,系统创建任务记录并返回执行结果。演示环境不会真正执行系统命令,而是根据白名单命令返回模拟输出。
5. 任务历史审计
每次任务执行都会保存状态、输出、开始时间和结束时间,为后续排查问题提供依据。
五、数据库/数据模型设计
本项目包含三张核心表:
servers 表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | Integer | 主键 |
| name | String | 服务器名称,唯一 |
| host | String | 服务器地址 |
| port | Integer | SSH 端口 |
| username | String | 登录用户名 |
| environment | String | 环境,如 production、staging |
| status | String | 状态,如 unknown、online |
| remark | Text | 备注 |
| created_at | DateTime | 创建时间 |
scripts 表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | Integer | 主键 |
| name | String | 脚本名称,唯一 |
| category | String | 分类 |
| content | Text | 脚本内容或命令 |
| enabled | Boolean | 是否启用 |
| created_at | DateTime | 创建时间 |
ops_jobs 表
| 字段 | 类型 | 说明 |
|---|---|---|
| id | Integer | 主键 |
| server_id | Integer | 服务器 ID |
| script_id | Integer | 脚本 ID |
| status | String | pending、running、success、failed |
| output | Text | 执行输出 |
| started_at | DateTime | 开始时间 |
| finished_at | DateTime | 结束时间 |
SQLAlchemy 模型片段如下:
python
class Server(Base):
__tablename__ = "servers"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(80), nullable=False, unique=True, index=True)
host = Column(String(120), nullable=False)
port = Column(Integer, default=22)
username = Column(String(80), default="root")
environment = Column(String(40), default="production")
status = Column(String(20), default="unknown")
六、后端接口设计
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/dashboard |
获取仪表盘统计 |
| GET | /api/servers |
获取服务器列表 |
| POST | /api/servers |
新增服务器 |
| PUT | /api/servers/{server_id} |
更新服务器 |
| DELETE | /api/servers/{server_id} |
删除服务器 |
| GET | /api/scripts |
获取脚本列表 |
| POST | /api/scripts |
新增脚本 |
| PUT | /api/scripts/{script_id} |
更新脚本 |
| DELETE | /api/scripts/{script_id} |
删除脚本 |
| POST | /api/jobs |
执行任务 |
| GET | /api/jobs |
获取任务历史 |
FastAPI 路由示例:
python
@app.post("/api/jobs", response_model=schemas.JobOut)
def run_job(data: schemas.JobCreate, db: Session = Depends(get_db)):
job = crud.run_job(db, data)
if not job:
raise HTTPException(status_code=400, detail="服务器或脚本不存在,或脚本已禁用")
return job
七、前端页面设计
前端使用一个单页 index.html 完成全部功能,页面分为四个区域:
- 顶部标题栏:展示项目名称和刷新按钮;
- 统计卡片:展示服务器、脚本、任务、成功、失败数量;
- 服务器与脚本维护区域:左侧表单新增,右侧列表展示;
- 任务执行与历史区域:选择服务器和脚本后触发执行,并展示执行输出。
前端通过 Fetch API 调用后端:
javascript
async function request(path, options = {}) {
const response = await fetch(`${API_BASE}${path}`, {
headers: { 'Content-Type': 'application/json' },
...options,
});
if (!response.ok) {
const error = await response.json().catch(() => ({ detail: '请求失败' }));
throw new Error(error.detail || '请求失败');
}
return response.json();
}
八、核心代码讲解
1. 数据库连接
database.py 中创建 SQLite 连接,并通过 get_db 为每个请求提供数据库会话:
python
engine = create_engine(
SQLALCHEMY_DATABASE_URL,
connect_args={"check_same_thread": False},
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
这种方式适合 FastAPI + SQLite 的教学场景。生产环境可以改为 MySQL、PostgreSQL,并使用连接池参数优化性能。
2. 任务执行逻辑
crud.py 中的 run_job 是系统核心。它先校验服务器和脚本是否存在,再创建任务记录,最后根据脚本内容返回执行结果:
python
SAFE_COMMANDS = {
"date": "模拟执行 date:2026-06-03 10:00:00",
"df -h": "模拟执行 df -h:/dev/sda1 40G 18G 22G 45% /",
"uptime": "模拟执行 uptime:10:00:00 up 12 days, load average: 0.15, 0.10, 0.08",
"free -m": "模拟执行 free -m:Mem: 4096 total, 1024 used, 3072 free",
}
如果脚本命令在白名单中,任务状态为 success;否则状态为 failed,并提示演示环境不允许执行危险命令。这个设计体现了自动化运维项目必须重视权限边界和执行安全。
3. 前端刷新逻辑
每次新增服务器、添加脚本或执行任务后,前端调用 refreshAll() 同步刷新仪表盘、资产列表、脚本列表和任务历史:
javascript
async function refreshAll() {
await Promise.all([loadDashboard(), loadServers(), loadScripts(), loadJobs()]);
}
这样可以保证用户看到的数据始终与数据库一致。
九、部署与运行步骤
1. 启动后端
bash
cd project/backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --host 127.0.0.1 --port 8000
启动成功后访问:
text
http://127.0.0.1:8000/docs
可以看到 FastAPI 自动生成的接口文档。
2. 打开前端
直接用浏览器打开:
text
project/frontend/index.html
如果浏览器限制本地文件请求,也可以在 frontend 目录启动一个静态服务:
bash
cd project/frontend
python3 -m http.server 8080
然后访问:
text
http://127.0.0.1:8080
3. 初始化使用示例
- 新增服务器:
prod-web-01 / 192.168.1.10 / root / production; - 新增脚本:
检查磁盘 / df -h; - 在执行任务区域选择服务器和脚本;
- 点击"立即执行";
- 在任务历史中查看输出结果。
十、项目扩展方向
当前项目是一个教学版全栈系统,可以继续扩展:
- 接入 Paramiko,通过 SSH 在远程服务器执行命令;
- 接入 Ansible Runner,实现批量主机任务;
- 增加用户登录、角色权限和操作审计;
- 增加定时任务,如每天巡检磁盘、内存、负载;
- 增加 WebSocket,实时推送任务日志;
- 增加服务器分组、标签和搜索功能;
- 将 SQLite 替换为 PostgreSQL,并使用 Docker Compose 部署。
十一、项目总结
本文完成了一个围绕"Python 自动化运维工具开发"的全栈项目。后端使用 FastAPI 提供接口,SQLite 负责数据持久化,SQLAlchemy 管理数据模型,Pydantic 完成请求响应校验;前端使用原生 HTML/CSS/JavaScript 实现服务器管理、脚本管理、任务执行和任务历史展示。
这个项目虽然轻量,但已经具备自动化运维平台的核心雏形:资产管理、脚本复用、任务执行、结果审计和统计概览。读者可以在此基础上进一步接入真实 SSH 执行器、权限系统和定时调度模块,逐步演进为企业内部可用的 DevOps 工具平台。