为封装的MySQL提供密码

时间:2009-03-06 17:58:50

标签: python mysql subprocess

问候。

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

我写的原始代码可以看作here

下面的这个变种非常相似,虽然我会省略测试程序以缩短它:

#!/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”和“communication”函数之间没有代码),我的包装函数就可以工作。


两个新想法,月份laster:

  1. 使用pexpect会让我提供密码。它模拟tty并获得所有输出,甚至是绕过stdout和stderr的输出。

  2. 在早期的alpha中有一个名为MySQL Connector/Python的项目,它允许提供一个纯python库来访问MySQL,而不需要你编译任何C代码。

4 个答案:

答案 0 :(得分:6)

你可以简单地构建一个my.cnf文件并指向mysql命令。显然,您需要使用permissions / 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

答案 1 :(得分:3)

唯一安全的方法是使用MySQL cnf文件作为其他海报之一。你也可以传递一个MYSQL_PWD env变量,但这也是不安全的:http://dev.mysql.com/doc/refman/5.0/en/password-security.html

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

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

答案 2 :(得分:2)

这可能是Windows / SQL Server功能,但您是否可以使用可信连接(即使用您的操作系统登录名/密码来访问数据库)?对于MySQL,可能存在OS X等价物。

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

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

答案 3 :(得分:0)

试试这个:

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

return stdout

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