paramiko 无法实例化 transport

2023-10-27

背景

Paramiko is a pure-Python [1] (2.7, 3.4+) implementation of the SSHv2 protocol [2], providing both client and server functionality. It provides the foundation for the high-level SSH library Fabric, which is what we recommend you use for common client use-cases such as running remote shell commands or transferring files.

Direct use of Paramiko itself is only intended for users who need advanced/low-level primitives or want to run an in-Python sshd.

以上是 paramiko 的官网介绍,简而言之,paramiko 是一个实用的 python ssh 库。

目前遇到一个问题,尝试用 paramiko 构建 ssh 连接,ssh 连接是基于 paramiko 的 transport 对象,因此需要先实例化 transport 对象,但是如果服务器宕机了,paramiko 会一直 pending 在实例化 transport 对象的过程中。

原因

Create a new SSH session over an existing socket, or socket-like object. This only creates the Transport object; it doesn’t begin the SSH session yet. Use connect or start_client to begin a client session, or start_server to begin a server session.

查看 paramiko 文档,发现 transport 是基于 socket 进行通信的,实例化 transport 对象需要传入 socket 对象或是类 socket 对象。而所谓类 socket 对象,其实就是 IP + port 的信息,这也是一般实例化 transport 的方法:

self.transport = paramiko.Transport((hostname, port))
self.transport.connect(username=username, password=password, **kwargs)

其实查看源码可以发现,这种类 socket 对象是 paramiko 对其做了向真实 socket 对象的转化:

...
if isinstance(sock, string_types):
    # convert "host:port" into (host, port)
    hl = sock.split(":", 1)
    self.hostname = hl[0]
    if len(hl) == 1:
        sock = (hl[0], 22)
    else:
        sock = (hl[0], int(hl[1]))
if type(sock) is tuple:
    # connect to the given (host, port)
    hostname, port = sock
    self.hostname = hostname
    reason = "No suitable address family"
    addrinfos = socket.getaddrinfo(
        hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM
    )
    for family, socktype, proto, canonname, sockaddr in addrinfos:
        if socktype == socket.SOCK_STREAM:
            af = family
            # addr = sockaddr
            sock = socket.socket(af, socket.SOCK_STREAM)
            try:
                retry_on_signal(lambda: sock.connect((hostname, port)))
            except socket.error as e:
                reason = str(e)
            else:
                break
    else:
        raise SSHException(
            "Unable to connect to {}: {}".format(hostname, reason)
        )
...

这时就会产生一个问题,paramiko 创建好 socket 对象后会测试连接,调用 retry_on_signal 方法,这个方法是个循环方法,直到连接通了才会停止。

def retry_on_signal(function):
    """Retries function until it doesn't raise an EINTR error"""
    while True:
        try:
            return function()
        except EnvironmentError as e:
            if e.errno != errno.EINTR:
                raise

但是,如果服务器宕机了,这个方法就会一直 pending 在这里…因为 paramiko 在实例化 socket 的时候并没有设置 socket 的 timeout 时间,即超时等待时间,而 socket 的默认 timeout 时间是 None…

socket.setdefaulttimeout(timeout)

Set the default timeout in seconds (float) for new socket objects. When the socket module is first imported, the default is None. See settimeout() for possible values and their respective meanings.

解决

解决思路是,既然实例化 transport 需要 socket 对象,那么就传一个真实的 socket 对象给构造函数,而不是让它帮我们实例化 socket。同时,我们在实例化 socket 的时候,同时调用 socket.timeout() 方法设置超时等待时间,以下代码参考 paramiko 的代码:

