Пригнічуйте попереджувальні повідомлення за допомогою mysql з терміналу, але пароль, написаний bash-скриптом


273

Коли я спробував запустити наступну команду на MySQL з терміналу:

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

Виконання працює як очікувалося, але воно завжди видає попередження:

Попередження: Використання пароля в інтерфейсі командного рядка може бути небезпечним.

Однак я повинен вести заяву вище, використовуючи змінну середовища ( $password), яка зберігає мій пароль, тому що я хочу запускати команду ітеративно в bash-скрипті з терміналу, і мені точно не подобається ідея чекати швидкого відображення і змушує мене вводити свій пароль 50 або 100 разів в одному сценарії. Тож ось моє запитання:

  • Чи можливо придушити попередження? Команда працює належним чином, як я вже заявив, але вікно стає досить безладним, коли я перекидаю та запускаю команду 50 або 100 разів.

  • Чи слід дотримуватися попереджувального повідомлення та НЕ писати свій пароль у своєму сценарії? Якщо це так, то чи потрібно мені вводити свій пароль щоразу, коли підказка змушує мене це зробити?

Біг man mysqlне допомагає, кажучи лише

--show-warnings
Причини попередження відображатись після кожного твердження, якщо вони є. Ця опція застосовується до інтерактивного та пакетного режимів.

і нічого не згадує про те, як відключити функціональність, якщо я щось не пропускаю.

Я перебуваю на OS X 10.9.1 Mavericks і використовую MySQL 5.6 від домашньої мови.


14
Рекомендований спосіб - зберігати свій пароль у файлі опцій (smth like [client] password=my_passwordin ~/.my.cnf). Звичайно, це має і певні наслідки для безпеки, але принаймні це не доступно для всіх, хто може працювати ps, і ви маєте контроль над ним за допомогою дозволів на файли.
Антон Коваленко

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

О, до речі, ви також можете використовувати щось на зразок Python pexcept. Він може робити термінальні вставки, а також обробляти відгуки, які дає команда. Таким чином ви можете просто пропустити цей багатослівний вихід і смужку фактичного виводу, який ви хочете :)

6
Рекомендований спосіб IMO карає тих, хто робить правильно, щоб захистити тих, хто робить не так. Якщо пароль зберігається у файлі скрипту, він не відображатиметься з ps або в будь-якому журналі. Це правильний спосіб зробити це. Якщо розмістити файл у зовнішньому файлі, це допоможе тим, хто змістить пароль, але це погано для початку. Тим часом сценарії, які працюють протягом багатьох років, виходять з ладу, і нам потрібно їх модифікувати лише тому, що це попередження з'являється в більш жорсткому рівні.
Нестор Уркіза

2
Для рекомендованого методу whcih не зберігає пароль у відкритому вигляді , докладно описаний в dev.mysql.com/doc/refman/5.6/en/mysql-config-editor.html
Антонієм

Відповіді:


249

Якщо ваш клієнт / сервер MySQL - це 5.6.xa спосіб уникнути повідомлення ПОПЕРЕДЖЕННЯ, використовуйте інструменти mysql_config_editor :

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

Тоді ви можете використовувати в своєму сценарії оболонки:

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

Замість:

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

28
Пам’ятайте, що --login-pathмає бути перед усіма іншими аргументами. Я намагався mysqldump --tables --login-path=localотримати помилку unknown variable 'login-path=local'.
Туліо

Клієнт командного рядка mysql за замовчуванням буде знаходитись під шляхом входу "client". Ви можете спростити вказівки до "mysql -e 'statement" ", внести невеликі зміни.
Морган Токер

2
Це добре працює, якщо ми безпосередньо виконуємо файл оболонки, але не працюємо, якщо його викликають із crontab
Nabeel Arshad

1
@NabeelArshad Я думаю , що це тому , що в вашому кронтаб «будинок» для користувача не встановлено (ENV варов в цілому) , так в кронтаб клієнт не може знайти правильний ~ / .mylogin.cnf
Cristian Порта

1
@NamGVU, я не впевнений, проте я вважаю, що це рішення зберігає зашифровані паролі.
джекаус

209

Я використовую щось на кшталт:

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

або

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

Де config.cnf містить:

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

Це дозволяє мати кілька конфігураційних файлів - для різних серверів / ролей / баз даних. Використання ~ / .my.cnf дозволить мати лише один набір конфігурацій (хоча це може бути корисним набором за замовчуванням).

Якщо ви перебуваєте на дистрибутиві на базі Debian і працює як root, ви можете пропустити вищезазначене та просто скористатися /etc/mysql/debian.cnf, щоб увійти ...:

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


12
Примітка: --defaults-extra-fileповинен бути першим варіантом, інакше mysql скаржиться mysqldump: unknown variable 'defaults-extra-file.
pevik

