Pergunta

Saudações.

Eu escrevi um script python pouco que chama MySQL em um subprocesso. [Sim, eu sei que a abordagem correta é usar MySQLdb, mas compilá-lo sob OS X Leopard é uma dor, e provavelmente mais doloroso se eu queria usar o script em computadores de diferentes arquiteturas.] As obras técnica subprocess, desde que I fornecer a senha no comando que inicia o processo; no entanto, isso significa que outros usuários na máquina podia ver a senha.

O código original que eu escrevi pode ser visto aqui .

Esta variante abaixo é muito semelhante, embora eu vou omitir a rotina de teste para mantê-lo mais curto:

#!/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

Estou desconfiado de que a solicitação de senha MySQL não é realmente em stdout (ou stderr), embora eu não sei como isso pode ser ou se isso significa que eu poderia prendê-lo.

Eu tentei ler a saída do primeiro, antes de fornecer uma senha, mas não funcionou. Eu também tentei passar a senha

Mais uma vez, se eu fornecer a senha na linha de comando (e, portanto, não têm nenhum código entre o "Popen" e "comunicar" funções) meus trabalhos de função embrulhadas.


Dois novos pensamentos, meses laster:

  1. Usando pexpect me deixaria fornecer uma senha. Ele simula um tty e recebe toda a saída, mesmo que ignora stdout e stderr.

  2. Há um projeto chamado MySQL Connector / Python , em alfa precoce, que permitirá fornecer uma biblioteca pura python para acessar MySQL, sem a necessidade de compilar qualquer código C.

Foi útil?

Solução

Você poderia simplesmente criar um arquivo my.cnf e apontam para que no comando mysql. Obviamente você vai querer proteger esse arquivo com permissões / acls. Mas não deve ser realmente um mais / menos segura em seguida, ter a senha em seu script python, ou a configuração para o seu script python.

Assim que você faria algo assim

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

e sua configuração ficaria mais ou menos assim

[client]
host     = localhost
user     = root
password = password
socket   = /var/run/mysqld/mysqld.sock

Outras dicas

O único método seguro é usar um arquivo MySQL CNF como um dos outros cartazes menciona. Você também pode passar uma variável MYSQL_PWD env, mas isso é inseguro também: http://dev.mysql.com/doc/refman/5.0/en/password-security.html

Como alternativa, você pode se comunicar com o banco de dados usando um arquivo socket Unix e com um pouco de ajustes você pode controlar permissões no nível do ID do usuário.

Mesmo melhor, você pode usar o livre BitNami pilha DjangoStack que tem Python e mysqldb pré-compilados para OS X (E Windows e Linux) http://bitnami.org/stacks

Este pode ser um / recurso SQL Server do Windows, mas você pode usar uma conexão confiável (ou seja, usar o seu login OS / senha para acessar o DB)? Pode haver um equivalente OS X para o MySQL.

Ou você pode só precisa configurar seu banco de dados para usar o login OS e senha para que você não precisa mantê-lo em seu código.

De qualquer forma, apenas uma idéia.

Tente isto:

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

return stdout

Chamada comunicar () para forçar o que você acabou de escrever para o buffer para enviar. Além disso, é bom para perto stdin quando você está feito.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top