2

问候。

我写了一个在子进程中调用 MySQL 的小 Python 脚本。[是的,我知道正确的方法是使用 MySQLdb,但在 OS X Leopard 下编译它很痛苦,如果我想在不同架构的计算机上使用该脚本,可能会更痛苦。] 子进程技术有效,前提是我在启动进程的命令中提供密码;但是,这意味着机器上的其他用户可以看到密码。

我写的原始代码可以在这里看到。

下面的这个变体非常相似,尽管我将省略测试例程以使其更短:

#!/usr/bin/env python

from subprocess import Popen, PIPE

# Set the command you need to connect to your database
mysql_cmd_line = "/Applications/MAMP/Library/bin/mysql -u root -p"
mysql_password = "root"

def RunSqlCommand(sql_statement, database=None):

    """Pass in the SQL statement that you would like executed.
    Optionally, specify a database to operate on.  Returns the result."""

    command_list = mysql_cmd_line.split()
    if database:
        command_list.append(database)

    # Run mysql in a subprocess
    process = Popen(command_list, stdin=PIPE, stdout=PIPE,
                    stderr=PIPE, close_fds=True)

    #print "Asking for output"
    #needs_pw = process.stdout.readline()
    #print "Got: " + needs_pw

    # pass it in the password
    process.stdin.write(mysql_password + "\n")

    # pass it our commands, and get the results
    #(stdout, stderr) = process.communicate( mysql_password + "\n" + sql_statement)
    (stdout, stderr) = process.communicate( sql_statement )

    return stdout

我怀疑 MySQL 密码提示实际上不在 stdout(或 stderr)上,尽管我不知道那可能是怎么回事,或者这是否意味着我可以捕获它。

在提供密码之前,我确实尝试过先读取输出,但它没有用。我也试过传递密码

同样,如果我在命令行上提供密码(因此在“Popen”和“communicate”函数之间没有代码)我的包装函数可以工作。


两个新想法,几个月后:

  1. 使用pexpect可以让我提供密码。它模拟一个 tty 并获得所有输出,即使是绕过 stdout 和 stderr 的输出。

  2. 有一个名为MySQL Connector/Python的项目,处于早期 alpha 阶段,它将允许提供一个纯 Python 库来访问 MySQL,而无需您编译任何 C 代码。

4

4 回答 4

6

您可以简单地构建一个 my.cnf 文件并在 mysql 命令上指向该文件。显然,您需要使用权限/acls 来保护该文件。但它不应该比在你的 python 脚本中拥有密码或你的 python 脚本的配置更安全。

所以你会做类似的事情

mysql_cmd_line = "/Applications/MAMP/Library/bin/mysql --defaults-file=credentials.cnf"

你的配置看起来像这样

[client]
host     = localhost
user     = root
password = password
socket   = /var/run/mysqld/mysqld.sock
于 2009-03-06T18:22:20.290 回答
3

唯一安全的方法是使用 MySQL cnf 文件,正如其他海报中提到的那样。您也可以传递一个 MYSQL_PWD 环境变量,但这也是不安全的:http ://dev.mysql.com/doc/refman/5.0/en/password-security.html

或者,您可以使用 Unix 套接字文件与数据库进行通信,并稍作调整,您可以在用户 ID 级别控制权限。

更好的是,您可以使用免费的 BitNami 堆栈 DjangoStack,它为 OS X(以及 Windows 和 Linux)预编译了 Python 和 MySQLDB http://bitnami.org/stacks

于 2009-03-06T18:38:01.750 回答
2

这可能是 Windows / SQL Server 功能,但您可以使用受信任的连接(即使用您的操作系统登录名/密码访问数据库)吗?MySQL 可能有一个 OS X 等价物。

或者您可能只需要设置您的数据库以使用操作系统登录名和密码,这样您就不需要将其保存在您的代码中。

无论如何,只是一个想法。

于 2009-03-06T18:15:44.767 回答
0

试试这个:

process.stdin.write(mysql_password + "\n")
process.communicate()
(stdout, stderr) = process.communicate( sql_statement )
process.stdin.close()

return stdout

调用communicate() 来强制发送你刚刚写入缓冲区的内容。此外,完成后关闭标准输入也很好。

于 2009-03-06T18:24:09.177 回答