ssh工具 从ssh服务器下载文件夹

此文分享一个python脚本,用于快速的定位、选择ssh服务器上的文件夹,并将其下载到本地指定的位置。

效果演示

  • 🔥完整演示效果
    20231225153336_rec_

  • 👇 第一步,显然,我们需要选择功能
    20231225153656

  • 👇 第二步,确认我们需要从哪个ssh服务器上下载文档
    20231225153729

  • 👇 第三步,定位、选择、确认需要下载的文件夹
    20231225153815

  • 👇 第四步,确认本地路径
    20231225153900

  • 👇 第五步,确认并下载文件夹
    20231225153937

    并显示下载状态👇:
    20231225154013

配置文件

我们需要在配置文件中记录和管理一些配置信息,例如上文中提到的ssh登录信息,例如用于文档搜索的everything接口信息等。这是一个json文档(cfg.json),如下👇;或者,你可以直接下载文档

{
   
"ssh接口列表":[{
   "主机名称":"virtualBox","主机地址":"192.168.56.1","端口号":22,"用户名":"dyy","密码":"123456"}],
"everythingIP":"127.0.0.1",
"everythingPort":"22"
}

python脚本

👇以下脚本,提供了以上👆所演示的功能; 或者,您可以直接下载脚本

# -*- coding:UTF-8 -*-
"""
@author: dyy
@contact: douyaoyuan@126.com
@time: 2023/11/16 22:37
@file: ssh工具.py
@desc: 脚本提供了ssh登录,ssh文档上传,ssh文档下载,ssh公钥配置等功能,以及优良的用户体验
"""

# region 引入必要的依赖
import os
from enum import Enum
import json

模块名 = 'DebugInfo'
try:
    from DebugInfo.DebugInfo import *
except ImportError as impErr:
    print(f"尝试导入 {
     模块名} 依赖时检测到异常:{
     impErr}")
    print(f"尝试安装 {
     模块名} 模块:")
    try:
        os.system(f"pip install {
     模块名}")
    except OSError as osErr:
        print(f"尝试安装模块 {
     模块名} 时检测到异常:{
     osErr}")
        exit(0)
    else:
        try:
            from DebugInfo.DebugInfo import *
        except ImportError as impErr:
            print(f"再次尝试导入 {
     模块名} 依赖时检测到异常:{
     impErr}")
            exit(0)

模块名 = 'paramiko'
try:
    import paramiko
except ImportError as impErr:
    print(f"尝试导入 {
     模块名} 依赖时检测到异常:{
     impErr}")
    print(f"尝试安装 {
     模块名} 模块:")
    try:
        os.system(f"pip install {
     模块名}")
    except OSError as osErr:
        print(f"尝试安装模块 {
     模块名} 时检测到异常:{
     osErr}")
        exit(0)
    else:
        try:
            import paramiko
        except ImportError as impErr:
            print(f"再次尝试导入 {
     模块名} 依赖时检测到异常:{
     impErr}")
            exit(0)

模块名 = 'difflib'
try:
    import difflib  # 需要安装 difflib 模块,以支持字符差异对比操作
except ImportError as impErr:
    print(f"尝试导入 {
     模块名} 依赖时检测到异常:{
     impErr}")
    print(f"尝试安装 {
     模块名} 模块:")
    try:
        os.system(f"pip install {
     模块名}")
    except OSError as osErr:
        print(f"尝试安装模块 {
     模块名} 时检测到异常:{
     osErr}")
        exit(0)
    else:
        try:
            import difflib
        except ImportError as impErr:
            print(f"再次尝试导入 {
     模块名} 依赖时检测到异常:{
     impErr}")
            exit(0)


# endregion