4
Дивовижна альтернатива прийнятої відповіді. Однозначно не встановлюйте MYSQL_PWDзмінну ....
DudeOnRock

1
Безумовно, хороший варіант для версій нижче 5.6. Інакше я б пішов із прийнятою відповіддю.
dkniffin

21
Альтернатива створення тимчасового .cnf-файлу - це зробити в Bash : mysql --defaults-extra-file=<(printf "[client]\nuser = %s\npassword = %s" "$user" "$pwd") -e "statement". Оскільки printfBash виконується безпосередньо, він не відображається в ps.
Дейв Джеймс Міллер

3
Мені потрібно було --defaults-fileскоріше використовувати --defaults-extra-file, тому що останній віддав перевагу налаштуванням у ~ / .my.cnf.
Роджер Дуек

185

Одним із зручних (але однаково небезпечних) методів є використання:

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

Зауважте, що офіційні документи рекомендують проти цього.
Див. 6.1.2.1 Правила для кінцевих користувачів щодо захисту пароля (Посібник Mysql для версії 5.6) :

Збереження пароля в MYSQL_PWDзмінній оточення

Цей метод визначення вашого пароля MySQL повинен вважатися надзвичайно небезпечним і не повинен застосовуватися. Деякі версії ps містять опцію відображення середовища запущених процесів. У деяких системах, якщо ви встановили MYSQL_PWD, ваш пароль піддається будь-якому іншому користувачеві, який працює з ps . Навіть у системах, що не мають такої версії ps , нерозумно вважати, що не існує інших методів, за допомогою яких користувачі можуть досліджувати середовище процесів.


6
Це не працює в моєму скрипті bash:Access denied for user 'root'@'localhost' (using password: NO)
rubo77

24
У сценарії вам потрібно export MYSQL_PWD=whatever.
Бунт

2
Оскільки мій запит дуже швидкий, я вибрав цей варіант. Потім я встановив це на щось хибне після виконання запиту.
TimH - Кодидакт

11
У сценарії вам не потрібно запускати export, просто розмістіть все в одному рядку:MYSQL_PWD=xxxxxxxx mysql -u root -e "statement"
JD

1
@JD: працює для мене в Ubuntu 16.04 з MySQL 5.7.21.
mivk

70

Якщо ви хочете використовувати пароль у командному рядку, я виявив, що це працює для фільтрації конкретного повідомлення про помилку:

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

Це в основному переадресація стандартної помилки на стандартний вихід - і за допомогою grep для скидання всіх рядків, які відповідають "Попередження: Використання пароля".

Таким чином, ви можете побачити будь-який інший вихід, включаючи помилки. Я використовую це для різних скриптів оболонки тощо.


Це відмінне рішення для використання в однолінійних завданнях, що називаються іншими завданнями, такими як створення завдання Rake для розгортання Capistrano.
JakeGould

2
Відмінний і простий для відключення цього повідомлення, не потрібно нічого торкатися в налаштуваннях MySQL.
Аджаскель

Як я можу це використовувати з mysqldump, де вже є переспрямування на SQL?
MacroMan

1
Це дійсно погане рішення порівняно з іншими тут. Можливо, це не вдасться до будь-якої наступної версії MySQL, якщо текст зміниться, а також не може працювати в іншій місцевості.
yktoo

42

Ось як я отримав скрипт bash для щоденних резервних копій бази даних mysqldump, щоб працювати більш безпечно. Це розширення чудової відповіді Крістіана Порта.

  1. Спершу використовуйте mysql_config_editor (поставляється з mysql 5.6+) для налаштування зашифрованого файлу паролів. Припустимо, ваше ім’я користувача "db_user". Запуск із підказки оболонки:

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

    Тут буде запропоновано ввести пароль. Після введення його користувач / пропуск зберігаються в зашифрованому виглядіhome/system_username/.mylogin.cnf

    Звичайно, змініть "system_username" на ваше ім'я користувача на сервері.

  2. Змініть свій bash-скрипт із цього:

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

    до цього:

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

Більше не відкритих паролів.


10

Найпростіший спосіб

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

43
Проблема в тому, що це також придушить законні помилки у вашому сценарії.
man910

4
Також ви можете створити файл журналу 2> /var/log/myscript.log для реєстрації цих помилок.
Skamasle

1
використовуйте 2>/dev/null | grep -v "mysql: [Warning] Using a password on the command line interface can be insecure."для придушення лише відповідного попередження
Хафенкраніч

10

Ви також можете запустити mysql_config_editor у своєму сценарії для передачі пароля під час вказування шляху входу.

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

Починається сеанс очікування, який може використовуватися в сценаріях для взаємодії з підказками

Дивіться цю публікацію


Це ">" насправді означало бути там?
Девід Гудвін

