Jak wykonać polecenie MySQL ze skryptu powłoki?

134

Jak mogę wykonać polecenie SQL za pomocą skryptu powłoki, aby można było je zautomatyzować?

Chcę przywrócić dane zebrane w pliku SQL za pomocą skryptu powłoki. Chcę połączyć się z serwerem i przywrócić dane. Polecenie działa, gdy jest wykonywane osobno za pomocą wiersza poleceń SSH.

Oto polecenie, którego używam:

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

To jest kod skryptu powłoki, który tworzy plik ds_fbids.sqli przekazuje go do 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

Jaki jest właściwy sposób, aby to zrobić?

MUFC
źródło

Odpowiedzi:

178

Musisz użyć -pflagi, aby wysłać hasło. Jest to trudne, ponieważ między -phasłem a hasłem nie może być spacji .

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

Jeśli użyjesz spacji po wyświetleniu -pprzez klienta mysql interaktywnego monitu o hasło, a następnie zinterpretuje następny argument polecenia jako nazwę bazy danych:

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

Właściwie wolę przechowywać użytkownika i hasło w ~ / .my.cnf, więc w ogóle nie muszę wpisywać ich w linii poleceń:

[client]
user = root
password = XXXXXXXX

Następnie:

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

Twój komentarz:

Uruchamiam polecenia mysql w trybie wsadowym, takie jak powyższe, w wierszu poleceń i skryptach powłoki przez cały czas. Trudno jest zdiagnozować, co jest nie tak ze skryptem powłoki, ponieważ nie udostępniono dokładnego skryptu ani żadnych wyników błędów. Proponuję edytować swoje pierwotne pytanie powyżej i podać przykłady nieprawidłowości.

Również podczas rozwiązywania problemów ze skryptem powłoki używam -xflagi, aby zobaczyć, jak wykonuje każde polecenie:

$ bash -x myscript.sh
Bill Karwin
źródło
Dzięki za szybką odpowiedź. Zmęczyłem się umieszczaniem hasła w samym wierszu poleceń. Prawdziwym problemem jest to, że umieszczam to polecenie w pliku .sh, a następnie wykonuję ten skrypt powłoki. Polecenie w pliku nie jest wykonywane w linii poleceń, ale to samo polecenie działa doskonale, gdy wykonuję tylko polecenie w wierszu poleceń.
MUFC
+ mysql -h dbservername -u user-name -ppassword dbname</br> : No such file or directoryids.sql</br> + $'\r' : command not found2:Oto komunikat o błędzie, który otrzymałem
MUFC
Ok, wnioskowałbym, że twój bieżący katalog roboczy nie znajduje się tam, gdzie znajduje się plik ids.sql. Możesz również mieć osadzone znaki nowej linii w swoim skrypcie.
Bill Karwin
Mam nowe wiersze osadzone w moim skrypcie powłoki po każdym poleceniu. Wszystko, co zawiera mój skrypt powłoki, to 3 polecenia wiersza poleceń, których nie chcę uruchamiać osobno, więc stworzyłem skrypt powłoki, aby działały bez mojej interwencji i umieszczam znak nowej linii po każdym poleceniu. Czy to powoduje problem?
MUFC
najlepiej unikać, -pjeśli hasło jest puste lub pusty ciąg, być może możesz zaktualizować swój post? :)
James Oravec
122

Użyj tej składni:

mysql -u $user -p$passsword -Bse "command1;command2;....;commandn"
Kshitij Sood
źródło
10
Na tę stronę trafiłem z google i jest to rozwiązanie, którego się spodziewałem (pasujące do tytułu pytania).
Janaka R Rajapaksha
17
Więcej szczegółów na temat opcji z podręcznika: -B oznacza wsad, drukuje wyniki używając tabulatora jako separatora kolumn, z każdym wierszem w nowej linii. Dzięki tej opcji mysql nie używa pliku historii. Tryb wsadowy skutkuje nietabelarycznym formatem wyjściowym i unikaniem znaków specjalnych. -s to tryb cichy. Produkuj mniej produktów. -e służy do wykonania instrukcji i zakończenia
wranvaud
Dzięki za pomoc! :)
haotang
Czy może działać z heredokiem?
zx1986
1
@ zx1986 Tak i nie, do HEREDOC. Zależy od tego, jak zamierzasz go używać. Użycie go do zastąpienia "command1;command2;....;commandn"części tej odpowiedzi nie zadziała. Użycie go do zastąpienia użycia przekierowanego pliku w składni OP może działać. Odniosłem się do tego problemu w mojej odpowiedzi na to pytanie.
Chindraba
45