class SSH(object):
    def __init__(self, hostname, username, password=None, port=22, **kwargs):
        """
        ssh = SSH(host, username, password)
        """
        self._username = username
        self._password = password

        timeout = kwargs.pop('timeout', 0)
        self.transport = paramiko.Transport(_create_socket(hostname=hostname, port=port, timeout=timeout))
        # self.transport = paramiko.Transport((hostname, port))
        self.transport.connect(username=username, password=password, **kwargs)

        self.ssh = paramiko.SSHClient()
        self.ssh._transport = self.transport
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def _create_socket(hostname, port, timeout=0):
    """
    Create socket instance
    If timeout>0, set the timeout of the instance, otherwise use the default timeout.
    :param hostname:
    :param port:
    :param timeout:
    :return:
    """
    reason = "No suitable address family"
    addrinfos = socket.getaddrinfo(
        hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM
    )
    for family, socktype, proto, canonname, sockaddr in addrinfos:
        if socktype == socket.SOCK_STREAM:
            sock = socket.socket(family, socket.SOCK_STREAM)
            if timeout > 0:
                sock.settimeout(timeout)
            try:
                retry_on_signal(lambda: sock.connect((hostname, port)))
            except socket.error as e:
                reason = str(e)
            else:
                break
    else:
        raise SSHException(
            "Unable to connect to {}: {}".format(hostname, reason)
        )
    return sock


if __name__ == '__main__':
    ssh = SSH('192.168.1.123', 'test', 'test')

得到抛出的异常:

Traceback (most recent call last):
  File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevd.py", line 1483, in _exec
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "/Users/alex/WorkSpace/repositories/hol-troubleshooting/scripts/ssh.py", line 240, in <module>
    ssh = SSH('192.168.1.123', 'test', 'test')
  File "/Users/alex/WorkSpace/repositories/hol-troubleshooting/scripts/ssh.py", line 37, in __init__
    self.transport = paramiko.Transport(_create_socket(hostname=hostname, port=port, timeout=timeout))
  File "/Users/alex/WorkSpace/repositories/hol-troubleshooting/scripts/ssh.py", line 201, in _create_socket
    "Unable to connect to {}: {}".format(hostname, reason)
paramiko.ssh_exception.SSHException: Unable to connect to 192.168.1.123: timed out

仅供参考,欢迎交流。

参考

  1. paramiko 官网
  2. paramiko api 文档
  3. python socket api 文档
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