так '>' покликаний бути там, щоб mysql_config_editor приймав дані від stdout. Що передається від stdout до mysql_config_editor - це пароль, який ви бажаєте мати цього користувача Без '>', то, що трапляється, це те, що команда echo розбирається, і все, що ви побачили, - це все після команди echo
phylanx

Отже, ти маєш на увазі використовувати трубопровід "|", правда? Принаймні, у * nix та DOS, ">" захопить STDOUT і запише його у файл під назвою "mysql_config_editor" у поточному робочому каталозі.
Джей Дансанд

Так, ви маєте рацію, я відредагував свою оригінальну відповідь
філанс

7

ок, рішення без тимчасових файлів чи нічого:

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

це аналогічно тому, що згадували інші, але тут вам не потрібен фактичний файл, ця частина команди підробляє файл: <(echo ...) (зауважте, що в середині місця немає місця<(


це не працює, якщо у вас вже є .my.cnfфайл ~/.із записом пароля
santiago arizti

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

Щоб побачити, що mysql_config_editor записав у файл .mylogin.cnf, використовуйте команду print:

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

Команда друку відображає кожен шлях входу у вигляді набору рядків, що починається із заголовка групи із зазначенням імені шляху входу у квадратних дужках з подальшим значенням параметра для шляху входу. Значення пароля маскуються і не виглядають як чіткий текст.

Як показано в попередніх прикладах, файл .mylogin.cnf може містити кілька шляхів входу. Таким чином, mysql_config_editor полегшує налаштування декількох «особистостей» для підключення до різних серверів MySQL. Будь-який із них можна вибрати по імені пізніше, використовуючи параметр --login-path, коли ви викликаєте клієнтську програму. Наприклад, для підключення до локального сервера використовуйте цю команду:

shell> mysql --login-path=local

Для підключення до віддаленого сервера використовуйте цю команду:

shell> mysql --login-path=remote

Що робити, якщо я хочу виконати команду mysqldump як користувач www-data? www-data не має домашнього каталогу ... як встановити mysql_config_editor для користувача www-data?
lewis4u

5

З 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

Іншою альтернативою є використання sshpass для виклику mysql, наприклад:

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

Здається, це працює, але ви повинні видалити 'ім'я користувача' з командного рядка, чи не так?
e2-e4

3

Простий сценарій для роботи. Назвіть цей "mysql" і поставте його на своєму шляху перед "/ usr / bin". Очевидні варіанти для інших команд або якщо текст попередження відрізняється.

#!/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
Незважаючи на те, що ця відповідь є дещо суперечливою, я просто схвалив її, тому що мені так сильно подобається бачити відповіді, які не є явними помилками або трохи нетрадиційними. Недарма Давид не відповів на жодні інші запитання! Він заскочив і спробував допомогти з новим рішенням, і його не врізали, не пояснюючи чому! Анонімні учасники FU, які не залишають коментарів!
Джеремі Девіс

3
+1 згоден Джеремі Девіс. Це суперечка, але якщо не залишилося іншого варіанту, це може бути прийнятним. Це напевно не помиляється, на відміну від вимкнення попереджень, що повинно бути найглупішою ідеєю будь-коли!
Бен Макінтайр

1
@JeremyDavis Так, це було суперечливо, головним чином тому, що я хотів показати роботу. Можливо, це можна зробити без жодних дужок, але це могло бути менш зрозумілим. Це також було моїм першим в світі непрочитаним заходом у всіх обмінах стеками ... після чого я довго не торкався цього. Ваш коментар був безумовно оцінений.
Девід Г.

@DavidG. - Радий, що мій коментар був для вас цінним. Також чудово бачити, що ви повернулися і що ваша відповідь зараз на позитивній території. Особисто я не вважаю, що голосування без коментування не повинно бути дозволеним ... Як це хтось має намір дізнатися, коли їх грюкають за те, що вони йдуть ?!
Джеремі Девіс

Сказавши це, переглядаючи свою відповідь, я не переконаний, що постійне рішення (по суті, обгортання mysql) тимчасової проблеми (придушення повідомлення про помилку для використання в одному сценарії) - найкращий спосіб. Обгортання mysql IMO у функції в рамках сценарію (використання вашого методу тут було б добре) є вищим підходом. Мій 2с ... :)
Джеремі Девіс

3

Ось рішення для Docker у скрипті / 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 "пароль = $ MYSQL_ROOT_PASSWORD" >> /root/mysql-credentials.cnf'

docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec mysqldump --defaults-extra-file = / root / mysql-credentials.cnf - всі бази даних'

Замініть [MYSQL_CONTAINER_NAME] і переконайтеся, що змінна середовища MYSQL_ROOT_PASSWORD встановлена ​​у вашому контейнері.

Сподіваюся, це допоможе тобі, як воно могло допомогти мені!


Непогано. Я щойно використав один дзвінок із поверненням, наприклад, docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec echo "[client] [RETURN HERE] password=pa55" > /root/defaults'використовуючи його, --defaults-fileвін також збирає корінь.
Меттью Вілкокссон

3

Ви також можете просто перенаправити стандартний вихід STDERR помилки на / dev / null

Тож просто роби:

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


7
Я б уникну цього способу, оскільки це зробить легітимні помилки важче зловити
Володимир Грабан

1

Особисто я використовую обгортку сценарію, щоб знайти цю помилку. Ось зразок коду:

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

Для PowerShell (це pwshне так bash), це було цілком рішенням «рубе-Гольдберг» ... Першою моєю спробою було ввімкнути виклики mysqlу try/catchфункцію, але через якусь дивну поведінку в роботі з помилками PowerShell це не було життєздатним.

Рішення було перевизначити $ErrorActionPreferenceтільки досить довго , щоб об'єднати і захоплення STDERRі STDOUTі розібрана на слова ERRORі повторного кидка по мірі необхідності. Причина, через яку ми не змогли наздогнати та випустити, "^mysql.*Warning.*password"- це те, що PowerShell обробляє та збільшує помилку як один потік, тому ви повинні захопити все це для фільтрації та повторного викидання. : /

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"
    }
}

