【问题标题】:how do I avoid the infinite loop when using the paramiko port forward demo?使用 paramiko 端口转发演示时如何避免无限循环?
【发布时间】:2011-08-29 21:35:01
【问题描述】:

我需要在 Python 中使用端口转发通过 SSH 隧道与远程 MySQL 数据库通信。我下载了 paramiko 包并试用了端口转发演示(forward.py)。它工作得很好,但我无法将它集成到我自己的脚本中(类似于下面的脚本)。当调用主转发函数时,它进入一个无限循环,我的其余代码不会执行。如何使用 forward.py 演示并越过无限循环?

我的脚本:

import paramiko
import forward
import MySQLdb
import cfg
import sys

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy())

try:
    client.connect(cfg.remhost, cfg.remport, username=cfg.user, password=cfg.password)
except Exception, e:
    print '*** Failed to connect to %s:%d: %r' % (cfg.remhost, cfg.remport, e)
    sys.exit(1)


try:
    forward.forward_tunnel(3306, cfg.remhost, 3306, client.get_transport())
except KeyboardInterrupt:
    print 'C-c: Port forwarding stopped.'
    sys.exit(0)

try:
    db = MySQLdb.connect('127.0.0.1', cfg.dbuser, cfg.dbpass, cfg.dbname)
except Exception, e:
    print 'Failed to connect to database'
    sys.exit(1)

try:
    cursor = self.db.cursor(MySQLdb.cursors.DictCursor)
    sql = 'SELECT * FROM  ' + cfg.dbtable
    cursor.execute(sql)
    results = cursor.fetchall()
    print str(len(results))
except Exception, e:
    print 'Failed to query database'
    sys.exit(1)

这是 forward.py 演示代码的主要部分:

class ForwardServer (SocketServer.ThreadingTCPServer):
    daemon_threads = True
    allow_reuse_address = True


class Handler (SocketServer.BaseRequestHandler):

    def handle(self):
        try:
            chan = self.ssh_transport.open_channel('direct-tcpip',
                                                   (self.chain_host, self.chain_port),
                                                   self.request.getpeername())
        except Exception, e:
            verbose('Incoming request to %s:%d failed: %s' % (self.chain_host,
                                                              self.chain_port,
                                                              repr(e)))
            return
        if chan is None:
            verbose('Incoming request to %s:%d was rejected by the SSH server.' %
                    (self.chain_host, self.chain_port))
            return

        verbose('Connected!  Tunnel open %r -> %r -> %r' % (self.request.getpeername(),
                                                            chan.getpeername(), (self.chain_host, self.chain_port)))
        while True:
            r, w, x = select.select([self.request, chan], [], [])
            if self.request in r:
                data = self.request.recv(1024)
                if len(data) == 0:
                    break
                chan.send(data)
            if chan in r:
                data = chan.recv(1024)
                if len(data) == 0:
                    break
                self.request.send(data)
        chan.close()
        self.request.close()
        verbose('Tunnel closed from %r' % (self.request.getpeername(),))


def forward_tunnel(local_port, remote_host, remote_port, transport):
    # this is a little convoluted, but lets me configure things for the Handler
    # object.  (SocketServer doesn't give Handlers any way to access the outer
    # server normally.)
    class SubHander (Handler):
        chain_host = remote_host
        chain_port = remote_port
        ssh_transport = transport
    ForwardServer(('', local_port), SubHander).serve_forever()


def verbose(s):
    if g_verbose:
        print s

【问题讨论】:

  • 好的,因为似乎没有人想回答这个问题,所以我的新问题是:我原来的问题让其他人反感怎么办?我应该改变什么才能让人们真正做出回应?我需要改写它或添加更多信息吗?

标签: python multithreading infinite-loop paramiko portforwarding


【解决方案1】:

我认为您需要处理程序转发代码在其自己的线程中运行并使用队列与其通信。

或者在你自己的循环中提取相关的调用和内容。嗯,我不确定这到底是如何工作的。

您希望您的 mysql 调用在您的程序中使用它还是从其他程序转发?

【讨论】:

  • 感谢您的回复。看来我需要学习如何在 Python 中运行线程。我不需要转发脚本成为我的数据库脚本的一部分,它们也不需要相互通信。数据库调用被发送到 127.0.0.1:3306 转发脚本已经转发到远程服务器。我只是很惊讶我找不到已经在某处发布的示例。
  • 我试过这样做,但无法让它工作。这是因为我的网络主机拒绝端口转发。我尝试通过编写自己的应用程序来做到这一点,该应用程序在创建 SSH 连接后在远程主机上运行,​​但无法使其工作。我确实收到了一些文本,但它无法与 mysql 服务器正确握手。抱歉,当我意识到我的网络主机是共享主机并阻止端口转发时,我不再搞乱 Paramiko 的东西,所以我无法提供更多帮助。
【解决方案2】:

我是一个名为 Python X2Go 的 Pyhon 模块的上游作者,该模块大量使用 Paramiko 进行 SSH 会话管理。

请看一下代码中的forward.py文件: http://code.x2go.org/gitweb?p=python-x2go.git;a=blob;f=x2go/forward.py

Python X2Go 的代码大量使用 Python gevent 进行服务器-客户端通信、端口转发等。

您好, 迈克

【讨论】:

  • 欢迎来到 Stack Overflow。请阅读我们的faqPlease do not post answers that are just a link:在您的帖子中包含有用的内容,并提供链接以供参考。在这里,您能否包含一些演示端口转发的代码(10-20 行会很棒)?
猜你喜欢
  • 1970-01-01
  • 2019-05-01
  • 1970-01-01
  • 2018-01-27
  • 1970-01-01
  • 2021-12-04
  • 1970-01-01
  • 1970-01-01
  • 2020-09-04
相关资源
最近更新 更多