paramiko 无法实例化 transport 的相关文章

  • 使用 Django 的 post_save() 信号

    我有两张桌子 class Advertisement models Model created at models DateTimeField auto now add True author email models EmailField
  • 用 Python 编写一个无操作或虚拟类

    假设我有这样的代码 foo fooFactory create 由于种种原因 fooFactory create 可能无法创建实例Foo 如果可以的话我想要fooFactory create 返回一个虚拟 无操作对象 这个对象应该是完全惰性
  • 使用 JSch 分别为各个提示提供输入

    问题是 SSH 连接需要在常规登录后提供另一个用户 ID 和密码信息 我正在使用 JSch 连接到远程服务器 它接受以下形式的输入InputStream 和这个InputStream只能通过一次 由于会话是交互式的 这会导致问题 我尝试将输
  • 如何将条目中的部分文本加粗并更改其背景颜色?

    我正在创建一个基于 Tkinter 的 GUI 它有一个 Entry 小部件 我想将其文本的一部分加粗并更改其背景颜色 但我不知道我该怎么做 如果我使用文本小部件 我可以只使用标签 但看起来它们不能与条目小部件一起使用 此代码使用文本小部件
  • 在 Python 中使用 sec 函数的反函数

    我正在创建一个程序 用于计算从一定高度范围和设定初始速度发射射弹的最佳角度 在我需要使用的最终方程中 存在一个反 sec 函数 它导致了一些麻烦 我已经导入了数学并尝试使用 asec 无论如何 但是数学似乎无法计算反秒函数 我也明白 sec
  • 在 python-docx 中搜索和替换

    我有一个包含以下字符串的文档 模板 你好 我的名字是鲍勃 鲍勃是一个很好的名字 我想使用 python docx 打开此文档并使用 查找和替换 方法 如果存在 来更改每个字符串 Bob gt Mark 最后 我想生成一个新文档 其中包含字符
  • python ttk treeview:如何选择并设置焦点在一行上?

    我有一个 ttk Treeview 小部件 其中包含一些数据行 如何设置焦点并选择 突出显示 指定项目 tree focus set 什么也没做 tree selection set 0 抱怨 尽管小部件明显填充了超过零个项目 但未找到项目
  • python中函数变量的作用域

    假设我们有两个函数 def ftpConnect ftp FTP server ftp login ftp cwd path def getFileList ftpConnect files ftp nlst print files 如果我
  • 行为:如何从另一个文件导入步骤?

    我刚刚开始使用behave http pythonhosted org behave 一个Pythonic BDD框架 使用小黄瓜语法 http docs behat org guides 1 gherkin html 行为需要一个特征 例
  • 反加入熊猫

    我有两个表 我想附加它们 以便仅保留表 A 中的所有数据 并且仅在其键唯一时添加表 B 中的数据 键值在表 A 和 B 中是唯一的 但在某些情况下键将出现在表 A 和 B 中 我认为执行此操作的方法将涉及某种过滤联接 反联接 以获取表 B
  • 如何为多组精灵创建随机位置?

    我尝试使用 blit 和 draw 方法进行 for 循环 并为 PlayerSprite 和 Treegroup 使用不同的变量 for PlayerSprite in Treegroup surface blit PlayerSprit
  • 使用Python将图像转换为十六进制格式

    我的下面有一个jpg文件tmp folder upload path tmp resized test jpg 我一直在使用下面的代码 Method 1 with open upload path rb as image file enco
  • Python 中的这种赋值方式叫什么? a = b = 真

    我知道关于元组拆包 http docs python org tutorial datastructures html tuples and sequences但是当一行中有多个等号时 这个赋值被称为什么 阿拉a b True 它总是让我有
  • 字典中列表中仅有的几个索引的总和

    如果我有这种类型的字典 a dictionary dog white 3 5 black 6 7 Brown 23 1 cat gray 5 6 brown 4 9 bird blue 3 5 green 1 2 yellow 4 9 mo
  • 使用循环将对象添加到列表(python)

    我正在尝试使用 while 循环将对象添加到列表中 基本上这就是我想做的 class x pass choice raw input pick what you want to do while choice 0 if choice 1 E
  • 有没有办法只安装mysql客户端(Linux)? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有没有不需要安装整个mysql db安装包的Linux mysql命令行工具 我想做的是从服务器 1 应用程序服务器 执行将在服务器 2
  • 在 pip.conf 中指定多个可信主机

    这是我尝试在我的中设置的 etc pip conf global trusted host pypi org files pythonhosted org 但是 它无法正常工作 参考 https pip pypa io en stable
  • Python Flask 是否定义了路由顺序?

    在我看来 我的设置类似于以下内容 app route test def test app route
  • Python 矩阵每一行的总和

    lista 1 2 3 4 5 6 7 8 9 print lista def filas lista res for elemento in lista x sum lista elemento res append x print re
  • 使用 numpy 加速 for 循环

    下一个 for 循环如何使用 numpy 获得加速 我想这里可以使用一些奇特的索引技巧 但我不知道是哪一个 这里可以使用 einsum 吗 a 0 for i in range len b a numpy mean C d e f b i