Wszystkie poprzednie odpowiedzi są świetne. Jeśli jest to prosta, jednowierszowa komenda sql, którą chcesz uruchomić, możesz również użyć opcji -e.

mysql -h <host> -u<user> -p<password> database -e \
  "SELECT * FROM blah WHERE foo='bar';"
Jericon
źródło
Zapytanie w podwójnych („”) cudzysłowach było tym, co muszę zrobić. Dzięki
user3132107
Rozumiem i rozumiem, że na końcu zapytania należy umieścić średnik?
Lori
19

Jak wykonać skrypt SQL, użyj następującej składni:

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

Jeśli używasz hosta jako lokalnego, nie musisz o tym wspominać. Możesz użyć tego:

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

To powinno działać w systemach Windows i Linux.

Jeśli treść hasła zawiera !(wykrzyknik), należy dodać przed nim \(ukośnik odwrotny).

Milinda Bandara
źródło
1
Jak określić bazę danych? czy powinien znajdować się wewnątrz -e, na przykład -e "użyj abc; source dbscript.sql"?
Abdul Muneer
9

Na sedno pytania udzielono już odpowiedzi kilka razy, pomyślałem tylko, że dodam, że znaki odwrotne (y) mają beaning zarówno w skryptach powłoki, jak i SQL. Jeśli chcesz użyć ich w języku SQL do określenia nazwy tabeli lub bazy danych, musisz zmienić ich znaczenie w skrypcie powłoki w następujący sposób:

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

Oczywiście generowanie kodu SQL za pomocą połączonych danych wejściowych użytkownika (przekazane argumenty) nie powinno być wykonywane, chyba że ufasz wejściu użytkownika. Znacznie bezpieczniej byłoby umieścić go w innym języku skryptowym z obsługą parametrów / poprawnymi znakami ucieczki do wstawienia do MySQL.

Li1t
źródło
5
mysql -h "hostname" -u usr_name -pPASSWD "db_name" < sql_script_file

(w sql_script_filerazie potrzeby użyj pełnej ścieżki )

Jeśli chcesz przekierować wyjście do pliku

mysql -h "hostname" -u usr_name -pPASSWD "db_name" < sql_script_file > out_file
wino
źródło
@Gus, Przede wszystkim dzięki za cenne uwagi. U mnie zadziałało jak urok. Chcę, aby wynik był plikiem Excel lub .csv. jak mogę to osiągnąć. Z góry dziękuję.
Ash_and_Perl
@Ash_and_Perl Tylko zredagowałem tę odpowiedź, dziękuję Vine nie mnie, to jego odpowiedź. Jeśli masz własne pytanie i próbowałeś już samodzielnie znaleźć rozwiązanie , sugeruję utworzenie pytania. W ten sposób możesz szczegółowo opisać, czego próbowałeś, dlaczego się nie udało, a ludzie mogą udzielić Ci pełnej, kompletnej odpowiedzi (i zdobyć za to punkty!).
Gus
5

Zapomniałeś -plub --password=(to drugie jest lepiej czytelne):

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

(Cudzysłowy są niepotrzebne, jeśli masz pewność, że Twoje poświadczenia / nazwy nie zawierają spacji ani znaków specjalnych powłoki).

Zauważ, że strona podręcznika również mówi, że podanie poświadczeń w wierszu poleceń jest niebezpieczne. Więc postępuj zgodnie z radą Billa dotyczącą my.cnf.

PointedEars
źródło
4

Jak wspomniano wcześniej, możesz użyć -p do przekazania hasła do serwera.

