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 全部通过
This commit is contained in:
+84
@@ -0,0 +1,84 @@
|
||||
# -*- 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,
|
||||
)
|
||||
Reference in New Issue
Block a user