使用Python打造SSH连接的GUI工具(paramiko+tkinter)

前言

本项目开发一个综合性的ssh远程服务器管理工具,用户可添加多台服务器信息,可通过新建、删除、修改来管理服务器信息。具有监控服务器的cpu、内存、进程的功能。可以执行交互性指令,通过vim工具来实现对于文件的编辑。实现了对于文件的上传和下载功能,使用户轻松的管理文件,并提供了批量下载日志文件的功能,以实现对于日志的批量收集,更好的掌握服务器的日志信息。

项目概述

本项目旨在创建一个用户友好的SSH客户端,它集成了服务器连接、命令执行、文件传输等功能。通过图形界面,用户可以轻松地管理多个服务器,执行远程命令,以及上传和下载文件。(注意:本项目使用vim需要先touch创建一个文件,vim一个文件时会自动打开本地的默认文本编辑器,保存会自动 同步内容到Linux中)

项目展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用的技术

Python:版本为3.11。
paramiko:用于SSH连接和SFTP文件传输的Python库。
tkinter:Python的标准GUI库,用于构建用户界面。

功能特点

服务器列表管理:支持服务器信息的增删改查。
SSH连接与命令执行:通过图形界面连接服务器并执行命令。
文件传输:实现文件的上传和下载。
实时监控:实时显示服务器的CPU、内存、磁盘和网络状态。

代码

MySSH 类

MySSH 类负责管理SSH连接和执行相关操作。

# -*- ecoding: utf-8 -*-
# @ModuleName: project
# @Function: 
# @Author: liweijia
# @Time: 2024/5/22 15:21
# #!/usr/bin/python
import os
import re

import paramiko
import tkinter as tk
from tkinter import messagebox
from tkinter import filedialog
import ttkbootstrap as ttk
import json


