DevOps Toolkit:用 PySide6 打造一站式 Windows 运维桌面工具集
DevOps Toolkit:用 PySide6 打造一站式 Windows 运维桌面工具集
一个把「SSH 部署、Git 管理、Maven 构建、打包发布、JSON 处理」收敛到本地桌面的工具箱实践笔记。
一、为什么要做这个工具
日复一日,本地开发者的运维动作其实高度重复:
- 打开终端连上服务器,备份、传 jar、重启 Docker,盯着日志等健康检查;
- 维护七八个 Git 仓库,挨个
git pull看有没有人推了代码; - 多个 Maven 工程批量
clean package; - 前端工程
pnpm build后压缩成 zip 发给别人。
这些动作散落在不同脚本和文档里,新同事上手要配一整套环境,老同事也经常记错远程目录或容器名。于是我决定把它们收敛到一个本地桌面应用里 —— 这就是 DevOps Toolkit。
它选择桌面形态而非 Web,原因很直接:它是「本地工具箱」,直接调用本机的 git / maven / pnpm,免部署、配置落地本地、不上传任何数据,打开即用。
二、技术选型
| 能力 | 选型 |
|---|---|
| GUI 框架 | PySide6(Qt 官方 Python 绑定) |
| UI 风格 | qfluentwidgets(微软 Fluent 风格控件) |
| 远程连接 | paramiko(SSH / SFTP) |
| 密码加密 | cryptography(Fernet 对称加密) |
| 打包 | PyInstaller |
整个项目分层非常克制:
app/
├── core/ # 引擎层:部署/ Git/ Maven/ 打包/ 配置/ 加密
├── models/ # 数据模型:Environment / Project / PipelineStep
├── pages/ # 页面:仪表盘 / 部署 / Git / Maven / 打包 / 设置
├── widgets/ # 通用组件:流水线、日志、环境选择、项目卡片
├── styles.py # 主题引擎(设计令牌 + QSS + QPalette)
└── main_window.py
三、架构亮点:三种异步模型并存
这是整个项目里最值得分享的设计决策。桌面应用的命门是「不能卡 UI」,而不同的运维动作天然适合不同的并发模型,所以核心层没有强行统一,而是按场景各取所长:
-
DeployEngine ——
threading.Thread
部署要管理「多项目并行 + 每项目独立 SSH 连接 + 可随时取消」,用线程最直观。关键是每个项目一份隔离上下文_ProjectCtx:@dataclass class _ProjectCtx: project: Project steps: List[PipelineStep] = field(default_factory=list) cancelled: threading.Event = field(default_factory=threading.Event) ssh_client: Optional[paramiko.SSHClient] = None # paramiko 非线程安全,必须每项目独立 sftp_client: Optional[paramiko.SFTPClient] = None run_id: int = 0 # 用于取消后过滤「迟到信号」多项目通过
threading.Semaphore控制并发度(默认按 CPU 核数推导),单项目失败不影响其他项目。run_id的设计很巧妙:取消后立刻重新部署会启动新线程,旧线程发出的「完成」信号带旧run_id,UI 据此直接丢弃,避免界面被过期状态污染。 -
GitEngine / MavenEngine / ProcessRunner ——
QProcess
这类动作本质是「启动一个长命令、实时捕获 stdout」,用QProcess比自己管理线程更自然,也天然契合 Qt 事件循环。 -
信号路由
后台线程通过Signal把日志和步骤状态推给 UI,信号里携带project_key,UI 再路由到对应的PipelineWidget/LogWidget,多个项目并行时互不串台。
四、响应式配置:单例 + Qt Signal 桥
ConfigManager 是经典的单例(__new__ + 线程锁),但它的巧思在于:它是一个纯 Python 对象,却能把配置变更「广播」成 Qt 信号,驱动所有页面自动刷新。
class _ConfigNotifier(QObject):
environments_changed = Signal()
projects_changed = Signal()
config_changed = Signal(str) # "environments" / "projects" / "settings"
class ConfigManager:
_instance = None
_lock = threading.Lock()
def __new__(cls):
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
当用户在「设置页」增删环境或项目,只需:
ConfigManager().notifier.config_changed.connect(_on_config_changed)
部署页、Git 页、仪表盘就会自动同步,无需手动刷新。配置落盘用原子写入(tempfile + os.replace),即使写入中途崩溃也不会损坏 JSON。
五、流水线状态机与可视化
部署被抽象成一组 PipelineStep,状态机清晰:
PENDING → RUNNING → SUCCESS / FAILURE / SKIPPED / CANCELLED
后端流水线:git pull → Maven clean → Maven package → 建立 SSH → 备份 → 上传 jar → 重启容器 + 健康检查;
前端流水线:git pull → pnpm 构建 → 建立 SSH → 备份 → 上传 dist。
任一步骤失败会自动把后续步骤标记为 SKIPPED 并终止,UI 上的 PipelineWidget 用颜色 + 图标实时反映每个步骤的状态。
六、安全设计:机器特征绑定的密码加密
environments.json 里存的是 SSH 密码,明文落盘显然不安全。项目用 cryptography 做了与机器绑定的对称加密:
def _derive_key() -> bytes:
user = getpass.getuser()
host = socket.gethostname()
install_path = os.path.dirname(...) # 安装路径
machine_id = f"{user}@{host}:{install_path}"
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32,
salt=_SALT, iterations=100_000)
return base64.urlsafe_b64encode(kdf.derive(machine_id.encode()))
密钥从「用户名 + 主机名 + 安装路径」派生,所以配置文件被复制到别的机器就无法解密 —— 这本身就是一项安全特性。同时兼容旧版明文(无 enc: 前缀原样返回),平滑升级。
七、部署流水线的健壮性细节
这些细节决定了工具「能不能真的日用」:
- 远程备份:
tar打包时排除config / logs / backups,保留最近 N 份并自动清理旧的; - 上传校验:jar 上传后对比本地 / 远程文件大小,不一致给黄色告警;
- 前端保护:扁平解压
dist内容(不创建dist层),且备份并恢复服务器上的platform-config.json,避免被覆盖; - Docker 健康检查:重启后等待启动,再检查容器状态、进程列表、最近日志,并在日志里扫描
Exception / Error等关键词给出潜在告警; - 取消机制:
threading.Event置位 + 关闭 SSH 连接 +terminate()子进程,三管齐下保证能干净停下。
八、主题系统
主题用「设计令牌 + QSS 模板 + QPalette」实现,默认暗色。页面只要实现 apply_theme 方法,就能被主窗口以鸭子类型自动接入主题切换:
for _page in pages.values():
_apply = getattr(_page, "apply_theme", None)
if callable(_apply):
window.theme_changed.connect(_apply)
九、打包与分发
PyInstaller 打包最大的坑是 qfluentwidgets / paramiko 有大量动态 / 延迟导入,必须显式收集子模块,否则 exe 启动即 ModuleNotFoundError:
hiddenimports = (
collect_submodules('qfluentwidgets') +
collect_submodules('paramiko') +
collect_submodules('cryptography') + [...]
)
exe = EXE(..., name='DevOpsToolkit', console=False, upx=True)
打包后配置文件落到 %APPDATA%/DevOpsToolkit/configs,首次运行自动从内置资源复制默认配置(且不覆盖已有配置)。一个 build_exe.py 脚本封装了清理旧目录、依赖自检、可选 UPX 压缩,一行 python build_exe.py 即可产出独立 exe。
十、写在最后
DevOps Toolkit 不是一个试图替代 CI/CD 的大型系统,它解决的是**「开发者自己机器上那一摊重复运维活」**。它的价值在于:
- 把散落的动作收敛成可视化流水线,错误一眼可见;
- 多项目并行部署,省下大量等待时间;
- 配置本地、密码加密、不上云,安全边界清晰。
如果你也厌倦了在终端里复制粘贴远程目录和容器名,不妨照着这个架构思路,给自己也攒一个顺手的小工具箱。
项目已开源(MIT License),技术栈:PySide6 + qfluentwidgets + paramiko + cryptography。
源码:
– https://gitee.com/gtnotgod/local-toolbox.git
项目截图:首页

项目截图:部署批处理发布到服务器

项目截图:本地多项目的GIT管理,批量拉取,分支合并

项目截图:本地多项目的Maven后端管理;多项目的常见Maven批处理Clean/Package/Deploy/Reload/强制更新依赖


项目截图:本地多项目打包管理;批量打包前后端

项目截图:常见工具JSON和Base64

项目截图:项目基础设置

项目截图:批处理项目部署服务器环境设置

项目截图:多项目本地管理

项目截图:项目使用的本地基础设施环境

项目截图:项目的关于

主题切换::

更多推荐
所有评论(0)