Як виконати команду MySQL із скрипту оболонки?


131

Як я можу виконати команду SQL через скрипт оболонки, щоб я міг зробити її автоматизованою?

Я хочу відновити дані, зібрані у файлі SQL, за допомогою сценарію оболонки. Я хочу підключитися до сервера та відновити дані. Команда працює, коли виконується окремо за допомогою командного рядка SSH.

Це команда, яку я використовую:

mysql -h "server-name" -u root "password" "database-name" < "filename.sql"

Це код скрипту оболонки, який створює файл ds_fbids.sqlі передає його в mysql.

perl fb_apps_frm_fb.pl
perl fb_new_spider.pl ds_fbids.txt ds_fbids.sql
mysql -h dbservername -u username -ppassword dbname < ds_fbids.sql

Який правильний спосіб це зробити?

Відповіді:


176

Вам потрібно використовувати -pпрапор, щоб надіслати пароль. І це складно, оскільки у вас не повинно бути місця між -pпаролем і паролем.

$ mysql -h "server-name" -u "root" "-pXXXXXXXX" "database-name" < "filename.sql"

Якщо ви використовуєте пробіл після -pтого, як він змушує клієнт mysql інтерактивно запитувати пароль, а потім він інтерпретує наступний аргумент команди як ім'я бази даних:

$ mysql -h "server-name" -u "root" -p "XXXXXXXX" "database-name" < "filename.sql"
Enter password: <you type it in here>
ERROR 1049 (42000): Unknown database 'XXXXXXXX'

Насправді я вважаю за краще зберігати користувача та пароль у ~ / .my.cnf, тому мені взагалі не потрібно ставити його в командному рядку:

[client]
user = root
password = XXXXXXXX

Тоді:

$ mysql -h "server-name" "database-name" < "filename.sql"

Повторіть свій коментар:

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

Крім того, коли я вирішую проблеми зі скриптом оболонки, я використовую -xпрапор, щоб я міг бачити, як воно виконує кожну команду:

$ bash -x myscript.sh

Дякуємо за швидку відповідь. Я втомився, вводячи пароль у сам командний рядок. Справжня проблема полягає в тому, що я ввожу цю команду у файл .sh та виконую цей скрипт оболонки. Команда у файлі не виконується в командному рядку, але ця сама команда прекрасно працює, коли я виконую лише команду в командному рядку.
MUFC

+ mysql -h dbservername -u user-name -ppassword dbname</br> : No such file or directoryids.sql</br> + $'\r' : command not found2:Це повідомлення про помилку, яке я отримав
MUFC

Гаразд, тоді я б зробив висновок, що ваша поточна робоча директорія не там, де знаходиться файл ids.sql. Також, можливо, ви вклали нові рядки у свій сценарій.
Білл Карвін

У мене в кожному сценарії оболонки вбудуються нові рядки після кожної команди. Все, що містить мій скрипт оболонки, - це 3 команди командного рядка, які я не хочу запускати окремо, тому я створив сценарій оболонки, щоб змусити їх запускатись без мого втручання, і я додаю новий рядок у кожну команду. Це викликає проблеми?
MUFC

найкраще уникати, -pякщо пароль є нульовим або порожнім рядком, можливо, ви можете оновити свою публікацію? :)
Джеймс Оравець

118

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

mysql -u $user -p$passsword -Bse "command1;command2;....;commandn"

8
Мені висадили цю сторінку від google, і це очікування, яке я очікував (співпадаючи з назвою питання).
Janaka R Раджапакша

15
Ще деякі подробиці щодо параметрів з посібника: -B призначено для пакетної роботи, друкуйте результати, використовуючи вкладку як роздільник стовпців, з кожним рядком у новому рядку. За допомогою цієї опції mysql не використовує файл історії. Пакетний режим призводить до нетабулярного вихідного формату та виділення спеціальних символів. -s - безшумний режим. Отримайте менше випуску. - це виконати заяву та вийти
wranvaud

Спасибі за вашу допомогу! :)
haotang

Чи міг би бігти з гередоком?
zx1986

