Elimina i messaggi di avviso utilizzando mysql dal Terminale, ma la password scritta nello script bash


273

Quando ho provato a eseguire il seguente comando su MySQL dal Terminale:

mysql -u $user -p$password -e "statement"

L'esecuzione funziona come previsto, ma emette sempre un avviso:

Avvertenza: l'utilizzo di una password sull'interfaccia della riga di comando può essere insicuro.

Tuttavia, devo condurre la dichiarazione sopra usando una variabile d'ambiente ( $password) che memorizza la mia password, perché voglio eseguire il comando iterativamente nello script bash da Terminal, e sicuramente non mi piace l'idea di aspettare un prompt che appare e costringendomi a inserire la mia password 50 o 100 volte in un singolo script. Quindi, ecco la mia domanda:

  • È possibile sopprimere l'avvertimento? Il comando funziona correttamente come ho affermato, ma la finestra diventa piuttosto disordinata quando eseguo il ciclo ed eseguo il comando 50 o 100 volte.

  • Devo obbedire al messaggio di avviso e NON scrivere la mia password nel mio script? In tal caso, devo digitare la mia password ogni volta che il prompt mi ​​costringe a farlo?

Correre man mysqlnon aiuta, solo dicendo

--show-warnings
Fa sì che vengano visualizzati degli avvisi dopo ogni istruzione, se presenti. Questa opzione si applica alla modalità interattiva e batch.

e non menziona nulla su come disattivare la funzionalità, se non mi manca qualcosa.

Sono su OS X 10.9.1 Mavericks e uso MySQL 5.6 da homebrew.


14
Il modo consigliato è quello di memorizzare la password in un file di opzioni (smth come [client] password=my_passwordin ~/.my.cnf). Sicuramente ha anche alcune implicazioni per la sicurezza, ma almeno non è accessibile a chiunque possa eseguirlo pse tu hai il controllo su di esso con i permessi dei file.
Anton Kovalenko il

4
mysql -u root password root -e "statement" > /dev/null?

A proposito, puoi anche usare qualcosa come Python pexcept. Può eseguire inserimenti di terminali e gestire anche il feedback fornito dal comando. In questo modo puoi semplicemente saltare

6
Il modo raccomandato IMO penalizza quelli che fanno la cosa giusta per proteggere quelli che fanno la cosa sbagliata. Se la password è memorizzata in un file di script, non verrà visualizzata con ps o in alcun registro. Questo è il modo corretto per farlo. Mettere il file in un file esterno aiuta quelli che vogliono cronizzare la password ma è male iniziare. Nel frattempo gli script che sono in esecuzione da anni ormai falliscono e dobbiamo modificarli solo perché questo avviso viene visualizzato nello standard.
Nestor Urquiza,

2
Per il metodo consigliato che non memorizza la password in chiaro, è dettagliato in dev.mysql.com/doc/refman/5.6/en/mysql-config-editor.html
anthony

Risposte:


250

Se la tua versione client / server MySQL è un modo 5.6.xa per evitare che il messaggio WARNING stia usando gli strumenti mysql_config_editor :

mysql_config_editor set --login-path=local --host=localhost --user=username --password

Quindi puoi usare lo script della shell:

mysql --login-path=local  -e "statement"

Invece di:

mysql -u username -p pass -e "statement"

28
Ricorda che --login-pathdeve venire prima di tutti gli altri argomenti. Stavo provando mysqldump --tables --login-path=locale ottenendo l'errore unknown variable 'login-path=local'.
Tulio,

Il client della riga di comando mysql cercherà per impostazione predefinita nel percorso di accesso "client". Puoi semplificare le istruzioni per "mysql -e 'statement'" apportando una piccola modifica.
Morgan Tocker,

2
Funziona bene se eseguiamo direttamente il file shell ma non funziona se chiamato da crontab
Nabeel Arshad

1
@NabeelArshad Penso che questo sia perché nel tuo crontab la "home" per l'utente non è impostata (ENV varia in generale) quindi nel crontab il client non è in grado di trovare il corretto ~ / .mylogin.cnf
Cristian Porta

1
@NamGVU, non sono sicuro, tuttavia, credo che questa soluzione memorizzi password crittografate.
Zhekaus,