class MySSH:
    def __init__(self):

        self.servers = []  # 读取server.json。  选择/添加/删除
        self.server = {
   }
        # 服务器是否连接
        self.connected = False
        # 用来保存当前路径
        self.path = ""
        # 实例化并且建立一个sshclient对象
        self.ssh = paramiko.SSHClient()
        # 将信任的主机自动加入到host_allow列表,需放在connect方法前面
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)
        self.cpu_percent = 0.0
        self.memory_percent = 0.0
        self.file_name = None
        self.processes = []
        self.load_server()

        # 此线程用于vim文件编辑功能
        t = threading.Thread(target=self.file_save)
        t.start()

    def load_server(self):
        # 打开文件
        with open("server.json", encoding='utf-8') as fp:
            self.servers = json.load(fp)

    def connect(self):
        # 调用connect方法连接服务器
        self.connected = None
        try:
            # 通过用户名和密码进行连接
            self.ssh.connect(hostname=self.server["ip"], port=self.server["port"], username=self.server["username"],
                             password=self.server["password"])
            print(f'连接到服务器{
     self.server["ip"]}成功!!!')
            self.connected = True

            # 创建一个交互式的shell窗口
            self.chan = self.ssh.invoke_shell()
            self.chan.settimeout(1000)
            # 刚进入linux服务器等待一会,否则直接通过chan.recv获取的信息不完整
            time.sleep(0.6)
            self.endSymbol = ['# ', '$ ', '> ', '* ']  # 设置我们定义的结束符

        except Exception as e:
            self.connected = False
            print(f"连接到服务器【{
     self.server['ip']}】失败,失败的原因:{
     e}")

    def transport(self, server_path, local_path, num):

        '''
        文件上传 如果传入num==1文件上传 num==0文件下载
        server_path:服务器路径
        local_path:本地路径
        num:1为上传操作 0为下载操作
        '''

        sftp = self.ssh.open_sftp()  # 初始化sftp
        file_name = ''
        pattern = r'[^\\\/]+(?=\.[^\\\/.]*$|$)'  # 正则表达式用于将文件名称从路径里抽取出来

        if num == 1:
            try:
                file_name = re.search(pattern, local_path).group(
                    0)
            except Exception as e:
                print(e)
            print(f"{
     server_path}/{
     file_name}")
            sftp.put(local_path, f"{
     server_path}/{
     file_name}")

        if num == 0:
            try:
                file_name = re.search(pattern, server_path).group(
                    0)
            except Exception as e:
                print(e)

            print(f'{
     server_path}')
            sftp.get(server_path, f'{
     local_path}/{
     file_name}')

    def more_transport(self, local_dir):
        sftp = self.ssh.open_sftp()  # 初始化sftp
        try:
            # 获取服务器的日志文件
            stdin, stdout, stderr = self.ssh.exec_command("ls /var/log/*.log | xargs -I {} basename '{}'")
            file_list = stdout.read().decode("utf-8").strip().split('\n')
            # 遍历文件列表并下载
            for file_name in file_list:
                remote_path = f"/var/log/{
     file_name}"
                local_path = f"{
     local_dir}/{
     file_name}"
                print(f"Downloading {
     remote_path} to {
     local_path}")
                sftp.get(remote_path, local_path)
        finally:
            # 关闭SFTP和SSH连接
            sftp.close()


    def runCommand(self, chanT, command, endSymbol):
        # 指令后加 '\n' 表示换行
        chanT.send(command + '\n')
        results = ''
        while True:

            result = chanT.recv(1024).decode('utf-8')
            if 'Last login:' in result: # 如果指令里包含Last...字段就再发送一次请求
                result = chanT.recv(1024).decode('utf-8')

            results += result
            # 判断最后两个字符是否是我们定义的结束符
            if results[-2:] in endSymbol:
                break

        re1 = results.split('\n')[1:]  # 第一行是我们输入的指令,丢弃
        re1 = '\n'.join(re1)

        clean_string = re.sub(r'\x1b\[[0-?]*[ -/]*[@-~]', '', re1)  # 由于我们的GUI只能展示纯文本信息所以选择 通过正则表达式对返回结果的ANSI进行匹配去除

        return clean_string+'\n'


    def vim_cat(self, command):
        '''
        :param command:
        用户编辑文件自动下载到本地,再自动打开本地编辑
        '''
        self.file_name = command.split(' ')[-1]
        self.chan.send('pwd'+'\n')
        path = ''
        while True:
            # 读取一行输出
            result = self.chan.recv(1024).decode('utf-8')
            if 'Last login:' in result:  # 如果指令里包含Last...字段就再发送一次请求
                result = self.chan.recv(1024).decode('utf-8')

            path += result
            # 判断最后两个字符是否是我们定义的结束符
            if path[-2:] in path:
                break

        re1 = path.split
Python中,可以使用第三方库如`paramiko`来实现图形化的SSH连接。`paramiko`是一个用于处理SSH协议的纯Python库,它允许你在程序中创建SSH会话、执行命令以及传输文件。 以下是一个简单的步骤示例: 1. 安装`paramiko`模块: ``` pip install paramiko ``` 2. 导入必要的模块并设置SSH连接信息(包括主机名、用户名和密码): ```python import paramiko hostname = 'your_host' username = 'your_username' password = 'your_password' ssh_client = paramiko.SSHClient() ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ``` 3. 连接到远程服务器: ```python ssh_client.connect(hostname=hostname, username=username, password=password) ``` 4. 为了实现图形化界面,你可以考虑使用TkinterPython GUI库来构建一个简单界面,让用户输入上述信息,并在用户确认后建立连接。例如: ```python from tkinter import Tk, Entry, Button def connect_ssh(): hostname_entry = e1.get() username_entry = e2.get() password_entry = e3.get() # 使用获取到的信息尝试连接 ssh_client.connect(hostname=hostname_entry, username=username_entry, password=password_entry) root = Tk() e1 = Entry(root) e2 = Entry(root) e3 = Entry(root, show="*") # 隐藏密码输入 button = Button(root, text='Connect', command=connect_ssh) # ... 组合和配置UI元素 root.mainloop() ``` 请注意,图形化SSH客户端通常更倾向于使用专门设计的应用程序,如`Putty`(Windows)、`SSH Tectia`(跨平台)或`MobaXterm`(包含终端和多种网络工具)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值