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. 文心一言 VS 讯飞星火 VS chatgpt (44)-- 算法导论6.1 1题

    一.在高度为h的堆中,元素个数最多和最少分别是多少? 文心一言: 在高度为 h 的二叉搜索树(BST)中,元素个数最多和最少的情况分别如下: 1.最多情况:当每个节点都包含两个子节点时,BST 中的元 ...

  2. LeetCode 栈与队列篇(12、155、84、239)

    20. 有效的括号 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须以正确的顺序闭合. ...

  3. PLG SaaS 案例:如何实践外链自动增长策略?

    首先任何的商业逻辑,光流量增长,没法变现是没用的. 就像博客群发提效工具,得有对应的用户,更得有对应付费用户群体的画像.剩下的就是靠增长,被动让他们找到你的产品,用产品解决他们痛点,他们自然而然会付费 ...

  4. Prometheus配置Basic Auth进行安全防护,实现登录控制

    本文分享自华为云社区<Prometheus配置Basic Auth进行安全防护,实现登录控制>,作者:可以交个朋友. 一.Prometheus Basic Auth 使用背景 在日常pro ...

  5. 华为IoT首席架构师王启军:全栈工程师“养成记”

    在王启军的公众号里,有一篇<My Team>的文章,里面记录了早年他所带团队成长的心得. 这个被他称为完美组合的团队,并不是来自大厂名企,彼时王启军给不起高待遇,团队核心成员中还有很多人是 ...

  6. 实战案例丨代码优化:如何去除context中的warning?

    在一个java语言群里面,有人抛了这么一段代码出来,问题是出现了下下图中的warning,问有什么好的方法消除 这种强转都是因为类型链条断掉了,写入的时候擦除了类型,读出来的时候也就只能强转了,那个i ...

  7. 古有诸葛亮八卦阵阻敌,今有 iptables 护网安

    摘要:保障网络环境的安全,我们得"武装"起来,守住各个入口.怎么"武装"呢? 网络世界就和现实世界一样,总是会有些不怀好意的"人"出现,扫扫 ...

  8. Apache HBase MTTR 优化实践:减少恢复时长

    摘要:HBase是Hadoop Database的简称,是建立在Hadoop文件系统之上的分布式面向列的数据库,它具有高可靠.高性能.面向列和可伸缩的特性,提供快速随机访问海量数据能力. 本文分享自华 ...

  9. 解密数据仓库LLVM技术神奇之处

    摘要:广义上讲就是指LLVM本身,它是一套用于开发编译前端与后端的工具套件,狭义上讲LLVM就是指整个编译套件的优化器及后端,而CLANG可以认为是C/C++的前端. 本文分享自华为云社区<Ga ...

  10. Docker cp 将宿主机上的文件复制到容器中

    [root@localhost ~]# docker cp /opt/web/docker_cp.txt tomcat9093:/usr/local/apache-tomcat-9.0.31/ [ro ...