1
@ zx1986 Так і ні, HEREDOC. Залежить від того, як ти маєш це використовувати. Використовувати його для заміни "command1;command2;....;commandn"частини цієї відповіді не вийде. Використовуючи його для заміни використання перенаправленого файлу в синтаксисі ОП, може працювати. Я вирішив це питання у своїй відповіді на це питання.
Чіндраба

45

Усі попередні відповіді чудові. Якщо це проста, однорядкова команда sql, яку ви хочете запустити, ви також можете скористатися параметром -e.

mysql -h <host> -u<user> -p<password> database -e \
  "SELECT * FROM blah WHERE foo='bar';"

Що мені потрібно зробити в межах подвійних ("") запитів. Дякую
користувач3132107

Я бачу, і я вважаю, що вам потрібно включити крапку з комою в кінці запиту?
Лорі

19

Як виконати сценарій SQL, використовуйте цей синтаксис:

mysql --host= localhost --user=root --password=xxxxxx  -e "source dbscript.sql"

Якщо ви використовуєте хост як localhost, вам не потрібно згадувати його. Ви можете скористатися цим:

mysql --user=root --password=xxxxxx  -e "source dbscript.sql"

Це повинно працювати для Windows та Linux.

Якщо вміст пароля містить !(знак оклику), слід додати \(зворотний косий рядок) перед ним.


1
Як вказати базу даних? це повинно бути всередині -e, як -e "використовувати abc; source dbscript.sql"?
Абдул Муньєр

9

Ядро питання вже було відповідено декілька разів, я просто подумав, що додам, що backticks (s) має значення як в сценарії оболонок, так і в SQL. Якщо вам потрібно використовувати їх у SQL для вказівки імені таблиці або бази даних, вам потрібно буде залишити їх у скрипті оболонки, наприклад:

mysql -p=password -u "root" -Bse "CREATE DATABASE \`${1}_database\`;
CREATE USER '$1'@'%' IDENTIFIED BY '$2';
GRANT ALL PRIVILEGES ON `${1}_database`.* TO '$1'@'%' WITH GRANT OPTION;"

Звичайно, генерувати SQL за допомогою об'єднаного користувальницького вводу (переданих аргументів) не слід робити, якщо ви не довіряєте користувальницькому вводу. Було б набагато безпечніше розмістити його на іншій мові сценаріїв із підтримкою параметрів / правильно витікаючих рядків для вставки в MySQL.


5
mysql -h "hostname" -u usr_name -pPASSWD "db_name" < sql_script_file

( sql_script_fileпри необхідності використовувати повний шлях )

Якщо ви хочете перенаправити вихід, поставте файл

mysql -h "hostname" -u usr_name -pPASSWD "db_name" < sql_script_file > out_file

@Gus, Перш за все дякую за цінні коментарі. Це спрацювало як шарм для мене. Я хочу, щоб вихід був файлом excel або .csv. як я можу цього досягти. Заздалегідь спасибі.
Ash_and_Perl

@Ash_and_Perl Я лише відредагував цю відповідь, дякую не лозі мені, це його відповідь. Якщо у вас є власне питання, і ви вже намагалися знайти рішення самостійно , пропоную вам створити питання. Таким чином ви зможете детально описувати, що ви пробували, як не вдалося, і люди можуть дати вам повну повну відповідь (і отримати бали за це!).
Гас

5

Ви забули -pабо --password=(останнє краще читається):

mysql -h "$server_name" "--user=$user" "--password=$password" "--database=$database_name" < "filename.sql"

(Цитати не потрібні, якщо ви впевнені, що ваші облікові дані / імена не містять пробілів або спеціальних символів оболонки.)

Зауважте, що на сторінці сторінки також зазначено, що надання облікових даних у командному рядку не є безпечним. Тому дотримуйтесь порад Білла про my.cnf.


4

Як зазначено раніше, ви можете використовувати -p для передачі пароля серверу.

Але я рекомендую це:

mysql -h "hostaddress" -u "username" -p "database-name" < "sqlfile.sql"

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

Це основний захід безпеки.

Якщо безпека не стосується, я би просто тимчасово видалив пароль у користувача бази даних. Потім після імпорту - знову додайте його.

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

Також виявляється, що в сценарії оболонки ви не чекаєте / перевіряєте, чи існує файл, який ви намагаєтеся імпортувати. Сценарій perl ще не завершено.