# 定义一个 命令行参数类,用于解析和记录命令行参数
class 命令行参数类(入参基类):
    def __init__(self):
        super().__init__()
        self._添加参数('srcDir', str, '引用的路径')
        self._添加参数('srcDoc', str, '引用的文档')
        self._添加参数('everythingIP', str, 'everything HTTP 服务地址', '127.0.0.1')
        self._添加参数('everythingPort', str, 'everything HTTP 服务端口', '22')
        # 添加定制属性
        self.ssh接口列表: list[ssh接口类] = []

    # region 访问器
    @property
    def jsonCfg(self) -> str:
        if 'jsonCfg' in self._参数字典:
            return self._参数字典['jsonCfg'].else:
            return ''

    @jsonCfg.setter
    def jsonCfg(self,: str):
        if 'jsonCfg' in self._参数字典:
            self._参数字典['jsonCfg'].= str()

    @property
    def srcDir(self) -> str:
        if 'srcDir' in self._参数字典:
            return self._参数字典['srcDir'].else:
            return ''

    @srcDir.setter
    def srcDir(self,: str):
        if 'srcDir' in self._参数字典:
            self._参数字典['srcDir'].= str()

    @property
    def srcDoc(self) -> str:
        if 'srcDoc' in self._参数字典:
            return self._参数字典['srcDoc'].else:
            return ''

    @srcDoc.setter
    def srcDoc(self,: str):
        if 'srcDoc' in self._参数字典:
            self._参数字典['srcDoc'].= str()

    @property
    def everythingIP(self) -> str:
        if 'everythingIP' in self._参数字典:
            return self._参数字典['everythingIP'].else:
            return ''

    @everythingIP.setter
    def everythingIP(self,: str):
        if 'everythingIP' in self._参数字典:
            self._参数字典['everythingIP'].= str()

    @property
    def everythingPort(self) -> str:
        if 'everythingPort' in self._参数字典:
            return self._参数字典['everythingPort'].else:
            return ''

    @everythingPort.setter
    def everythingPort(self,: str):
        if 'everythingPort' in self._参数字典:
            self._参数字典['everythingPort'].= str()

    # endregion

    # region ssh候选列表
    def 解析Json(self,
                 jsonCfg: str = None,
                 encoding: str = 'utf-8',
                 画板: 打印模板 = None):
        """
                从指定的json文档中(如果不指定,则从 jsonCfg 参数指定的json文档中)读取配置参数,将值赋值给同名的命令行参数
                :param jsonCfg: 可以指定jsonCfg文档
                :param encoding: 可以指定jsonCfg文档的编码格式,默认为 utf-8
                :param 画板: 提供消息打印渠道
                :return: None
                """
        画板 = 画板 if isinstance(画板, 打印模板) else 打印模板()
        画板.执行位置(self.__class__, self.解析Json)

        if not jsonCfg:
            if 'jsonCfg' in self._参数字典.keys():
                jsonCfg = self._参数字典['jsonCfg'].值

        jsonCfg = str(jsonCfg if jsonCfg else '').strip()
        if not jsonCfg:
            画板.提示调试错误('jsonCfg 路径无效')
            return None
        if not os.path.isfile(jsonCfg):
            画板.提示调试错误(f'jsonCfg 不是有效的 json 文件路径: {
     jsonCfg}')
            return None
        if not jsonCfg.endswith('.json'):
            画板.提示调试错误(f'jsonCfg 不是 json 格式的文件: {
     jsonCfg}')

        画板.调试消息(f'待解析的 jsonCfg 文件是: {
     jsonCfg}')

        encoding = str(encoding if encoding else 'utf-8').strip()
        jsonDic: dict
        try:
            with open(jsonCfg, 'r', encoding=encoding) as f:
                jsonDic = json.load(f)
        except Exception as openExp:
            画板.提示调试错误(f'打开并读取 json 文档时遇到错误: {
     openExp}')
            jsonDic = {
   }
        if not jsonDic:
            画板.提示调试错误(f'未解析到有效的 json 内容: {
     jsonCfg}')
            return None

        jsonDic字典: dict = {
   }
        for,in jsonDic.items():
            # 去除键前后的空格= str().strip()
            if:
                jsonDic字典[] = 值

        已匹配的参数: dict[str, 入参基类._参数结构类] = {
   }
        未匹配的参数: dict[str, 入参基类._参数结构类] = {
   }
        for 参数 in self._参数字典.values():
            if 参数.名称 in jsonDic字典:
                参数.= jsonDic字典[参数.名称]
                if str(参数.).strip() == str(jsonDic字典[参数.名称]).strip():
                    已匹配的参数[参数.名称] = 参数
        if 'ssh接口列表' in jsonDic字典.keys() and jsonDic字典['ssh接口列表']:
            # 解析ssh接口配置
            ssh接口列表 = jsonDic字典['ssh接口列表']
            参数 = 命令行参数类._参数结构类(名称='ssh接口列表')
            参数.= ssh接口列表
            已匹配的参数['ssh接口列表'] = 参数
            for 接口 in ssh接口列表:
                ssh接口: ssh接口类 = ssh接口类()
                if '主机名称' in 接口:
                    ssh接口.主机名 = 接口['主机名称']
                if '主机地址' in 接口:
                    ssh接口.主机地址 = 接口['主机地址']
                if '端口号' in 接口:
                    ssh接口.端口号 = 接口['端口号']
                if '用户名' in 接口:
                    ssh接口.用户名 = 接口['用户名']
                if '密码' in 接口:
                    ssh接口.密码 = 接口['密码']
                self.ssh接口列表.append(ssh接口)
        for,in jsonDic字典.items():
            ifnot in 已匹配的参数.keys():
                这个参数: 入参基类._参数结构类 = 入参基类._参数结构类(名称=,
                                                                      类型=str,
                                                                      提示='这是 jsonCfg 中未匹配成功的参数',
                                                                      默认值=)
                未匹配的参数[] = 这个参数

        if 画板.正在调试 and (已匹配的参数 or 未匹配的参数):
            画板.准备表格()
            if 已匹配的参数:
                画板.添加一行('参数名', '参数类型', '参数值', '提示').修饰行(青字)
                for 参数 in 已匹配的参数.values():
                    画板.添加一行(参数.名称, 参数.类型, 参数., 参数.提示)
            if 未匹配的参数:
                画板.添加分隔行(提示文本='以下参数未匹配成功', 修饰方法=红字, 适应窗口=True)
                for 参数 in 未匹配的参数.values():
                    画板.添加一行(参数.名称, 参数.类型, 参数., 参数.提示)
            画板.展示表格()
    # endregion


