[英]Accessing MySQL database using Python over SSH Tunnel port forwarding
我在遠程服務器上有 MySQL 數據庫,在訪問它之前,我需要使用 ssh 隧道進行端口轉發。 如果沒有 python,我通常會執行以下命令並在 shell 中輸入我的密碼。 通過身份驗證后,我通過連接到 localhost:3306 來訪問 mysql 工作台中的數據庫。 我在 Mac OS X El Capitan 上做所有事情
ssh -L 3306:remote.database.host:3306 xxxx@xxxx.com
我現在想從 Python 訪問數據庫,這是我使用的腳本:
import pexpect
import time
import sqlalchemy as sql
from sqlalchemy.engine.url import URL
myDB = URL(drivername='mysql+pymysql', host='localhost',
database='test_db',
username='roott',
password='xxxxxx',
port=3306)
child = pexpect.spawnu('ssh -L 3306:remote.database.host:3306 xxxx@xxxx.com')
child.expect (u'password:')
child.sendline ('xxxxx')
while child.isalive():
try:
engine = sql.create_engine(name_or_url=myDB)
connection = engine.connect()
connection.close()
break
finally:
child.close()
上面的腳本給了我以下錯誤:
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost' ([Errno 61] Connection refused)")
我還通過參考Python 中的jsjc 解決方案- SSH Tunnel Setup and MySQL DB Access嘗試使用 sshtunnelforwarder,但它也不起作用。
from sshtunnel import SSHTunnelForwarder
from sqlalchemy import create_engine
from sqlalchemy.engine.url import URL
with SSHTunnelForwarder(('ssh_host', 22),
ssh_username='xxxxx',
ssh_pkey='/path/to/key/file',
local_bind_address=('127.0.0.1', 3306),
remote_bind_address=('127.0.0.1', 3306)) as server:
myDB = URL(drivername='mysql+pymysql', host='127.0.0.1',
database='test_db',
username='roott',
password='xxxxx',
port=3306
)
engine = create_engine(name_or_url=myDB)
connection = engine.connect()
connection.close()
我將以下信息登錄到控制台,但沒有任何反應,它只是掛在那里,我必須手動終止程序。
DEBUG:paramiko.transport:starting thread (client mode): 0xbe25940
DEBUG:paramiko.transport:Local version/idstring: SSH-2.0-paramiko_1.16.0
DEBUG:paramiko.transport:Remote version/idstring: SSH-2.0-OpenSSH_6.2
INFO:paramiko.transport:Connected (version 2.0, client OpenSSH_6.2)
DEBUG:paramiko.transport:........
DEBUG:paramiko.transport:Kex agreed: diffie-hellman-group1-sha1
DEBUG:paramiko.transport:Cipher agreed: aes128-ctr
DEBUG:paramiko.transport:MAC agreed: hmac-sha2-256
DEBUG:paramiko.transport:Compression agreed: none
DEBUG:paramiko.transport:kex engine KexGroup1 specified hash_algo <built-in function openssl_sha1>
DEBUG:paramiko.transport:Switch to new keys ...
DEBUG:paramiko.transport:Attempting public-key auth...
DEBUG:paramiko.transport:userauth is OK
INFO:paramiko.transport:Auth banner: b'Amazon Linux AMI release 2014.09\nKernel \\r on an \\m\n'
INFO:paramiko.transport:Authentication continues...
DEBUG:paramiko.transport:Methods: ['password']
DEBUG:paramiko.transport:[chan 0] Max packet in: 32768 bytes
WARNING:paramiko.transport:Oops, unhandled type 3
這是我以前遇到的一個問題。 問題是當使用localhost
作為數據庫服務器時,驅動程序堅持連接到本地 unix 套接字,而不是使用指定端口通過環回接口連接。
解決方法是將數據庫服務器更改為除localhost之外的其他內容。 這將導致驅動程序使用您指定的服務器/端口,而不是嘗試連接到本地套接字。
myDB = URL(drivername='mysql+pymysql', host='127.0.0.1', ...)
myDB = URL(drivername='mysql+pymysql', host='your.ip.add.ress', ...)
myDB = URL(drivername='mysql+pymysql', host='your.hostname', ...)
我不知道 OP 是否已經解決了這個問題(已經 3 年了,所以我希望如此),但我的解決方案非常簡單。 我只需要在“with”子句中縮進 myDB、引擎和連接定義。 否則,ssh 隧道將在您有機會連接到數據庫之前關閉:
with SSHTunnelForwarder(('ipforsshing', sshport), ssh_username='sshuser', ssh_pkey='privatekeypath', local_bind_address=('127.0.0.1', 3305), remote_bind_address=('127.0.0.1', 3306)) as server:
adcrawl_db = URL(drivername='mysql+pymysql', host='127.0.0.1', database='dbname', username='dbusername',password='dbpassword', port=3305)
engine = create_engine(name_or_url=adcrawl_db)
connection = engine.connect()
print("CONNECTED!")
connection.close()
希望這對未來的任何人都有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.