代码之家  ›  专栏  ›  技术社区  ›  Clinton Blackmore

为包装好的MySQL提供密码

  •  2
  • Clinton Blackmore  · 技术社区  · 17 年前

    问候语。

    我编写了一个在子进程中调用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
    

    在提供密码之前,我确实尝试过先读取输出,但没有成功。我还试着传递密码

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


    1. 使用 pexpect 请允许我提供密码。它模拟tty并获取所有输出,甚至是绕过标准输出和标准输出的输出。

    2. 有一个项目叫做 MySQL Connector/Python

    4 回复  |  直到 16 年前
        1
  •  6
  •   Zoredache    17 年前

    您可以简单地构建一个my.cnf文件,并在mysql命令上指向该文件。显然,您需要使用权限/ACL保护该文件。但是,它不应该真的比在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
    
        2
  •  3
  •   Daniel Lopez    17 年前

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

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

    http://bitnami.org/stacks

        3
  •  2
  •   tgray    17 年前

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

    不管怎样,只是个想法。

        4
  •  0
  •   Jason Coon    17 年前

    试试这个:

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

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