https://www.jianshu.com/p/944674f44b24

paramiko 是 Python 中的一个用来连接远程主机的第三方工具,通过使用 paramiko 可以用来代替以 ssh 连接到远程主机执行命令。

paramiko 模块提供了两个核心组件,分别是 SSHClient 和 SFTPClient。前者用于在远程主机上执行命令,是对于 ssh 会话的封装;后者用于对资源上传下载等操作,是对 sftp 的封装。

paramiko 模块提供了一些SSH核心组件

  • Channel: 建立 ssh 连接后,paramiko会调用底层的 channel 类来打开一个socket连接,后续发送的命令会通过 channel 进行发送,当接收到命令的返回结果(标准输出或标准错误)后,结果又将通过 channel 发送到连接的客户端。
  • Client: 建立的 ssh 会话的客户端。通过客户端可以去连接多个远程主机,并将执行的命令通过 client.exec_command() 方法发送到远程主机。
  • Message: 一个用来将传输过程中的字符、整形、布尔及长类型的字符组合进行编码组成的字节流信息。
  • PacketizerImplementation of the base SSH packet protocol.
  • Transport: 封装了一个加密的会话,调用该会话时会创建一个流式隧道(通常称为 channel)

封装的具体逻辑,为了保持功能的纯粹性,仅通过 paramiko 实现客户端的的建立及命令的发送。

以下为实现逻辑

#!/usr/bin/env python3
# coding=utf-8 import sys
import socket
import paramiko
from paramiko.ssh_exception import NoValidConnectionsError, AuthenticationException class Connect(object): def __init__(self, username: str,
password: str,
port: int = 22,
hostname: str,
pkey: str = None,
look_for_keys: bool = True,
allow_agent: bool = True,
timeout: float = None
):
self.hostname = hostname
self.username = suername
self.port = port
self.password = password
self.pkey = pkey
self.allow_agent = allow_agent
self.look_for_keys = look_for_keys
self.timeout = timeout def _connect(self):
self.client = SSHClient()
self.client.load_system_host_keys()
self.client.set_missing_host_key_policy(paramiko.AutoAddpolicy())
try:
self.client.connect(hostname=self.hostname,
port=self.port,
username=self.username,
password=self.password,
pkey=self.pkey,
allow_agent=self.allow_agent,
look_for_keys=self.look_for_keys
)
except BadHostKeyException as badKey:
msg = "Receive a bad key"
sys.exit()
except AuthenticationException as auth:
msg = "Invalid username or password"
sys.exit()
except SSHExpection as ssh:
msg = "Establish ssh session error"
sys.exit()
exception scoket.error as sock:
msg = "Connecting has a socket error"
sys.exit() def run(self, command: str):
stdin, stdout, stderr = self.client.exec_command(command, timeout=self.timeout)
stdin.close()
stdout.flush() try:
output = stdout.read()
err_msg = stderr.read() output = output.decode("utf-8") if isinstance(output, bytes) else output
err_msg = err_msg.decode("utf-8") if isinstance(err_msg, bytes) else err_msg
return output, err_msg except socket.timeout:
raise(f"Exec Command {command} timeout") def close(self):
self.client.close()

将ssh会话保存到会话池中

#!/usr/bin/env python3
# encoding=utf-8 import os
import socket
import paramiko
from collections import deque
from paramiko.ssh_exception import SSHException
from paramiko.ssh_exception import NoValidConnectionsError, AuthenticationException
from eventlet import pools class SSHPool(pools.Pool): """创建 SSH 对象池 """
_pool = deque() def __init__(self,
ip: str,
username: str,
password: str = None,
port: int = 22,
privatekey: str = None,
timeout: float = None,
**kwargs
):
self.ip = ip
self.port = port
self.password = password
self.username = username
self.privatekey = privatekey
self.timeout = timeout
super(SSHPool, self).__init__(**kwargs) def create(self):
try:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) if self.password:
client.connect(self.ip,
port=self.port,
username=self.username,
password=self.password,
timeout=self.timeout
)
elif self.privatekey:
if isinstance(self.privatekey, paramiko.rsakey.RSAKey):
key = self.privatekey
else:
keyfile = os.path.expanduser(self.privatekey)
key = paramiko.RSAKey.from_private_key_file(keyfile)
client.connect(self.ip,
port=self.port,
username=self.username,
look_for_keys=True,
pkey=key,
timeout=self.timeout
)
else:
raise SSHException("Invalid username or password") # Paramiko by default sets the socket timeout to 0.1 seconds,
# ignoring what we set through the sshclient. This doesn't help for
# keeping long lived connections. Hence we have to bypass it, by
# overriding it after the transport is initialized. We are setting
# the sockettimeout to None and setting a keepalive packet so that,
# the server will keep the connection open. All that does is send
# a keepalive packet every ssh_conn_timeout seconds. if self.timeout:
transport = client.get_transport()
transport.sock.settimeout(None)
transport.set_keepalive(self.timeout)
return client except socket.timeout:
raise SSHException("Connect timeout")
except NoValidConnectionsError as novalid:
raise SSHException("Connect valid failed")
except AuthenticationException as auth:
raise SSHException("Invalid username or password")
except Exception as e:
raise SSHException("An exception happened") def get(self):
"""从会话池中获取 SSH 会话
1. 返回一个存活的会话
2. 不存在的会话或已经失效的会话, 会新建一个会话并返回该会话
"""
conn = super(SSHPool, self).get()
print("get: [%s]" % conn)
if conn:
if conn.get_transport().is_active():
return conn
else:
conn.close()
return self.create() #def put(self, ssh):
# """将 SSH 会话添加到会话池中"""
# conn = super(SSHPool, self).get()
# if ssh not in self._pool:
# self._pool.append(ssh) def remove(self, ssh):
"""关闭 SSH 会话,并将其从会话池中移除"""
ssh.close()
ssh = None
print("remove: [%s]" % ','.join(self.free_items))
if ssh in self.free_items:
self.free_items.pop(ssh)
if self.current_size > 0:
self.current -= 1 if __name__ == "__main__":
client = SSHPool(username='root', password='****!', ip='****')
with client.get() as conn:
_, stdout, stderr = conn.exec_command("ls -l")
print(stdout.read().decode()) # 参考自: https://opendev.org/openstack/cinder/commit/75ef446fef63320e9c1ed4a04e59ffbbb62b5cef?style=unified

