使用paramiko端口转发演示时如何避免无限循环?

| 我需要在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
    
已邀请:
我认为您需要处理程序转发代码以在其自己的线程中运行并使用队列与之通信。 或者拔出相关的电话,将其放入您自己的循环中。嗯,我不确定这是如何工作的。 您是要让mysql调用在您的程序中使用它还是从其他程序转发它?     
我是一个称为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进行服务器-客户端通信,端口转发等。 问候, 麦克风     

要回复问题请先登录注册