随机推荐

  • 自动驾驶测试中的Re-simulation技术

    随着自动驾驶技术的发展 自动驾驶仿真的重要性越来越大 一是体现在上路之前可以通过仿真进行初步验证 二是体现在路上遇到问题时 可以通过仿真进行数据回放 改善算法模块性能 平时常见的自动驾驶仿真主要是利用软件搭载测试场景 然而 随着data d
  • 【解决】VS2019各种乱码的情况

    关于Visual Studio 2019控制台输出中文出现乱码问题及解决办法 1 从 txt文件中读取输出出现乱码 2 从中文字符串中读取输出出现乱码 3 上传git时 gitee github里出现乱码 总结 环境 Windows11 V
  • Torchtext 0.12+ API 根据token,得到语料中统计的频数值(3)

    使用OrderedDict构造vocab时会按照从大到小的排序来构造token 因此借用这个特点 构造一个列表 专门保存vocab中每一个单词的频数 此时列表的下标位置与vocab中下标位置是一一对应的 借助vocab将文本 gt toke
  • Python判断股票是交易日,爬虫抓取深交所交易日历

    为了判断某一天是不是股票的交易日 以此区分自然日与交易日 我们通过抓取深交所的交易日历获取相关数据 获取交易日思路 首先 打开深交所的交易日历页面 http www szse cn aboutus calendar index html 我
  • Nginx:配置访问页面认证(ngx_http_auth_basic_module)

    Nginx 配置访问页面认证 ngx http auth basic module 我们在访问一些网站的时候 会遇到下图这样的验证页面 类似这样的验证页面在nginx怎么进行配置呢 下面我们来做一个演示 安装niginx 直接使用yum安装
  • 【LaTeX中英排版系列】LaTeX中英双标题、作者、机构、摘要文档首页排版指北

    效果图预览 XeLaTeX可编译代码 documentclass 11pt article usepackage xeCJK CJK语言环境 使用XeLaTex进行编译 usepackage authblk 对应中文部分的作者机构特殊语法
  • MySql集群搭建笔记

    MySql集群搭建笔记 博客分类 配置与管理 数据库 Mysql cluster 集群 1 Mysql集群介绍 Mysql集群架构中主要包括管理节点和数据节点 管理节点负责整个集群结构的管理 数据的存储则由各个数据节点负责 当然 像非集群环
  • 孢子气囊 tkinter控制台

    模块 tkinter time randon serial 可以用串口连接 import serial import tkinter import tkinter ttk import time import random ser seri
  • 百度地图API 手动添加文字标记

  • QT 布局管理器(QHBoxLayout/QVBoxLayout/QGridLayout)

    1 setcontentmargins设置四周留白 相对于整个窗口的 的间隔 函数原型 void QLayout setContentsMargins int left int top int right int bottom layout
  • ERP经典范式知多少—重温Go/Nogo范式的经典实验

    本文同步发布于 脑之说 微信公众号 欢迎搜索关注 ERP Event related Potentials 作为神经电生理研究中的重要方法已经被广泛的应用在脑科学研究中 在ERP研究中 实验范式是重中之重 可靠的实验范式能够帮助研究者更好的
  • db2按时间戳或日期条件查询

    我一同事写的 记录一下 substr char timestamp 1 10 date timestamp是表中timestamp字段 date 是条件值 select from table where substr char timest
  • stm32笔记:GPIO的的配置和操作(1)推挽输出方式

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 封装端口输出高低电平控制LED显示 以下方式便于修改 LED h ifndef LED H define LED H include stm32f10x h define
  • Python二级必考函数.format()函数

    目录 一 format 函数介绍 二 函数运用 位置填充 填充物 fill 对齐 align 宽度 width sign参数保留正负号 指定精度 nf 分隔符 进制 o b d x 一 format 函数介绍 format 函数用来收集其后
  • Python 第三方模块 统计2 patsy,chowtest

    一 patsy 官方文档 https pypi org project patsy 1 概述 1 简介 patsy是1个用于描述统计模型 尤其是线性模型或具有线性组件的模型 和构建设计矩阵的Python库 其受R S语言中的公式迷你语言启发
  • 数据库索引原理及优化

    转发内容 一 摘要 本文以MySQL数据库为研究对象 讨论与数据库索引相关的一些话题 特别需要说明的是 MySQL支持诸多存储引擎 而各种存储引擎对索引的支持也各不相同 因此MySQL数据库支持多种索引类型 如BTree索引 哈希索引 全文
  • Python实现红黑树的删除操作

    Python实现红黑树的删除操作 本专栏的上一篇文章使用Python实现了红黑树的插入操作 参考 https blog csdn net weixin 43790276 article details 106456969 本篇文章使用Pyt
  • STL模板简介

    STL是C 中的优秀作品 有了它的陪伴 许多底层的数据机构以及算法我们不需要自己写 可以直接用STL里面的 就相当于我们站在巨人的肩膀上 飞一般地向前进 一 什么是STL STL standard template library 标准模板
  • H5跳转微信小程序-成功案例(VUE)(踩坑无数)

    这里写自定义目录标题 准备工作 根据官方提供的资料需准备以下几点 1 已认证的服务号 2 绑定JS接口安全域名 在微信公众平台设置 3 IP白名单 在微信公众平台设置 4 将小程序和H5公众号进行关联 在微信公众平台设置 5 页面path和
  • paramiko 无法实例化 transport

    背景 Paramiko is a pure Python 1 2 7 3 4 implementation of the SSHv2 protocol 2 providing both client and server functiona