【转帖】基于paramiko的二次封装的更多相关文章

  1. Python实现Paramiko的二次封装

    Paramiko是一个用于执行SSH命令的Python第三方库,使用该库可实现自动化运维的所有任务,如下是一些常用代码的封装方式,多数代码为半成品,只是敲代码时的备份副本防止丢失,仅供参考,目前本人巡 ...

  2. iOS基于MBProgressHUD的二次封装,一行搞定,使用超简单

    MBProgressHUD的使用,临时总结了几款最常用的使用场景: 1.提示消息 用法: [YJProgressHUD showMessage:@"显示文字,1s隐藏" inVie ...

  3. 基于element-ui进行二次封装的表格组件

    <!-- * @description 表格组件 * @fileName TableList.vue * @authorQ * @date 2021/05/15 15:13:45 --> ...

  4. Selenium二次封装-Java版本

    package com.yanfuchang.selenium.utils; import java.awt.AWTException; import java.awt.Robot; import j ...

  5. 基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil

    基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil,把日常能用到的各种CRUD都进行了简化封装,让普通程序员只需关注业务即可,因为非常简单,故直接贴源代码,大家若需使用可以直 ...

  6. python+selenium十:基于原生selenium的二次封装

    from selenium import webdriverfrom selenium.webdriver.support.wait import WebDriverWaitfrom selenium ...

  7. 使用Vue CLI 3将基于element-ui二次封装的组件发布到npm

    前言:之前在网上找的好多都是基于vue-cli 2.x的,而使用vue-cli 3的文章比较少,Vue CLI 3 中文文档,所以我在自己尝试的时候把几篇文章结合了一下,调出来了我想要的模式,也就是V ...

  8. android基于开源网络框架asychhttpclient,二次封装为通用网络请求组件

    网络请求是全部App都不可缺少的功能,假设每次开发都重写一次网络请求或者将曾经的代码拷贝到新的App中,不是非常合理,出于此目的,我希望将整个网络请求框架独立出来,与业务逻辑分隔开,这样就能够避免每次 ...

  9. 基于bootstrap table配置的二次封装

    准备 jQuery js css 引用完毕 开始 如果对bootstrap table 的方法与事件不熟悉: Bootstrap table方法,Bootstrap table事件 <table ...

  10. Vue.js 自定义组件封装实录——基于现有控件的二次封装(以计时器为例)

    在本人着手开发一个考试系统的过程中,出现了如下一个需求:制作一个倒计时的控件显示在试卷页面上.本文所记录的就是这样的一个过程. 前期工作 对于这个需求,自然我想到的是有没有现成的组件可以直接使用(本着 ...

随机推荐

  1. 作为所有类的顶层父类,没想到Object的魔力如此之大!

    写在开头 在上一篇博文中我们提到了Java面向对象的四大特性,其中谈及"抽象"特性时做了一个引子,引出今天的主人公Object,作为所有类的顶级父类,Object被视为是James ...

  2. 8种图数据库对 NULL 属性值支持情况

    摘要:在语义网等图模型中,遵循开放世界假设,对于数据中未包含的事实,都认为是未知的而非假的. 本文分享自华为云社区<图数据库对 NULL 属性值支持情况>,原文作者:你好_TT . NUL ...

  3. 低门槛上手快!火山引擎 VeDI 这样满足数据分析新需求

      更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 近日,市场研究机构 IDC 发布<2022 年 V2 全球大数据支出指南>. 数据显示,2021 ...

  4. PPT 年终总结PPT 应该怎么样改

  5. compilation.templatesPlugin is not a function

    ERROR Failed to compile with 1 error TypeError: compilation.templatesPlugin is not a function - SetV ...

  6. 🤗Hugging Face 87个 AI 游戏可以在线玩啦

    7月9日结束的开源游戏挑战赛有超过来自全球 1000 多名开发者参加 一共收录了 87 个游戏 目前已经进入投票期 视频中的:猜名画 ️ 用了之前推荐的 LEDITS 目前得分很高呢 来试试看你能猜对 ...

  7. Django rest_framework用户认证和权限

    完整的代码 https://gitee.com/mom925/django-system 使用jwt实现用户认证 pip install djangorestframework-simplejwt 重 ...

  8. 叫板GPT-4的Gemini,我做了一个聊天网页,可图片输入,附教程

    先看效果: 简介 Gemini 是谷歌研发的最新一代大语言模型,目前有三个版本,被称为中杯.大杯.超大杯,Gemini Ultra 号称可与GPT-4一较高低: Gemini Nano(预览访问) 为 ...

  9. C++ 智能指针的正确使用方式

    C++11 中推出了三种智能指针,unique_ptr.shared_ptr 和 weak_ptr,同时也将 auto_ptr 置为废弃 (deprecated). 但是在实际的使用过程中,很多人都会 ...

  10. POJ 1015 Jury Compromise (完全背包)

    题目大意: 在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定.陪审团是由法官从公众中挑选的.先随机挑选n 个人作为陪审团的候选人,然后再从这n 个人中选m 人组成陪审团.选m 人的办法是:控方和辩 ...