209

Uso qualcosa del tipo:

mysql --defaults-extra-file=/path/to/config.cnf

o

mysqldump --defaults-extra-file=/path/to/config.cnf 

Dove contiene config.cnf:

[client]
user = whatever
password = whatever
host = whatever

Ciò consente di disporre di più file di configurazione - per server / ruoli / database diversi. L'uso di ~ / .my.cnf ti consentirà di avere solo un set di configurazione (sebbene possa essere un utile set di valori predefiniti).

Se sei su una distro basata su Debian ed esegui come root, puoi saltare quanto sopra e usare semplicemente /etc/mysql/debian.cnf per entrare ...:

mysql --defaults-extra-file=/etc/mysql/debian.cnf


12
Nota: --defaults-extra-filedeve essere la prima opzione, altrimenti mysql si lamenta mysqldump: unknown variable 'defaults-extra-file.
pevik,

4
Fantastica alternativa alla risposta accettata. Sicuramente non impostare la MYSQL_PWDvariabile ....
DudeOnRock,

1
Sicuramente una buona opzione per le versioni precedenti alla 5.6. Altrimenti, andrei con la risposta accettata.
dkniffin,

21
Un'alternativa a fare un file .cnf temporanea è quello di farlo in Bash: mysql --defaults-extra-file=<(printf "[client]\nuser = %s\npassword = %s" "$user" "$pwd") -e "statement". Poiché il file printfviene eseguito direttamente da Bash, non viene visualizzato in ps.
Dave James Miller,

3
Ho dovuto usare --defaults-filepiuttosto che --defaults-extra-file, perché quest'ultimo ha dato la preferenza alle impostazioni in ~ / .my.cnf.
Roger Dueck,

186

Un metodo che è conveniente (ma ugualmente insicuro) è usare:

MYSQL_PWD=xxxxxxxx mysql -u root -e "statement"

Nota che i documenti ufficiali sconsigliano.
Vedi 6.1.2.1 Linee guida per l'utente finale per la sicurezza delle password (Manuale Mysql per versione 5.6) :

Memorizzare la password nella MYSQL_PWDvariabile d'ambiente

Questo metodo per specificare la password di MySQL deve essere considerato estremamente insicuro e non deve essere utilizzato. Alcune versioni di ps includono un'opzione per visualizzare l'ambiente dei processi in esecuzione. Su alcuni sistemi, se impostato MYSQL_PWD, la password viene esposta a qualsiasi altro utente che esegue ps . Anche su sistemi senza tale versione di ps , non è saggio supporre che non ci siano altri metodi con cui gli utenti possono esaminare gli ambienti di processo.


6
Questo non funziona nel mio script bash:Access denied for user 'root'@'localhost' (using password: NO)
rubo77,

24
In uno script, è necessario export MYSQL_PWD=whatever.
Rivolta del

2
Poiché la mia query è molto rapida, ho optato per questa opzione. Quindi l'ho impostato su qualcosa di falso dopo aver eseguito la query.
TimH - Codidact,

11
In uno script non è necessario eseguire export, basta posizionare tutto su una riga:MYSQL_PWD=xxxxxxxx mysql -u root -e "statement"
JD

1
@JD: funziona per me in Ubuntu 16.04 con MySQL 5.7.21.
marzo

70

Se desideri utilizzare una password nella riga di comando, ho scoperto che funziona per filtrare il messaggio di errore specifico:

mysqlcommand 2>&1 | grep -v "Warning: Using a password"

Fondamentalmente reindirizza l'errore standard all'output standard e utilizza grep per eliminare tutte le righe che corrispondono a "Avvertenza: utilizzo di una password".

In questo modo, puoi vedere qualsiasi altro output, inclusi gli errori. Lo uso per vari script di shell, ecc.


Questa è una soluzione eccellente per l'uso in attività con una sola riga chiamate in altre attività come la creazione di un'attività Rake per una distribuzione Capistrano.
Jake Gould,

2
Eccellente e semplice per silenziare quel messaggio, non è necessario toccare nulla nella configurazione di MySQL.
ajaaskel,

Come lo userei con mysqldump dove ho già un reindirizzamento per SQL?
MacroMan

