Как избежать бесконечного цикла при использовании демо-порта paramiko forward? - PullRequest
0 голосов
/ 20 мая 2011

Мне нужно использовать переадресацию портов в Python для связи с удаленной базой данных MySQL через туннель SSH.Я скачал пакет 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

Ответы [ 2 ]

1 голос
/ 25 мая 2012

Я являюсь автором основного модуля Pyhon под названием Python X2Go, который интенсивно использует Paramiko для управления сеансами SSH.

Пожалуйста, взгляните на файл forward.py в коде: http://code.x2go.org/gitweb?p=python-x2go.git;a=blob;f=x2go/forward.py

Код Python X2Go интенсивно использует Python Gevent для связи сервер-клиент, переадресации портов и т. Д.

Привет, Майк

1 голос
/ 05 июля 2011

Я думаю, вам нужен код переадресации обработчика для запуска в своем собственном потоке и использования очередей для связи с ним.

Или вытащите соответствующие вызовы и поместите их в свой цикл. Хммм, я не уверен, как именно это работает.

Вы хотите, чтобы ваши вызовы mysql работали с ним в вашей программе или перенаправляли из другой программы?

...