1
Ви пропустили "автоматизовану" частину питання, а тимчасове видалення пароля - це справді погана ідея.
Вказано вухами

Я читав це як "відновити" і "автоматизовано", що означає "автоматизовано, але не назавжди". Але, як я сказав, "якщо безпека не стосується". Я згоден - це дійсно погана ідея.
Стерлінг Гамільтон

Мені шкода, якщо я створив плутанину. Що я мав на увазі під Автоматизованим, це те, що у мене є два сценарії Perl, які використовуються для генерування файлу .sql, але команда скинути цей файл у БД не працює за допомогою сценарію оболонки, але він працює абсолютно файлом, якщо я запускаю цю команду в командному рядку. Я хочу докласти зусиль до запуску цієї команди в командному рядку та запуску її через сценарій оболонки.
MUFC

1
Вайбав: якщо ви зможете помістити власний скрипт оболонки у своє запитання, я, можливо, зможу допомогти далі.
Стерлінг Гамільтон

perl fb_apps_frm_fb.pl</br> perl fb_new_spider.pl ds_fbids.txt ds_fbids.sql` </br>mysql -h dbservername -u username -ppassword dbname < ds_fbids.sql
MUFC


3

Щоб "автоматизувати" процес імпорту згенерованого .sqlфайлу, уникаючи при цьому всіх пасток, які можна приховати при спробі передачі файлів, stdinі stdoutпросто скажіть MySQL виконати створений .sqlфайл за допомогою SOURCEкоманди в MySQL.

Синтаксис у короткій, але чудовій відповіді від Kshitij Sood дає найкращу вихідну точку. Якщо коротко, змініть команду OP відповідно до синтаксису Кшитія Соода та замініть команди на SOURCEкоманду:

#!/bin/bash
mysql -u$user -p$password $dbname -Bse "SOURCE ds_fbids.sql
SOURCE ds_fbidx.sql"

Якщо ім'я бази даних включено в створений .sqlфайл, його можна скинути з команди.

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

Як вирішувати проблеми безпеки навколо пароля в командному рядку або у my.cnfфайлі тощо, було добре розглянуто в інших відповідях, з відмінними пропозиціями. Моя улюблена відповідь від Danny розповідає про це, включаючи те, як впоратися з проблемою під час cronроботи або будь-чого іншого.


Щоб вирішити коментар (запитання?) До короткої відповіді, яку я згадав: Ні, його не можна використовувати з синтаксисом HEREDOC, оскільки ця команда оболонки задана. HEREDOC можна використовувати в синтаксисі версії переадресації (без -Bseопції), оскільки перенаправлення вводу / виводу - це те, що HEREDOC будується навколо. Якщо вам потрібна функціональність HEREDOC, було б краще використовувати її при створенні .sqlфайлу, навіть якщо це тимчасовий, і використовувати цей файл як "команду" для виконання за допомогою пакетної лінії MySQL.

#!/bin/bash
cat >temp.sql <<SQL_STATEMENTS
...
SELECT \`column_name\` FROM \`table_name\` WHERE \`column_name\`='$shell_variable';
...
SQL_STATEMENTS
mysql -u $user -p$password $db_name -Be "SOURCE temp.sql"
rm -f temp.sql

Майте на увазі, що через розширення оболонки ви можете використовувати змінні оболонки та середовища в межах HEREDOC. Недоліком є ​​те, що ви повинні уникати кожного вибору. MySQL використовує їх як роздільники для ідентифікаторів, але оболонка, яка спочатку отримує рядок, використовує їх як виконувані роздільники команд. Пропустіть втечу на одному зворотному боці команд MySQL, і вся справа вибухне помилками. Всю проблему можна вирішити, скориставшись цитованим LimitString для HEREDOC:

#!/bin/bash
cat >temp.sql <<'SQL_STATEMENTS'
...
SELECT `column_name` FROM `table_name` WHERE `column_name`='constant_value';
...
SQL_STATEMENTS
mysql -u $user -p$password $db_name -Be "SOURCE temp.sql"
rm -f temp.sql

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

Інший варіант - використовувати рядки з цитованими рядками, дозволені в Bash, з версією пакетного синтаксису (з -Bse). Я не знаю інших снарядів, тому не можу сказати, чи вони також працюють у них. Вам потрібно буде використовувати це для виконання декількох .sqlфайлів з SOURCEкомандою так чи інакше, оскільки це не закінчується ;як інші команди MySQL, і лише один рядок дозволений. Багаторядковий рядок може бути одно- або подвійним цитуванням, з нормальним впливом на розширення оболонки. Він також має ті самі застереження, що і для використання синтаксису HEREDOC для заднього плану тощо.

Потенційно кращим рішенням буде використання мови сценаріїв, Perl, Python тощо, щоб створити .sqlфайл, як це робив ОП, і SOURCEцей файл, використовуючи простий синтаксис команди вгорі. Мови сценаріїв набагато кращі при обробці рядків, ніж оболонка, і більшість мають вбудовані процедури для обробки котирувань та уникнення, необхідних під час роботи з MySQL.


2

Важливим фактором доступу до mysql із скрипту оболонки, що використовується в cron, є те, що mysql дивиться на зареєстрованого користувача, щоб визначити .my.cnf для завантаження.

Це не працює з кроном. Це також може заплутатися, якщо ви використовуєте su / sudo, оскільки користувач, який увійшов у систему, може бути не тим користувачем, якого ви використовуєте.

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

mysql --defaults-extra-file=/path/to/specific/.my.cnf -e 'SELECT something FROM sometable'

Просто переконайтеся, що право власності та дозволи користувачів та групи встановлені у файлі .my.cnf належним чином та щільно.


1
#!/bin/sh
#Procedures = update
#Scheduled at : Every 00.05 

v_path=/etc/database_jobs
v_cnt=0

MAILTO="indd@abc.in joanson@abc.in sturt@abc.in"
touch "$v_path/db_db_log.log"

#test
mysql -uusername -ppassword -h111.111.111.111 db_name -e "CALL functionName()" > $v_path/db_db_log.log 2>&1
if [ "$?" -eq 0 ]
  then
   v_cnt=`expr $v_cnt + 1`
  mail -s "db Attendance Update has been run successfully" $MAILTO < $v_path/db_db_log.log
 else
   mail -s "Alert : db Attendance Update has been failed" $MAILTO < $v_path/db_db_log.log
   exit
fi

0
mysql_config_editor set --login-path=storedPasswordKey --host=localhost --user=root --password

Як виконати командний рядок із захищеним паролем ?? використовувати конфігураційний редактор !!!

Станом на mysql 5.6.6 ви можете зберігати пароль у конфігураційному файлі, а потім виконувати такі команди cli, як це ....

mysql --login-path=storedPasswordKey ....

--login-path замінює змінні ... хост, користувач І пароль. відмінна справа!



0

Я написав скрипт оболонки, який буде читати дані з файлу властивостей, а потім запускати скрипт mysql на скрипті оболонки. поділитися цим може допомогти іншим.

#!/bin/bash
    PROPERTY_FILE=filename.properties

    function getProperty {
       PROP_KEY=$1
       PROP_VALUE=`cat $PROPERTY_FILE | grep "$PROP_KEY" | cut -d'=' -f2`
       echo $PROP_VALUE
    }

    echo "# Reading property from $PROPERTY_FILE"
    DB_USER=$(getProperty "db.username")
    DB_PASS=$(getProperty "db.password")
    ROOT_LOC=$(getProperty "root.location")
    echo $DB_USER
    echo $DB_PASS
    echo $ROOT_LOC
    echo "Writing on DB ... "
    mysql -u$DB_USER -p$DB_PASS dbname<<EOFMYSQL

    update tablename set tablename.value_ = "$ROOT_LOC" where tablename.name_="Root directory location";
    EOFMYSQL
    echo "Writing root location($ROOT_LOC) is done ... "
    counter=`mysql -u${DB_USER} -p${DB_PASS} dbname -e "select count(*) from tablename where tablename.name_='Root directory location' and tablename.value_ = '$ROOT_LOC';" | grep -v "count"`;

    if [ "$counter" = "1" ]
    then
    echo "ROOT location updated"
    fi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.