Domanda

Saluti.

Ho scritto un piccolo script Python che chiama MySQL in un sottoprocesso. [Sì, so che l'approccio giusto è usare MySQLdb, ma compilarlo sotto OS X Leopard è una seccatura, e probabilmente più doloroso se volessi usare lo script su computer di diverse architetture.] La tecnica del sottoprocesso funziona, a condizione che Fornisco la password nel comando che avvia il processo; tuttavia, ciò significa che altri utenti sulla macchina potrebbero vedere la password.

Il codice originale che ho scritto può essere visto qui .

Questa variante di seguito è molto simile, anche se ometterò la routine di test per renderla più breve:

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

Sono sospettoso che la richiesta della password di MySQL non sia effettivamente su stdout (o stderr), anche se non so come potrebbe essere o se ciò significhi che potrei intrappolarlo.

Ho provato prima a leggere l'output, prima di fornire una password, ma non ha funzionato. Ho anche provato a passare la password

Ancora una volta, se fornisco la password sulla riga di comando (e quindi non ho un codice tra le funzioni "Popen" e "Comunicazione") la mia funzione "wrapped" funziona.


Due nuovi pensieri, mesi dopo:

  1. L'uso di pexpect mi permetterebbe di fornire una password. Simula un tty e ottiene tutto l'output, anche quello che ignora stdout e stderr.

  2. Esiste un progetto chiamato MySQL Connector / Python , in versione alpha, che consentirà di fornire una libreria Python pura per l'accesso a MySQL, senza la necessità di compilare alcun codice C.

È stato utile?

Soluzione

Potresti semplicemente creare un file my.cnf e puntare a quello sul comando mysql. Ovviamente ti consigliamo di proteggere quel file con autorizzazioni / acls. Ma non dovrebbe essere davvero più / meno sicuro che avere la password nel tuo script Python o la configurazione per il tuo script Python.

Quindi faresti qualcosa del genere

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

e la tua configurazione sarebbe simile a questa

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

Altri suggerimenti

L'unico metodo sicuro è usare un file cnf di MySQL come uno degli altri poster menzionati. Puoi anche passare una variabile env MYSQL_PWD, ma anche questa non è sicura: http://dev.mysql.com/doc/refman/5.0/en/password-security.html

In alternativa, puoi comunicare con il database usando un file socket Unix e con un po 'di modifica puoi controllare le autorizzazioni a livello di ID utente.

Ancora meglio, puoi usare lo stack gratuito BitNami DjangoStack con Python e MySQLDB precompilati per OS X (e Windows e Linux) http://bitnami.org/stacks

Potrebbe trattarsi di una funzionalità di Windows / SQL Server, ma potresti utilizzare una connessione sicura (ovvero utilizzare il tuo login / password del sistema operativo per accedere al DB)? Potrebbe esserci un equivalente di OS X per MySQL.

Oppure potresti aver solo bisogno di impostare il tuo DB per utilizzare il login e la password del SO in modo da non doverlo conservare nel tuo codice.

Comunque, solo un'idea.

Prova questo:

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

return stdout

Chiama communic () per forzare l'invio di ciò che hai appena scritto nel buffer. Inoltre, è utile chiudere stdin al termine.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top