class 文档操作记录类:
    def __init__(self,
                 旧文档: str = None,
                 新文档: str = None):
        self.__旧文档: str = 旧文档
        self.__新文档: str = 新文档
        self.__带标注的旧文档: str = ''
        self.__带标注的新文档: str = ''

    # region 访问器
    @property
    def 旧文档(self) -> str:
        return self.__旧文档

    @旧文档.setter
    def 旧文档(self, 文档: str):
        文档 = str(文档 if 文档 else '').strip()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/269602.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

4.2 媒资管理模块 - 项目搭建、minio文件系统

文章目录 一、搭建媒资服务工程1.1 media-api 工程1.1.1 bootstrap.yaml1.1.2 Maven1.1.3 Nacos 1.2 media-service 工程1.2.1 bootstrap.yaml1.2.2 Maven1.2.3 Nacos1.2.4 分页插件 1.3 media-model 工程1.3.1 QueryMediaParamsDto1.3.2 MediaFiles1.3.3 MediaProcess1.3.4 Me…

MySql的mvcc原理

目录 一、什么是mvcc? 二、什么是当前读,快照读? 当前读 快照读 三、mvcc实现原理 版本链 undo日志 Undo log 的用途 Read View(读视图) Read View几个属性 五、RR、RC级别下生成时机 一、什么是mvcc? mvcc全称Multi-Version Concurrency Control,即…

为什么我的网络这么卡卡卡卡卡?(网络调试篇)

前言 最近小白迷上了打游戏。 有没有一起上王者的小伙伴? 有没有一起吃鸡的小伙伴? 欧耶, 咱们组队 送人头去吧 为了不让对方太菜, 送人头是与对方最高的敬意。 闲话说到这,本文就结束了。 感谢观看~…

常用组件的一些数据指标

QPS metrics 机制,利用 AtomicLong 算出核心接口每分钟调用多少次(除以 60 就是高峰期每秒访问次数)以及每天被调用总次数 TP99 100ms , 99%的接口耗时在 100ms以内,1%的接口耗时在100ms以上 TP95 100ms , 95%的接口耗时在 1…

CUMT--Java复习--网络编程

目录 一、Java网络API 1、InetAddress类 2、URL类 3、URLConnection类 4、URLDecoder类和URLEncoder类 二、基于TCP的网络编程 1、Socket类 2、ServerSocket类 三、网络通信过程 一、Java网络API Java中有关网络方面的功能都定义在java.net中。 1、InetAddress类 Jav…

AP有信号,但没有注册到AC上的排查

1、有wifi信号收到,并且可以连接,但A P没有获取到地址。 1.AP没有获取到地址,那么就一定没办法找到AC到地址进行注册。 2、交换侧现象: dis poe power 查看端口供电情况。 3、有供电,但没有UP。 4、判断为配…