Примітка: PowerShell доступний для Unix, тому це рішення є кросплатформним. Він може бути адаптований до bashдеяких незначних модифікацій синтаксису.

Попередження: Є десятки крайових випадків, коли це не спрацює, як-от повідомлення про помилки чи англійські повідомлення про помилки, які повертають слово ERRORкудись у висновку, але цього було достатньо, щоб проковтнути попередження для базового дзвінка, mysqlне вибухаючи весь сценарій. Сподіваємось, інші вважають це корисним.

Було б добре, якби mysqlпросто додати опцію придушити це попередження.


1

Якщо ви часто використовуєте Rundeck для планування своїх завдань або будь-яку іншу платформу, де ви запитуєте mylogin.cnfфайл, я успішно використав наступний код оболонки, щоб забезпечити нове місце для файлу, перш ніж продовжувати дзвінки 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")

Де MYSQL_TEST_LOGIN_FILEє змінна середовище, яку можна встановити на інший шлях до файлу, ніж стандартний.

Це особливо корисно, якщо ви працюєте в роздвоєному процесі і не можете переміщувати або копіювати файли в $HOMEкаталог.

Дивіться документацію тут.


0

найкраще рішення - використовувати псевдонім:

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

Наприклад, введіть це у свій сценарій:

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

потім пізніше у вашому сценарії завантажте базу даних:

drupal-mysql database_name < database_dump.sql

запустити операцію:

drupal-mysql -e "EXEC SOMESTATEMENT;"

то скасуйте псевдонім:
Ніл Девіс

FYI, ви не можете використовувати псевдонім, якщо ви викликаєте mysql всередині функції всередині сценарію.
користувач3616725

0

Визначте помічника:

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

Використай це:

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

Тахаан! Ваш код чистий і приємний для читання

(випробуваний на баш)


-1

Ще одне рішення (наприклад, зі сценарію):

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

Тут -i''є можливість сумісності з Mac OS X. Стандартні ОС UNIX можуть використовувати прямо-i


1
пароль все ще знаходиться в командному рядку 'sed', тому залишається видимим у списках процесів, навіть якщо коротко.
антоній

-1

Проблема, яка була у мене, полягала у використанні виводу в умовному режимі bash.

Це не елегантно, але в docker env це дійсно не має значення. В основному все це - це ігнорування результатів, які не знаходяться в останньому рядку. Ви можете зробити подібне з awk, і змінити, щоб повернути всі, крім першого рядка тощо.

Це повертає лише останній рядок

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

Він не придушить помилку, але переконається, що ви можете використовувати вихід запиту в скрипті bash.


-1

Найпростіший спосіб:

mysql -u root -p YOUR_DATABASE

Введіть це, і вам потрібно буде ввести пароль.

Примітка. Так, без крапки з комою.


-3

Ви можете виконати mySQL і придушити повідомлення попередження та помилок, використовуючи, наприклад, / dev / null:

# 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

Де:

${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

насолоджуйтесь!


1
Тільки майте на увазі, що це буде придушувати ВСІ повідомлення про помилки, а не лише ці попередження про пароль.
Саймон Схід

-3

Він працював для мене - додається лише 2> nullпісля $(mysql_command), і він буде придушувати лише повідомлення про помилки та попередження.


1
Це також означає, що ви не отримаєте звіт, коли щось інше піде не так!
Антоній

Також ви, напевно, хотіли 2>/dev/null. Використання 2> nullпросто помістить вихід у файл, який називається "null" у поточному каталозі.
thelogix
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.