Pregunta

Saludos.

He escrito un pequeño script en python que llama a MySQL en un subproceso. [Sí, sé que el enfoque correcto es usar MySQLdb, pero compilarlo bajo OS X Leopard es un dolor, y probablemente más doloroso si quisiera usar el script en computadoras de diferentes arquitecturas.] La técnica de subproceso funciona, siempre que Suministro la contraseña en el comando que inicia el proceso; sin embargo, eso significa que otros usuarios en la máquina podrían ver la contraseña.

El código original que escribí se puede ver aquí .

Esta variante a continuación es muy similar, aunque omitiré la rutina de prueba para hacerlo más corto:

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

Sospecho que la solicitud de contraseña de MySQL no está realmente en stdout (o stderr), aunque no sé cómo podría ser eso o si significa que podría interceptarlo.

Intenté leer primero la salida, antes de proporcionar una contraseña, pero no funcionó. También intenté pasar la contraseña

Una vez más, si proporciono la contraseña en la línea de comandos (y, por lo tanto, no tengo ningún código entre las funciones " Popen " y quot quot; comunicar ") mi función ajustada funciona.


Dos nuevos pensamientos, meses laster:

  1. El uso de pexpect me permitiría proporcionar una contraseña. Simula un tty y obtiene toda la salida, incluso la que omite stdout y stderr.

  2. Hay un proyecto llamado MySQL Connector / Python , en la versión alfa temprana, que permitirá proporcionar una biblioteca de python pura para acceder a MySQL, sin necesidad de compilar ningún código C.

¿Fue útil?

Solución

Puede simplemente construir un archivo my.cnf y señalarlo en el comando mysql. Obviamente, querrá proteger ese archivo con permisos / acls. Pero no debería ser realmente más / menos seguro que tener la contraseña en su script de python, o la configuración de su script de python.

Así que harías algo como

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

y tu configuración se vería así como

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

Otros consejos

El único método seguro es usar un archivo cnf de MySQL como una de las otras menciones de los carteles. También puede pasar una variable env MYSQL_PWD, pero eso también es inseguro: http://dev.mysql.com/doc/refman/5.0/en/password-security.html

Alternativamente, puedes comunicarte con la base de datos utilizando un archivo de socket Unix y con un poco de ajustes puedes controlar los permisos en el nivel de identificación de usuario.

Aún mejor, puedes usar la pila de BitNami gratuita DjangoStack que tiene Python y MySQLDB precompilados para OS X (y Windows y Linux) http://bitnami.org/stacks

Esto puede ser una característica de Windows / SQL Server, pero ¿podría usar una conexión de confianza (es decir, usar el nombre de usuario / contraseña de su sistema operativo para acceder a la base de datos)? Puede haber un equivalente de OS X para MySQL.

O puede que solo necesite configurar su base de datos para utilizar el inicio de sesión y la contraseña del sistema operativo para que no tenga que guardarla en su código.

De todos modos, solo una idea.

Prueba esto:

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

return stdout

Llame a communic () para forzar lo que acaba de escribir en el búfer para enviar. Además, es bueno cerrar la entrada estándar cuando hayas terminado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top