如何使用Jellyfin结合内网穿透搭建私人影音平台远程可访问

作者简介: 懒大王敲代码,计算机专业应届生 今天给大家如何使用Jellyfin结合内网穿透搭建私人影音平台远程可访问,希望大家能觉得实用! 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖 前言…

设计模式--桥接模式

实验9:桥接模式 本次实验属于模仿型实验,通过本次实验学生将掌握以下内容: 1、理解桥接模式的动机,掌握该模式的结构; 2、能够利用桥接模式解决实际问题。 [实验任务]:两个维度的桥接模式 用桥接模式…

JuiceSSH结合内网穿透实现公网远程访问本地Linux虚拟机

文章目录 1. Linux安装cpolar2. 创建公网SSH连接地址3. JuiceSSH公网远程连接4. 固定连接SSH公网地址5. SSH固定地址连接测试 处于内网的虚拟机如何被外网访问呢?如何手机就能访问虚拟机呢? cpolarJuiceSSH 实现手机端远程连接Linux虚拟机(内网穿透,手机端连接Linux虚拟机) …

Ubuntu系统如何安装SVN服务端并通过客户端无公网ip实现远程访问?

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

Houdini 20版本 功能概述

SideFX 发布了 Houdini 20 预览版,这是其用于视觉特效、游戏开发和动态图形的程序 3D 软件的下一个主要版本,Houdini 20.0 对软件的主要工具集进行了更新,特别是角色装备和动画、模拟工具以及 Karma 渲染器。 Houdini 20新功能亮点 渲染 视频…

玩转大数据22:常见的关联规则挖掘算法

引言 关联规则挖掘是数据挖掘中的一种重要技术,主要用于发现数据集中项之间的有趣关系。关联规则挖掘在许多领域都有广泛的应用,如市场篮子分析、推荐系统等。常见的关联规则挖掘算法包括Apriori算法和FP-Growth算法。 一、Apriori算法 关联规则挖掘是…

制作一个可以离线安装的Visual Studio安装包

须知 前提条件,需要电脑可以正常上网且网速还行,硬盘可以空间容量足够大,怎么判断容量够用?由组件数量的多少来决定。Visual Studio 频道和发布节奏 https://learn.microsoft.com/zh-cn/visualstudio/productinfo/release-rhythm…

Linux上iPortal 配置80端口的http

作者:yx 文章目录 前言方法一、配置使用外置ES1、关闭启用 iPortal 内置的 ES2、修改80端口3、启动外置ES4、启动iPortal5、结果验证 方法二、更改 Linux 系统配置1. 安装 Authbind2. 启用端口的读取和执行权限3. 在 Apache Tomcat 上启用 Authbind4. 重启iPortal5.…

Mysql高级函数——GROUP_CONCAT

Mysql高级函数——GROUP_CONCAT 前言仰天大笑出门去,我辈岂是蓬蒿人 前言 大概内容: 在MySQL中,可以使用GROUP_CONCAT函数来实现将多个数据拼接为一个字符串的功能。GROUP_CONCAT函数接受一个参数,用于指定要拼接的数据列&#x…

【Unity3D日常BUG】Unity3D中编辑完代码后卡在Reload Scripts Assemblies界面的解决方案

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 首先,说明一下,每个人对于BUG的定义不一…

【多线程及高并发 二】线程基础及线程中断同步

👏作者简介:大家好,我是若明天不见,BAT的Java高级开发工程师,CSDN博客专家,后端领域优质创作者 📕系列专栏:多线程及高并发系列 📕其他专栏:微服务框架系列、…

SpringCloud和Dubbo有哪些区别

🍎个人博客:个人主页 🏆个人专栏: Spring ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 介绍 Spring Cloud: Dubbo: 选择: 区别 结语 我的其他博客 前言 构建分布式系统是…

Netty组件基础

Netty入门简介 netty是一个异步、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端。 Netty优势 Netty解决了TCP传输问题,如黏包、半包问题,解决了epoll空轮询导致CPU100%的问题。并且Netty对API进行增强&#xf…

Playbook中jinja2模板的使用

本章主要介绍playbook中如何使用jinja2模板 什么是jinja2模板在jinja2模板文件中写if判断语句在jinja2模板文件在写for循环语句handlers的使用 可以使用copy模块把本地的一个文件拷贝到远端机器,下面再次复习一下 本章实验都在demo4文件夹下操作,跟之…