1
Questa è una soluzione davvero negativa rispetto alle altre qui. Potrebbe non funzionare con qualsiasi versione successiva di MySQL in caso di modifica del testo, potrebbe non funzionare in un'altra locale.
yktoo,

42

Ecco come ho ottenuto il mio script bash per i miei backup quotidiani del database mysqldump per lavorare in modo più sicuro. Questa è un'espansione della grande risposta di Cristian Porta.

  1. Per prima cosa usa mysql_config_editor (viene fornito con mysql 5.6+) per impostare il file di password crittografato. Supponiamo che il tuo nome utente sia "db_user". In esecuzione dal prompt della shell:

    mysql_config_editor set --login-path=local --host=localhost --user=db_user --password

    Richiede la password. Una volta inserito, l'utente / pass vengono salvati crittografati nel tuohome/system_username/.mylogin.cnf

    Naturalmente, cambia "nome_sistema" con il tuo nome utente sul server.

  2. Cambia il tuo script bash da questo:

    mysqldump -u db_user -pInsecurePassword my_database | gzip > db_backup.tar.gz

    a questa:

    mysqldump --login-path=local my_database | gzip > db_backup.tar.gz

Niente più password esposte.


10

Il modo più semplice è

mysql -u root -pMYPASSWORD -e "show databases" 2>/dev/null

43
Il problema è che questo eliminerà anche errori legittimi nella tua sceneggiatura.
man910

4
Inoltre è possibile creare un file di registro 2> /var/log/myscript.log per registrare tali errori.
Skamasle

1
utilizzare 2>/dev/null | grep -v "mysql: [Warning] Using a password on the command line interface can be insecure."per sopprimere solo l'avviso in questione
Hafenkranich

10

Puoi anche eseguire mysql_config_editor nel tuo script per passare la password quando specifichi il percorso di accesso

expect -c "
spawn mysql_config_editor set --login-path=$mySqlUser --host=localhost --user=$mySqlUser --password
expect -nocase \"Enter password:\" {send \"$mySqlPassword\r\"; interact}
"

Ciò avvia una sessione di attesa che può essere utilizzata negli script per interagire con i prompt

Vedi questo post


Questo ">" è davvero pensato per essere lì?
David Goodwin,

si '>' è pensato per essere lì in modo che mysql_config_editor prende input da stdout. Ciò che viene passato da stdout a mysql_config_editor è la password che si desidera che questo utente abbia senza il ">", quindi ciò che accade è che il comando echo viene analizzato e tutto ciò che si vedrebbe è tutto dopo il comando echo
phylanx

Quindi, intendi usare l'operatore pipe "|", giusto? Almeno, in * nix e DOS, ">" acquisirà lo STDOUT e lo scriverà in un file chiamato "mysql_config_editor" nella directory di lavoro corrente.
Jay Dansand,

Sì, hai ragione, ho modificato la mia risposta originale
phylanx,

7

ok, soluzione senza file temporanei o altro:

mysql --defaults-extra-file=<(echo $'[client]\npassword='"$password") -u $user -e "statement"

