从 python 连接到远程服务器中的 MySQL
Conecting to MySQL in a remote server from python
我在 MacOS X 10.12 上使用 Python 3.5、pymysql 0.7.6。
我正在尝试使用 python 访问远程服务器中的 MySQL 数据库。我可以使用以下命令从命令行访问:
ssh root@XXX.XXX.XXX.XXX
root@XXX.XXX.XXX.XXX's password: my_server_password
然后在服务器中:
mysql my_database -p
Enter password: my_database_password
它有效,我可以用我的数据库做各种各样的事情。现在,我尝试在 python 内执行相同的操作,遵循文档或我在此处其他帖子中找到的大量示例:
import pymysql
cnx = pymysql.connect(host='XXX.XXX.XXX.XXX', port='3306', user='root', password='my_server_password', db='my_database')
它不起作用,出现错误:
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'XXX.XXX.XXX.XXX' ([Errno 61] Connection refused)")
凭据是正确的凭据,我已经检查端口是否正确,正如其他帖子中所建议的那样。我怀疑这可能与也有密码的数据库有关,而不仅仅是服务器,但我还没有找到包含这两个密码的任何方法。事实上,我不确定连接命令中应该包含哪个密码,是服务器密码还是数据库密码。它不适用于他们两个。
那么,对于这里可能出现的问题或者我是否遗漏了重要信息,您有什么建议吗?
当您 运行 使用 mysql
命令时,您是在 SSH shell 中执行此操作。也就是说,您正在通过 localhost
连接连接到远程计算机上的服务器 运行ning。该远程服务器似乎未设置为允许与其远程连接,仅允许来自机器本身的连接。
您需要让 python 脚本以与您相同的方式通过 SSH 连接到 MySQL 服务器。您可以打开 SSH 隧道到远程服务器上的端口 3306。
我喜欢用于此目的的模块是:https://pypi.python.org/pypi/sshtunnel
from sshtunnel import SSHTunnelForwarder
import pymysql
server = SSHTunnelForwarder(
'XXX.XXX.XXX.XXX',
ssh_username='root',
ssh_password='my_server_password',
remote_bind_address=('127.0.0.1', 3306)
)
server.start()
cnx = pymysql.connect(
host='127.0.0.1',
port=server.local_bind_port,
user='root',
password='my_database_password',
db='my_database'
)
# Make sure to call server.stop() when you want to disconnect
# after calling cnx.close()
根据给出的信息,我建议您尝试以下操作:
确保MySQL绑定地址是“0.0.0.0”。您可以通过编辑 /etc/mysql/my.cnf
并检查 bind-address
选项设置为“0.0.0.0”
来完成此操作
确保端口已从您的远程计算机打开。安装 "nmap" 然后使用 nmap -sS -O -p3306 <public-server-ip>
。如果看到类似 3306/mysql open
的东西,一切都很好。如果没有,您需要确保您的防火墙没有阻止该端口。
正如 Rocket Hazmat 所建议的那样,您可能希望使用 SSH 隧道来降低直接暴露 MySQL 端口的风险,因为数据可能以明文形式发送。如果您只需要在部署到服务器之前在本地测试您的代码,您可以在 运行 您的 Python 代码之前使用以下命令:ssh -f user@serverip -L 3306:127.0.0.1:3306 -N
。在这种情况下,您不需要完成第一步和第二步。
工作代码
#!/usr/local/bin/python3
# -*- coding: utf-8 -*-
import pymysql
import sshtunnel
from sshtunnel import SSHTunnelForwarder
server = SSHTunnelForwarder(
('xx.xx.xx.xx', 22),
ssh_username='deploy',
ssh_pkey='~/.ssh/id_rsa',
remote_bind_address=('127.0.0.1', 3306)
)
server.start()
con = pymysql.connect(host='127.0.0.1', user='root', passwd='mysql', db='backoffice_demo', port=server.local_bind_port)
with con:
cur = con.cursor()
cur.execute("SELECT VERSION()")
version = cur.fetchone()
print("Database version: {}".format(version[0]))
我在 MacOS X 10.12 上使用 Python 3.5、pymysql 0.7.6。
我正在尝试使用 python 访问远程服务器中的 MySQL 数据库。我可以使用以下命令从命令行访问:
ssh root@XXX.XXX.XXX.XXX
root@XXX.XXX.XXX.XXX's password: my_server_password
然后在服务器中:
mysql my_database -p
Enter password: my_database_password
它有效,我可以用我的数据库做各种各样的事情。现在,我尝试在 python 内执行相同的操作,遵循文档或我在此处其他帖子中找到的大量示例:
import pymysql
cnx = pymysql.connect(host='XXX.XXX.XXX.XXX', port='3306', user='root', password='my_server_password', db='my_database')
它不起作用,出现错误:
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'XXX.XXX.XXX.XXX' ([Errno 61] Connection refused)")
凭据是正确的凭据,我已经检查端口是否正确,正如其他帖子中所建议的那样。我怀疑这可能与也有密码的数据库有关,而不仅仅是服务器,但我还没有找到包含这两个密码的任何方法。事实上,我不确定连接命令中应该包含哪个密码,是服务器密码还是数据库密码。它不适用于他们两个。
那么,对于这里可能出现的问题或者我是否遗漏了重要信息,您有什么建议吗?
当您 运行 使用 mysql
命令时,您是在 SSH shell 中执行此操作。也就是说,您正在通过 localhost
连接连接到远程计算机上的服务器 运行ning。该远程服务器似乎未设置为允许与其远程连接,仅允许来自机器本身的连接。
您需要让 python 脚本以与您相同的方式通过 SSH 连接到 MySQL 服务器。您可以打开 SSH 隧道到远程服务器上的端口 3306。
我喜欢用于此目的的模块是:https://pypi.python.org/pypi/sshtunnel
from sshtunnel import SSHTunnelForwarder
import pymysql
server = SSHTunnelForwarder(
'XXX.XXX.XXX.XXX',
ssh_username='root',
ssh_password='my_server_password',
remote_bind_address=('127.0.0.1', 3306)
)
server.start()
cnx = pymysql.connect(
host='127.0.0.1',
port=server.local_bind_port,
user='root',
password='my_database_password',
db='my_database'
)
# Make sure to call server.stop() when you want to disconnect
# after calling cnx.close()
根据给出的信息,我建议您尝试以下操作:
确保MySQL绑定地址是“0.0.0.0”。您可以通过编辑
/etc/mysql/my.cnf
并检查bind-address
选项设置为“0.0.0.0” 来完成此操作
确保端口已从您的远程计算机打开。安装 "nmap" 然后使用
nmap -sS -O -p3306 <public-server-ip>
。如果看到类似3306/mysql open
的东西,一切都很好。如果没有,您需要确保您的防火墙没有阻止该端口。
正如 Rocket Hazmat 所建议的那样,您可能希望使用 SSH 隧道来降低直接暴露 MySQL 端口的风险,因为数据可能以明文形式发送。如果您只需要在部署到服务器之前在本地测试您的代码,您可以在 运行 您的 Python 代码之前使用以下命令:ssh -f user@serverip -L 3306:127.0.0.1:3306 -N
。在这种情况下,您不需要完成第一步和第二步。
工作代码
#!/usr/local/bin/python3
# -*- coding: utf-8 -*-
import pymysql
import sshtunnel
from sshtunnel import SSHTunnelForwarder
server = SSHTunnelForwarder(
('xx.xx.xx.xx', 22),
ssh_username='deploy',
ssh_pkey='~/.ssh/id_rsa',
remote_bind_address=('127.0.0.1', 3306)
)
server.start()
con = pymysql.connect(host='127.0.0.1', user='root', passwd='mysql', db='backoffice_demo', port=server.local_bind_port)
with con:
cur = con.cursor()
cur.execute("SELECT VERSION()")
version = cur.fetchone()
print("Database version: {}".format(version[0]))