通过Python中的SSH隧道连接到Postgresql数据库

时间:2016-01-23 16:22:13

标签: python database postgresql ssh ssh-tunnel

我正在尝试连接以远程连接到服务器,然后使用python访问它的本地数据库。我成功连接到服务器,虽然我似乎无法连接到服务器上的数据库。我的代码如下:

import psycopg2
from sshtunnel import SSHTunnelForwarder

try:

    with SSHTunnelForwarder(
         ('<server ip address>', 22),
         ssh_private_key="</path/to/private/ssh/key>",
         ssh_username="<server username>",
         remote_bind_address=('localhost', 5432)) as server:

        print "server connected"

        conn = psycopg2.connect(database="<dbname>",port=server.local_bind_port)
        curs = conn.cursor()
        print "database connected

except:
    print "Connection Failed"

这是我在互联网上找到的一些示例代码。我还尝试了下面的连接语句来代替上面的连接语句:

params = {
  'database': '<dbname>',
  'user': '<dbusername>',
  'password': '<dbuserpass>',
  'host': 'localhost',
  'port': 5432
}
conn = psycopg2.connect(**params)

我知道我可以连接到数据库,因为在我的机器上;我可以使用sqlectron隧道并正确连接。

如果我不清楚上面要做什么,我需要在我的计算机上使用私有ssh密钥(通过正常工作)将ssh隧道导入我的远程服务器,然后我需要连接到PostgreSQL端口localhost5432上的数据库。

我目前正在获取两种尝试连接方式的当前错误消息:

2016-01-23 11:16:10,978 | ERROR   | Tunnel: 0.0.0.0:49386 <> localhost:5432 error: (9, 'Bad file descriptor')

3 个答案:

答案 0 :(得分:3)

我不知道这是否有用,但我也必须通过SSH隧道连接到Postgresql数据库。我成功地使用您的代码进行了一些修改:

import psycopg2
from sshtunnel import SSHTunnelForwarder

try:

    with SSHTunnelForwarder(
         ('<server ip address>', 22),
         #ssh_private_key="</path/to/private/ssh/key>",
         ### in my case, I used a password instead of a private key
         ssh_username="<server username>",
         ssh_password="<mypasswd>", 
         remote_bind_address=('localhost', 5432)) as server:

         server.start()
         print "server connected"

         params = {
             'database': '<dbname>',
             'user': '<dbusername>',
             'password': '<dbuserpass>',
             'host': 'localhost',
             'port': local_bind_port
             }

         conn = psycopg2.connect(**params)
         curs = conn.cursor()
         print "database connected"

except:
    print "Connection Failed"

添加server.start()后,代码运行良好。此外,“数据库连接”后,引号丢失了。 我希望这对您有所帮助,感谢您分享您的代码!

答案 1 :(得分:2)

这两个例子都非常有用。我在db连接中手动绑定本地端口时遇到问题。我猜我们的服务器上有动态端口?我结合了两个例子的元素。使用sever.local_bind_port可能是一个更健壮和动态的解决方案。

from sshtunnel import SSHTunnelForwarder #Run pip install sshtunnel
from sqlalchemy.orm import sessionmaker #Run pip install sqlalchemy

with SSHTunnelForwarder(
    ('<remote server ip>', 22), #Remote server IP and SSH port
    ssh_username = "<username>",
    ssh_password = "<password>",
    remote_bind_address=('<local server ip>', 5432)) as server: #PostgreSQL server IP and sever port on remote machine

    server.start() #start ssh sever
    print 'Server connected via SSH'

    #connect to PostgreSQL
    local_port = str(server.local_bind_port)
    engine = create_engine('postgresql://<username>:<password>@127.0.0.1:' + local_port +'/database_name')

    Session = sessionmaker(bind=engine)
    session = Session()

    print 'Database session created'

    #test data retrieval
    test = session.execute("SELECT * FROM database_table")
    for row in test:
        print row['id']

    session.close()

答案 2 :(得分:-1)

此解决方案解决了Windows 10上的Python3问题。

我必须添加:

from sqlalchemy import create_engine