Paramiko Transport settimeout

#python #paramiko

#python #paramiko

Вопрос:

Я использую Paramiko с переадресацией портов, основной вариант работает нормально, но когда я тестирую свои случаи ошибок. У меня длительный тайм-аут, когда я это делаю:

 port = transport.request_port_forward(my_ip],0)
channel = transport.open_channel('direct-tcpip',(my_ip',22),
                                    ('127.0.0.1',port))
  

Проблема в transport.open_channel: устройство (my_ip) недоступно, поэтому paramiko не может подключиться… Я хотел бы установить тайм-аут для этой операции, но в настоящее время я знаю, как установить его только для:

 Client.connect()
Channel.settiemout()
  

Но Client.connect работает только для соединения, и я получил свой канал после transport.open_channel()…

Я нашел это в документации paramiko (Транспорт) :

инициализация(sock)

 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.

If the object is not actually a socket, it must have the following methods:

    send(str): Writes from 1 to len(str) bytes, and returns an int representing the number of bytes written. Returns 0 or raises EOFError if the stream has been closed.
    recv(int): Reads from 1 to int bytes and returns them as a string. Returns 0 or raises EOFError if the stream has been closed.
    close(): Closes the socket.
    settimeout(n): Sets a (float) timeout on I/O operations.
  

Но я не знаю, как я могу назвать это «settimeout (float)» или установить его. Должен ли я создавать свой собственный объект с помощью этих 4 методов?

Заранее благодарю тебя, брат.

Ответ №1:

Я нашел, как это исправить… Я не знаю, лучший ли это способ, но он работает… Я добавил эту функцию в transport.py и теперь он отлично работает:

     def open_channel_with_timeout(self, kind,timeout,
                                dest_addr=None, src_addr=None):
    """
    Request a new channel to the server. `Channels <.Channel>` are
    socket-like objects used for the actual transfer of data across the
    session. You may only request a channel after negotiating encryption
    (using `connect` or `start_client`) and authenticating.

    :param str kind:
        the kind of channel requested (usually ``"session"``,
        ``"forwarded-tcpip"``, ``"direct-tcpip"``, or ``"x11"``)
    :param tuple dest_addr:
        the destination address (address   port tuple) of this port
        forwarding, if ``kind`` is ``"forwarded-tcpip"`` or
        ``"direct-tcpip"`` (ignored for other channel types)
    :param src_addr: the source address of this port forwarding, if
        ``kind`` is ``"forwarded-tcpip"``, ``"direct-tcpip"``, or ``"x11"``
    :param float timeout: the value of timeout before raising exception
    :return: a new `.Channel` on success

    :raises SSHException: if the request is rejected or the session ends
        prematurely
    """
    if not self.active:
        raise SSHException('SSH session not active')
    self.lock.acquire()
    try:
        chanid = self._next_channel()
        m = Message()
        m.add_byte(cMSG_CHANNEL_OPEN)
        m.add_string(kind)
        m.add_int(chanid)
        m.add_int(self.window_size)
        m.add_int(self.max_packet_size)
        if (kind == 'forwarded-tcpip') or (kind == 'direct-tcpip'):
            m.add_string(dest_addr[0])
            m.add_int(dest_addr[1])
            m.add_string(src_addr[0])
            m.add_int(src_addr[1])
        elif kind == 'x11':
            m.add_string(src_addr[0])
            m.add_int(src_addr[1])
        chan = Channel(chanid)
        self._channels.put(chanid, chan)
        self.channel_events[chanid] = event = threading.Event()
        self.channels_seen[chanid] = True
        chan._set_transport(self)
        chan._set_window(self.window_size, self.max_packet_size)
    finally:
        self.lock.release()
    self._send_user_message(m)
    egg_timer = 0.0
    while True:
        event.wait(0.1)
        egg_timer  = 0.1
        if egg_timer > timeout:
            e = socket.error('Unable to open channel (Timeout).')
            raise e
        if not self.active:
            e = self.get_exception()
            if e is None:
                e = SSHException('Unable to open channel.')
            raise e
        if event.isSet():
            break
    chan = self._channels.get(chanid)
    if chan is not None:
        return chan
    e = self.get_exception()
    if e is None:
        e = SSHException('Unable to open channel.')
    raise e