Python基于PyQt5開(kāi)發(fā)一個(gè)SSH遠(yuǎn)程登錄終端工具
基于 PyQt5 + Paramiko 實(shí)現(xiàn)的 SSH 遠(yuǎn)程登錄終端工具,包含服務(wù)器管理、多標(biāo)簽終端與遠(yuǎn)程文件瀏覽/下載。
效果如下:

環(huán)境要求
- Python >= 3.9
- Windows 10/11
功能特性
服務(wù)器管理
- 添加、編輯、刪除服務(wù)器配置
- 服務(wù)器分組管理
- 配置信息持久化保存
SSH 連接
- 密碼認(rèn)證
- 密鑰文件認(rèn)證
- 每次詢問(wèn)(ask)
- 連接測(cè)試功能
終端界面
- 交互式 SSH 終端
- 命令輸入與執(zhí)行
- 實(shí)時(shí)輸出顯示
遠(yuǎn)程文件瀏覽器
- 瀏覽遠(yuǎn)程服務(wù)器文件系統(tǒng)
- 查看文件和目錄信息
- 下載文件
多標(biāo)簽頁(yè)支持
- 同時(shí)連接多個(gè)服務(wù)器
- 標(biāo)簽頁(yè)管理
安裝依賴
pip install -r requirements.txt
快速開(kāi)始(Windows)
安裝依賴(見(jiàn)上)。
啟動(dòng)程序(二選一):
- 方式 A:雙擊運(yùn)行
run.bat - 方式 B:命令行運(yùn)行:
python RemoteTerminal_python.py
使用方法
添加服務(wù)器
- 點(diǎn)擊“添加服務(wù)器”按鈕
- 填寫(xiě)服務(wù)器信息(地址、端口、用戶名、密碼等)
- 選擇認(rèn)證方式(密碼/密鑰/每次詢問(wèn))
- 點(diǎn)擊“保存”
連接服務(wù)器
- 雙擊服務(wù)器列表中的服務(wù)器
- 或右鍵點(diǎn)擊選擇“連接”
使用終端
- 在終端標(biāo)簽頁(yè)中輸入命令
- 按 Enter 或點(diǎn)擊“發(fā)送”按鈕執(zhí)行命令
瀏覽文件
- 在左側(cè)文件瀏覽器中瀏覽遠(yuǎn)程文件系統(tǒng)
- 雙擊目錄進(jìn)入
- 右鍵文件可下載
SSH 核心代碼說(shuō)明
連接線程:SSHConnection
- 繼承自
QThread,在獨(dú)立線程中維護(hù)與遠(yuǎn)程主機(jī)的 SSH 會(huì)話,避免阻塞 GUI。 - 在
run()中使用paramiko.SSHClient創(chuàng)建連接,根據(jù)是否配置密鑰文件選擇:- 密鑰登錄:
client.connect(..., key_filename=key_file, timeout=10) - 密碼登錄:
client.connect(..., password=password, timeout=10)
- 密鑰登錄:
- 通過(guò)
client.invoke_shell(term='xterm-256color')創(chuàng)建交互式 SSH shell 通道channel。 - 持續(xù)輪詢
channel.recv_ready(),有數(shù)據(jù)時(shí)調(diào)用channel.recv(4096)并解碼為字符串,通過(guò)output_received信號(hào)異步發(fā)送給界面。 - 出現(xiàn)異常時(shí),通過(guò)
error_occurred信號(hào)上報(bào)錯(cuò)誤,在finally中統(tǒng)一發(fā)出connection_closed信號(hào),便于界面做收尾處理。
命令發(fā)送與關(guān)閉
send_command(command)會(huì)在通道仍然可用時(shí)執(zhí)行self.channel.send(command),通常由終端輸入框在用戶按下 Enter 時(shí)調(diào)用(會(huì)附帶換行符)。close()方法將running置為False,并關(guān)閉底層channel與client,讓線程循環(huán)自然退出。
連接測(cè)試
- 在服務(wù)器配置對(duì)話框中,
test_connection()會(huì)臨時(shí)創(chuàng)建一個(gè)paramiko.SSHClient,用與實(shí)際連接相同的參數(shù)執(zhí)行一次connect/close。 - 成功則彈出“連接測(cè)試成功”提示,失敗則捕獲異常并展示錯(cuò)誤信息,便于提前發(fā)現(xiàn)賬號(hào)或網(wǎng)絡(luò)問(wèn)題。
示例核心代碼:
import os
import time
import paramiko
from PyQt5.QtCore import QThread, pyqtSignal
class SSHConnection(QThread):
"""SSH 連接線程"""
output_received = pyqtSignal(str)
error_occurred = pyqtSignal(str)
connection_closed = pyqtSignal()
def __init__(self, host, port, username, password=None, key_file=None):
super().__init__()
self.host = host
self.port = port
self.username = username
self.password = password
self.key_file = key_file
self.client = None
self.channel = None
self.running = False
def run(self):
try:
self.client = paramiko.SSHClient()
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 連接服務(wù)器(密鑰優(yōu)先,其次密碼)
if self.key_file and os.path.exists(self.key_file):
self.client.connect(
hostname=self.host,
port=self.port,
username=self.username,
key_filename=self.key_file,
timeout=10,
)
else:
self.client.connect(
hostname=self.host,
port=self.port,
username=self.username,
password=self.password,
timeout=10,
)
# 創(chuàng)建交互式 shell
self.channel = self.client.invoke_shell(term="xterm-256color")
self.running = True
# 持續(xù)讀取遠(yuǎn)程輸出
while self.running:
if self.channel.recv_ready():
data = self.channel.recv(4096).decode("utf-8", errors="ignore")
if data:
self.output_received.emit(data)
elif self.channel.exit_status_ready():
break
time.sleep(0.1)
except Exception as e:
self.error_occurred.emit(str(e))
finally:
self.connection_closed.emit()
def send_command(self, command: str):
"""發(fā)送命令到遠(yuǎn)程 shell"""
if self.channel and self.running:
self.channel.send(command)
def close(self):
"""關(guān)閉連接"""
self.running = False
if self.channel:
self.channel.close()
if self.client:
self.client.close()
配置說(shuō)明(servers.json)
服務(wù)器配置保存在 servers.json 文件中,包含以下字段:
name: 服務(wù)器名稱host: 服務(wù)器地址port: SSH 端口(默認(rèn) 22)username: 登錄用戶名password: 登錄密碼(密碼認(rèn)證時(shí))key_file: SSH 密鑰文件路徑(密鑰認(rèn)證時(shí))group: 服務(wù)器分組auth_method: 認(rèn)證方式(password/key/ask)notes: 備注信息
安全提示:
servers.json可能包含密碼等敏感信息,建議僅在本機(jī)保存,不要隨意分享/上傳。- 當(dāng)前實(shí)現(xiàn)會(huì)在首次連接時(shí) 自動(dòng)接受主機(jī)密鑰(Paramiko
AutoAddPolicy)。在生產(chǎn)環(huán)境建議改為校驗(yàn)指紋/已知主機(jī)列表,避免中間人風(fēng)險(xiǎn)。 - 若使用密鑰文件,建議使用 絕對(duì)路徑,并確保密鑰權(quán)限設(shè)置合理。
打包(PyInstaller)
推薦直接使用倉(cāng)庫(kù)內(nèi)的 RemoteTerminalPython.spec:
pyinstaller --noconfirm --clean RemoteTerminalPython.spec
如果要用命令行參數(shù)方式(Windows 示例,注意 --add-data 分隔符為 ;):
pyinstaller --noconfirm --clean --windowed --onedir --name "RemoteTerminalPython" --add-data "servers.json;." RemoteTerminal_python.py
依賴庫(kù)
- PyQt5: GUI 界面框架
- paramiko: SSH 客戶端庫(kù)
以上就是Python基于PyQt5開(kāi)發(fā)一個(gè)SSH遠(yuǎn)程登錄終端工具的詳細(xì)內(nèi)容,更多關(guān)于Python SSH遠(yuǎn)程登錄的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python+os根據(jù)文件名自動(dòng)生成文本
這篇文章主要為大家詳細(xì)介紹了python+os根據(jù)文件名自動(dòng)生成文本,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03
matplotlib畫(huà)圖之修改坐標(biāo)軸刻度問(wèn)題
這篇文章主要介紹了matplotlib畫(huà)圖之修改坐標(biāo)軸刻度問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
關(guān)于Python排序問(wèn)題(冒泡/選擇/插入)
這篇文章主要介紹了關(guān)于Python排序問(wèn)題(冒泡/選擇/插入),學(xué)過(guò)C語(yǔ)言肯定接觸過(guò)排序問(wèn)題,我們最常用的也就是冒泡排序、選擇排序、插入排序,需要的朋友可以參考下2023-04-04
淺談Python_Openpyxl使用(最全總結(jié))
這篇文章主要介紹了淺談Python_Openpyxl使用(最全總結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Python?Flask?JinJa2?語(yǔ)法使用示例詳解
這篇文章主要為大家介紹了Python?Flask?JinJa2?語(yǔ)法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
python numpy數(shù)組中的復(fù)制知識(shí)解析
這篇文章主要介紹了python numpy數(shù)組中的復(fù)制知識(shí)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
Django自關(guān)聯(lián)實(shí)現(xiàn)多級(jí)聯(lián)動(dòng)查詢實(shí)例
這篇文章主要介紹了Django自關(guān)聯(lián)實(shí)現(xiàn)多級(jí)聯(lián)動(dòng)查詢實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
python 鏈接sqlserver 寫(xiě)接口實(shí)例
這篇文章主要介紹了python 鏈接sqlserver 寫(xiě)接口實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03