Ale polecam to:

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

Zauważ, że nie ma tam hasła. Następnie poprosi o hasło. WTEDY wpisałbym to. Aby Twoje hasło nie zostało zalogowane w historii wiersza poleceń serwera.

To jest podstawowy środek bezpieczeństwa.

Jeśli bezpieczeństwo nie jest problemem, po prostu tymczasowo usunąłbym hasło z użytkownika bazy danych. Następnie po imporcie - dodaj go ponownie.

W ten sposób żadne inne konta, które możesz mieć, korzystające z tego samego hasła, nie zostaną naruszone.

Wydaje się również, że w skrypcie powłoki nie czekasz / nie sprawdzasz, czy plik, który próbujesz zaimportować, rzeczywiście istnieje. Skrypt Perla może nie zostać jeszcze ukończony.

Sterling Hamilton
źródło
1
Przegapiłeś „zautomatyzowaną” część pytania, a tymczasowe usunięcie hasła to naprawdę zły pomysł.
PointedEars
Czytam to jako „przywracanie” i „zautomatyzowane”, co oznacza „zautomatyzowane, ale nie na zawsze”. Ale jak powiedziałem „jeśli bezpieczeństwo nie jest problemem”. Zgadzam się - to NAPRAWDĘ zły pomysł.
Sterling Hamilton
Przepraszam, jeśli spowodowałem zamieszanie. Przez Automated miałem na myśli dwa skrypty Perla, które są używane do generowania pliku .sql, ale polecenie zrzucenia tego pliku do DB nie jest uruchamiane przez skrypt powłoki, ale działa absolutnie plik, jeśli uruchomię to polecenie w wierszu poleceń. Chcę wyeliminować wysiłek związany z uruchomieniem tego polecenia w wierszu poleceń i uruchomić go przez sam skrypt powłoki.
MUFC
1
Vaibav: gdybyś mógł umieścić w swoim pytaniu rzeczywisty skrypt powłoki, być może będę mógł dalej pomóc.
Sterling Hamilton
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

Posługiwać się

echo "your sql script;" | mysql -u -p -h db_name
senninha
źródło
3

Aby „zautomatyzować” proces importowania wygenerowanego .sqlpliku, unikając przy tym wszystkich pułapek, które mogą być ukryte podczas próby przepuszczenia plików, stdini stdoutpo prostu powiedz MySQL, aby wykonał wygenerowany .sqlplik za pomocą SOURCEpolecenia w MySQL.

Składnia w krótkim, ale bardzo dobre, odpowiedź , z Kshitij Sood , daje najlepszy punkt wyjścia. Krótko mówiąc, zmodyfikuj polecenie OP zgodnie ze składnią Kshitij Sood i zastąp polecenia w tym SOURCEpoleceniem:

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

Jeśli nazwa bazy danych jest zawarta w wygenerowanym .sqlpliku, można ją usunąć z polecenia.

Zakłada się tutaj, że wygenerowany plik jest sam w sobie ważny jako .sqlplik. Brak przekierowania pliku, potokowania lub w inny sposób obsługiwany przez powłokę nie powoduje problemu z koniecznością ucieczki któregokolwiek ze znaków w wygenerowanym wyjściu z powodu powłoki. Zasady dotyczące tego, co należy zmienić w .sqlpliku, oczywiście nadal obowiązują.

Sposób radzenia sobie z kwestiami bezpieczeństwa związanymi z hasłem w wierszu poleceń, w my.cnfpliku itp. Został dobrze omówiony w innych odpowiedziach, z kilkoma doskonałymi sugestiami. Moja ulubiona odpowiedź od Danny'ego obejmuje to, w tym sposób radzenia sobie z problemem podczas cronpracy lub cokolwiek innego.


Aby odpowiedzieć na komentarz (pytanie?) Do krótkiej odpowiedzi, o której wspomniałem: Nie, nie można jej używać ze składnią HEREDOC, ponieważ podano to polecenie powłoki. HEREDOC może być używany w składni wersji przekierowania (bez -Bseopcji), ponieważ przekierowanie I / O jest tym, na czym opiera się HEREDOC. Jeśli potrzebujesz funkcjonalności HEREDOC, lepiej byłoby użyć jej podczas tworzenia .sqlpliku, nawet jeśli jest to plik tymczasowy, i użyć tego pliku jako „polecenia” do wykonania z wierszem wsadowym 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