è simile a quello che altri hanno menzionato, ma qui non è necessario un file reale, questa parte del comando falsifica il file: <(echo ...) (nota che non c'è spazio nel mezzo di<(


questo non funziona se hai già un .my.cnffile ~/.con una password
inserita

5
shell> mysql_config_editor set --login-path=local
     --host=localhost --user=localuser --password
Enter password: enter password "localpass" here
shell> mysql_config_editor set --login-path=remote
     --host=remote.example.com --user=remoteuser --password
Enter password: enter password "remotepass" here

Per vedere cosa ha scritto mysql_config_editor nel file .mylogin.cnf, usa il comando print:

shell> mysql_config_editor print --all
[local]
user = localuser
password = *****
host = localhost
[remote]
user = remoteuser
password = *****
host = remote.example.com

Il comando di stampa visualizza ogni percorso di accesso come un insieme di righe che iniziano con un'intestazione di gruppo che indica il nome del percorso di accesso tra parentesi quadre, seguito dai valori delle opzioni per il percorso di accesso. I valori della password sono mascherati e non vengono visualizzati come testo in chiaro.

Come mostrato dagli esempi precedenti, il file .mylogin.cnf può contenere più percorsi di accesso. In questo modo, mysql_config_editor semplifica l'impostazione di più "personalità" per la connessione a diversi server MySQL. Ognuno di questi può essere selezionato per nome in seguito utilizzando l'opzione --login-path quando si richiama un programma client. Ad esempio, per connettersi al server locale, utilizzare questo comando:

shell> mysql --login-path=local

Per connettersi al server remoto, utilizzare questo comando:

shell> mysql --login-path=remote

Cosa succede se desidero eseguire un comando mysqldump come utente www-data? www-data non ha home directory ... come posso impostare mysql_config_editor per l'utente www-data?
lewis4u,

5

Da https://gist.github.com/nestoru/4f684f206c399894952d

# Let us consider the following typical mysql backup script:
mysqldump --routines --no-data -h $mysqlHost -P $mysqlPort -u $mysqlUser -p$mysqlPassword $database

# It succeeds but stderr will get:
# Warning: Using a password on the command line interface can be insecure.
# You can fix this with the below hack:
credentialsFile=/mysql-credentials.cnf
echo "[client]" > $credentialsFile
echo "user=$mysqlUser" >> $credentialsFile
echo "password=$mysqlPassword" >> $credentialsFile
echo "host=$mysqlHost" >> $credentialsFile
mysqldump --defaults-extra-file=$credentialsFile --routines --no-data $database

# This should not be IMO an error. It is just a 'considered best practice'
# Read more from http://thinkinginsoftware.blogspot.com/2015/10/solution-for-mysql-warning-using.html

3

Un'altra alternativa è usare sshpass per invocare mysql, ad esempio:

sshpass -p topsecret mysql -u root -p username -e 'statement'

Sembra funzionare, ma devi rimuovere "username" dalla riga di comando, vero?
e2-e4,

3

Una semplice sceneggiatura alternativa. Assegna un nome a "mysql" e inseriscilo nel tuo percorso prima di "/ usr / bin". Varianti evidenti per altri comandi o se il testo di avviso è diverso.

#!/bin/sh

(
(
(
(
(
    /usr/bin/mysql "$@"
) 1>&9 
) 2>&1
) | fgrep -v 'mysql: [Warning] Using a password on the command line interface can be insecure.'
) 1>&2 
) 9>&1

3
Mentre questa risposta è un po 'contorta, l'ho appena votata perché mi fa tanto schifo vedere risposte che non sono esplicitamente sbagliate o che sono un po' non convenzionali ottenere voti bassi senza commenti! Non c'è da stupirsi che David non abbia risposto ad altre domande! È saltato dentro e ha cercato di aiutare con una nuova soluzione ed è stato sbattuto senza spiegazioni sul perché! Fu downvoter anonimi che non lasciano commenti!
Jeremy Davis il

3
+1 sono d'accordo con Jeremy Davis. Questo è contorto, ma se lasciato senza altra opzione potrebbe essere accettabile. Non è assolutamente sbagliato, a differenza di disattivare gli avvisi che devono essere l'idea più stupida di sempre!
Ben McIntyre,

1
@JeremyDavis Sì, questo è stato contorto, principalmente perché volevo mostrare il lavoro. Potrebbe essere fatto senza parentesi, ma avrebbe potuto essere meno chiaro. Questa è stata anche la mia prima attività senza lettura in tutto lo scambio di stack ... dopo di che non l'ho toccato per molto tempo. Il tuo commento è stato sicuramente apprezzato.
David G.

@DavidG. - Sono contento che il mio commento sia stato utile per te. Anche bello vedere che sei tornato e che la tua risposta è ora in territorio positivo. Personalmente, non penso che dovrebbe essere consentito il voto negativo senza commentare ... Come si può imparare qualcuno quando viene sbattuto per provare ?!
Jeremy Davis il

Detto questo, rivedendo la tua risposta, non sono convinto che una soluzione permanente (essenzialmente il wrapping di mysql) a un problema temporaneo (la soppressione di un messaggio di errore da utilizzare in un singolo script) sia il modo migliore di procedere. Il wrapping di IMO in mysql in una funzione all'interno dello script (usando il tuo metodo qui andrebbe bene) è un approccio superiore. My 2c ... :)
Jeremy Davis il

3

Ecco una soluzione per Docker in uno script / bin / sh:

docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec echo "[client]"> /root/mysql-credentials.cnf'

docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec echo "user = root" >> /root/mysql-credentials.cnf'

docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec echo "password = $ MYSQL_ROOT_PASSWORD" >> /root/mysql-credentials.cnf'

docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec mysqldump --defaults-extra-file = / root / mysql-credentials.cnf --all-d Database'

Sostituisci [MYSQL_CONTAINER_NAME] e assicurati che la variabile di ambiente MYSQL_ROOT_PASSWORD sia impostata nel tuo contenitore.

Spero che ti aiuterà come potrebbe aiutarmi!


Non male. Ho appena usato una chiamata con un ritorno, ad es. docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec echo "[client] [RETURN HERE] password=pa55" > /root/defaults'Usando --defaults-filesi prende già anche root.
Matthew Wilcoxson,

3

Puoi anche reindirizzare l'output STDERR dell'errore standard su / dev / null

Quindi fai solo:

mysql -u $user -p$password -e "statement" 2> /dev/null



1

Personalmente, uso il wrapper di script per rilevare quell'errore. Ecco un esempio di codice:

#!/bin/bash

#echo $@ | cat >> /home/mysqldump.log 2>/dev/null
ERR_FILE=/tmp/tmp_mdump.err

# Execute dumper
/usr/bin/mysqldump $@ 2>$ERR_FILE

# Determine error and remove tmp file
ERROR=`cat $ERR_FILE`
rm $ERR_FILE

# Handle an error
if [ "" != "$ERROR" ]; then

        # Error occured
        if [ "Warning: Using a password on the command line interface can be insecure." != "$ERROR" ]; then
                echo $ERROR >&2
                exit 1
        fi
fi

1

Per PowerShell ( pwsh, non bash), questa era una soluzione piuttosto rube-goldberg ... Il mio primo tentativo è stato quello di racchiudere le chiamate mysqlin una try/catchfunzione, ma a causa di uno strano comportamento nella gestione degli errori di PowerShell , questo non era fattibile.

La soluzione era quella di ignorare il $ErrorActionPreferencegiusto il tempo di combinare e la cattura STDERRe STDOUTe analizzare per la parola ERRORe ri-tiro, se necessario. Il motivo per cui non siamo riusciti a catturare e rilasciare "^mysql.*Warning.*password"è perché PowerShell gestisce e genera l'errore come un flusso, quindi è necessario acquisire tutto per filtrare e rilanciare. : /

Function CallMySQL() {
    # Cache the error action preference
    $_temp = $ErrorActionPreference
    $ErrorActionPreference = "Continue"

    # Capture all output from mysql
    $output = (&mysql --user=foo --password=bar 2>&1)

    # Restore the error action preference
    $ErrorActionPreference = $_temp

    if ($output -match "ERROR") {
        throw $output
    } elseif($output) {
        "   Swallowing $output"
    } else {
        "   No output"
    }
}

Nota: PowerShell è disponibile per Unix, quindi questa soluzione è multipiattaforma. Può essere adattato bashcon alcune piccole modifiche alla sintassi.

Avvertenza: ci sono dozzine di casi limite in cui questo non funzionerà come messaggi di errore o dichiarazioni non inglesi che restituiscono la parola in ERRORqualsiasi punto dell'output, ma è stato sufficiente ingoiare l'avviso per una chiamata di base mysqlsenza bombardare il intera sceneggiatura. Spero che altri lo trovino utile.

Sarebbe bello se fosse mysqlsemplicemente aggiunta un'opzione per sopprimere questo avviso.


1

Se ti capita di usare Rundeck per pianificare le tue attività o qualsiasi altra piattaforma in cui richiedi un mylogin.cnffile, ho usato con successo il seguente codice shell per fornire una nuova posizione per il file prima di procedere con le chiamate sql:

if test -f "$CUSTOM_MY_LOGINS_FILE_PATH"; then
   chmod 600 $CUSTOM_MY_LOGINS_FILE_PATH
   export MYSQL_TEST_LOGIN_FILE="$CUSTOM_MY_LOGINS_FILE_PATH"
fi

...

result=$(mysql --login-path=production -NBA -D $schema -e "$query")

Dove si MYSQL_TEST_LOGIN_FILEtrova una variabile di ambiente che può essere impostata su un percorso file diverso da quello predefinito.

Ciò è particolarmente utile se si esegue un processo biforcuto e non è possibile spostare o copiare i file nella $HOMEdirectory.

Vedi la documentazione qui.


0

la soluzione migliore è usare l'alias:

alias [yourapp]-mysql="mysql -u root -psomepassword -P3306 -h 127.0.0.1"

esempio, inseriscilo nel tuo script:

alias drupal-mysql="mysql -u root -psomepassword -P3306 -h 127.0.0.1"

poi più tardi nello script per caricare un database:

drupal-mysql database_name < database_dump.sql

per eseguire una dichiarazione:

drupal-mysql -e "EXEC SOMESTATEMENT;"

quindi unifica gli aliaas:
Neil Davis,

Cordiali saluti, non è possibile utilizzare l'alias se si chiama mysql all'interno di una funzione all'interno dello script.
user3616725,

0

Definisci l'helper:

remove-warning () {
    grep -v 'mysql: [Warning] Using a password on the command line interface can be insecure.'
}

Usalo:

mysql -u $user -p$password -e "statement" 2>&1 | remove-warning

Tachaan! Il tuo codice è pulito e piacevole da leggere

(testato con bash)


-1

Un'altra soluzione (ad esempio da uno script):

 sed -i'' -e "s/password=.*\$/password=$pass/g" ~/.my.cnf
 mysql -h $host -u $user $db_name -e "$sql_cmd"

L' -i''opzione è qui per la compatibilità con Mac OS X. I sistemi operativi UNIX standard possono essere utilizzati direttamente-i


1
la password è ancora sulla riga di comando di 'sed', quindi rimane visibile negli elenchi dei processi, anche se solo brevemente.
Anthony il

-1

Il problema che ho avuto è stato l'utilizzo dell'output in modo condizionale in uno script bash.

Questo non è elegante, ma in un ambiente mobile non dovrebbe davvero importare. Fondamentalmente tutto ciò che fa è ignorare l'output che non è sull'ultima riga. Puoi fare lo stesso con awk e cambiare per restituire tutto tranne la prima riga ecc.

Questo restituisce solo l'ultima riga

mysql -u db_user -pInsecurePassword my_database ... | sed -e '$!d'

Non sopprimerà l'errore, ma farà in modo che sia possibile utilizzare l'output di una query in uno script bash.


-1

La via più facile:

mysql -u root -p YOUR_DATABASE

Inserisci questo e dovrai inserire la password.

Nota: Sì, senza punto e virgola.


-3

È possibile eseguire mySQL e sopprimere i messaggi di avviso e di errore usando / dev / null per esempio:

# if you run just a SQL-command
mysql -u ${USERNAME} -p${PASSWORD} -h ${HOST} ${DATABASE} -e "${STATEMENT}" &> /dev/null

# Or you can run SQL-script as a file
mysql -u ${USERNAME} -p${PASSWORD} -h ${HOST} ${DATABASE} < ${FILEPATH} &> /dev/null

Dove:

${USERNAME} - existing mysql user

${PASSWORD} - password

${HOST}     - ip or hostname, for example 'localhost'

${DATABASE} - name of database

${STATEMENT}- SQL command

${FILEPATH} - Path to the SQL-script

godere!


1
Basta essere consapevoli del fatto che sopprimerà TUTTI i messaggi di errore, non solo quegli avvisi di password.
Simon East,

-3

Ha funzionato per me - Appena aggiunto 2> nulldopo il $(mysql_command), e sopprimerà solo i messaggi di errore e di avviso.


1
Ciò significa anche che non ricevi un rapporto quando qualcos'altro va storto!
Anthony il

Inoltre, probabilmente lo volevi 2>/dev/null. L'utilizzo 2> nullavrebbe semplicemente messo l'output in un file chiamato "null" nella directory corrente.
thelogix,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.