Files
sshclient/build.spec
T
Hermes a57dbc0252 feat: SSHClient v1.0.0 - PyQt5 + paramiko 跨平台 SSH 客户端
功能:
- 多主机管理 (增删改查, 密码/私钥双认证, 导入导出)
- 远程终端 (命令执行 + 常用命令快捷栏 + 超时控制)
- SFTP 文件浏览 (上传/下载带进度, 新建/删除/重命名)
- 实时监控 (CPU/内存/磁盘/网络, 1-10秒可调刷新)
- AI Agent (OpenAI 兼容 API, 5 工具自动调用: 命令/指标/列文件/读文件/上传)

技术栈: PyQt5 + paramiko + psutil + requests + PyInstaller
打包: build_windows.bat / build.sh 一键产出 ~57MB 单文件 exe
测试: core 6/6 + UI 3/3 + E2E 6/6 全部通过
2026-07-28 21:01:31 +08:00

85 lines
2.4 KiB
RPMSpec

# -*- mode: python ; coding: utf-8 -*-
"""
PyInstaller spec for SSHClient
Windows 上构建:
pip install -r requirements.txt
pyinstaller build.spec --clean --noconfirm
产物: dist/SSHClient.exe (单文件, ~50MB)
"""
import sys
from pathlib import Path
block_cipher = None
# 项目根
ROOT = Path(SPECPATH).resolve() if 'SPECPATH' in dir() else Path('.').resolve()
# 隐式导入(PyQt5 + paramiko 有动态导入,PyInstaller 偶尔抓不全)
hiddenimports = [
"paramiko",
"cryptography",
"requests",
"psutil",
# PyQt5 子模块
"PyQt5.QtCore",
"PyQt5.QtGui",
"PyQt5.QtWidgets",
]
a = Analysis(
['main.py'],
pathex=[str(ROOT)],
binaries=[],
datas=[
# 如果后续要加资源文件(图标、配置模板),放这里
# ('resources/icon.ico', 'resources'),
],
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[
# 砍掉体积
"tkinter", "matplotlib", "numpy", "pandas", "scipy",
"PyQt5.QtBluetooth", "PyQt5.QtDBus", "PyQt5.QtDesigner",
"PyQt5.QtHelp", "PyQt5.QtLocation", "PyQt5.QtMultimedia",
"PyQt5.QtMultimediaWidgets", "PyQt5.QtNetwork", "PyQt5.QtNetworkAuth",
"PyQt5.QtNfc", "PyQt5.QtOpenGL", "PyQt5.QtPositioning",
"PyQt5.QtPrintSupport", "PyQt5.QtQml", "PyQt5.QtQuick",
"PyQt5.QtQuickWidgets", "PyQt5.QtRemoteObjects", "PyQt5.QtSensors",
"PyQt5.QtSerialPort", "PyQt5.QtSql", "PyQt5.QtSvg",
"PyQt5.QtTest", "PyQt5.QtWebChannel", "PyQt5.QtWebSockets",
"PyQt5.QtXml", "PyQt5.QtXmlPatterns",
],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
# 单文件 exe(启动稍慢但分发简单);如需启动更快可改成 COLLECT + EXE
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='SSHClient',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True, # 如果装了 UPX 会进一步压缩
upx_exclude=[],
runtime_tmpdir=None,
console=False, # GUI 模式不弹黑窗
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
# icon='resources/icon.ico' if Path('resources/icon.ico').exists() else None,
)