Należy pamiętać, że ze względu na rozszerzenie powłoki w HEREDOC można używać zmiennych powłoki i środowiska. Wadą jest to, że musisz uciec przed każdym backtickiem. MySQL używa ich jako separatorów dla identyfikatorów, ale powłoka, która jako pierwsza pobiera łańcuch, używa ich jako separatorów poleceń wykonywalnych. Przegap ucieczkę za jednym kliknięciem wstecz w poleceniach MySQL, a całość eksploduje błędami. Cały problem można rozwiązać, korzystając z cytowanego limitu dla 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

Usunięcie rozszerzenia powłoki w ten sposób eliminuje potrzebę ucieczki przed znakami odwrotnymi i innymi znakami specjalnymi powłoki. Usuwa również możliwość używania w nim zmiennych powłoki i środowiska. To właściwie usuwa korzyści płynące z używania HEREDOC wewnątrz skryptu powłoki.

Inną opcją jest użycie wielowierszowych cudzysłowów dozwolonych w Bash z wersją składni wsadowej (z -Bse). Nie znam innych muszli, więc nie mogę powiedzieć, czy one też w nich działają. Będziesz musiał użyć tego do wykonania więcej niż jednego .sqlpliku z SOURCEpoleceniem i tak, ponieważ nie jest to przerywane przez a, ;jak inne polecenia MySQL, a tylko jeden jest dozwolony w każdym wierszu. Łańcuch wielowierszowy może być ujęty w pojedyncze lub podwójne cudzysłowy, z normalnym wpływem na rozwinięcie powłoki. Ma również te same zastrzeżenia, co użycie składni HEREDOC w przypadku grawitacji itp.

Potencjalnie lepszym rozwiązaniem byłoby użycie języka skryptowego, Perla, Pythona itp., Aby utworzyć .sqlplik, tak jak zrobił to OP, i SOURCEten plik przy użyciu prostej składni poleceń u góry. Języki skryptowe znacznie lepiej radzą sobie z operacjami na łańcuchach niż powłoka, a większość z nich ma wbudowane procedury do obsługi cytowań i znaków ucieczki potrzebnych podczas pracy z MySQL.

Chindraba
źródło
2

Ważną kwestią podczas uzyskiwania dostępu do mysql ze skryptu powłoki używanego w cron jest to, że mysql sprawdza zalogowanego użytkownika, aby określić plik .my.cnf do załadowania.

To nie działa z cronem. Może to również być mylące, jeśli używasz su / sudo, ponieważ zalogowany użytkownik może nie być użytkownikiem, jako którego używasz.

Używam czegoś takiego:

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

Po prostu upewnij się, że prawa własności i uprawnienia użytkowników i grup są ustawione odpowiednio i ściśle w pliku .my.cnf.

Danny
źródło
1
#!/bin/sh
#Procedures = update
#Scheduled at : Every 00.05 

v_path=/etc/database_jobs
v_cnt=0

MAILTO="[email protected] [email protected] [email protected]"
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
kartavya soni
źródło
0
mysql_config_editor set --login-path=storedPasswordKey --host=localhost --user=root --password

Jak wykonać wiersz poleceń z bezpiecznym hasłem? użyj edytora konfiguracji !!!

Począwszy od mysql 5.6.6 możesz przechowywać hasło w pliku konfiguracyjnym, a następnie wykonywać polecenia CLI, takie jak to ...

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

--login-path zastępuje zmienne ... host, użytkownik ORAZ hasło. świetnie, prawda!

Artistan
źródło
0

Napisałem skrypt powłoki, który odczyta dane z pliku właściwości, a następnie uruchomi skrypt mysql na skrypcie powłoki. dzielenie się tym może pomóc innym.

#!/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
flopcoder
źródło