Bir kabuk betiğinden bir MySQL komutu nasıl çalıştırılır?


131

Otomatik hale getirebilmek için bir kabuk betiği aracılığıyla bir SQL komutunu nasıl çalıştırabilirim?

Bir kabuk komut dosyası kullanarak bir SQL dosyasında topladığım verileri geri yüklemek istiyorum. Bir sunucuya bağlanmak ve verileri geri yüklemek istiyorum. Komut, SSH komut satırı aracılığıyla ayrı olarak yürütüldüğünde çalışır.

Kullandığım komut bu:

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

Bu, dosyayı oluşturan ds_fbids.sqlve onu mysql'ye yönlendiren kabuk betiğidir .

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

Bunu yapmanın doğru yolu nedir?

Yanıtlar:


176

-pParola göndermek için bayrağı kullanmanız gerekir . Ve bu aldatıcıdır çünkü -pşifre ile arasında boşluk olmamalıdır .

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

-pMysql istemcisinin sizden parola için etkileşimli olarak sormasını sağladıktan sonra bir boşluk kullanırsanız ve ardından sonraki komut bağımsız değişkenini bir veritabanı adı olarak yorumlar:

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

Aslında, kullanıcıyı ve parolayı ~ / .my.cnf içinde saklamayı tercih ederim, bu yüzden komut satırına koymam gerekmez:

[client]
user = root
password = XXXXXXXX

Sonra:

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

Yorumunuz yeniden:

Yukarıdaki gibi toplu mod mysql komutlarını komut satırında ve her zaman kabuk betiklerinde çalıştırıyorum. Kabuk betiğinizde neyin yanlış olduğunu teşhis etmek zordur, çünkü tam komut dosyasını veya herhangi bir hata çıktısını paylaşmadınız. Yukarıda orijinal sorunuzu düzenlemenizi ve neyin yanlış gittiğine dair örnekler vermenizi öneririm.

Ayrıca bir kabuk betiğinde sorun giderirken -xbayrağı kullanıyorum, böylece her bir komutu nasıl çalıştırdığını görebiliyorum:

$ bash -x myscript.sh

Hızlı yanıt için teşekkürler. Parolayı komut satırının kendisine koymaktan yoruldum. Asıl sorun, bu komutu .sh dosyasına koyuyorum ve ardından bu kabuk betiğini çalıştırıyorum. Dosyadaki komut komut satırında çalıştırılmıyor, ancak aynı komut sadece komut satırındaki komutu çalıştırdığımda mükemmel çalışıyor.
MUFC

+ mysql -h dbservername -u user-name -ppassword dbname</br> : No such file or directoryids.sql</br> + $'\r' : command not found2:Bu aldığım hata mesajı
MUFC

Tamam, o zaman şu anki çalışma dizininizin ids.sql dosyasının bulunduğu yerde olmadığını anlıyorum. Ayrıca betiğinize yeni satırlar katmış olabilirsiniz.
Bill Karwin

Her komuttan sonra kabuk betiğime gömülü yeni satırlarım var. Kabuk betiğimin içerdiği tek şey, ayrı olarak çalıştırmak istemediğim 3 komut satırı komutu, bu yüzden onların müdahalem olmadan çalışmasını sağlamak için bir kabuk betiği oluşturdum ve her komuta yeni satır yazdım. Bu soruna mı neden oluyor?
MUFC

En iyisi -pşifre null veya boş dizedir, belki yayınınızı güncelleyebilirsiniz? :)
James Oravec

118

Bu sözdizimini kullanın:

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

8
Bu sayfaya google'dan geldim ve beklediğim çözüm bu (sorunun başlığıyla eşleşen).
Janaka R Rajapaksha

16
Kılavuzdaki seçenekler hakkında daha fazla ayrıntı: -B toplu iş içindir, sonuçları sütun ayırıcı olarak sekmeyi kullanarak, her satır yeni bir satırda olacak şekilde yazdırın. Bu seçenek ile mysql geçmiş dosyasını kullanmaz. Toplu iş modu, düzensiz çıktı biçimine ve özel karakterlerin kaçmasına neden olur. -s sessiz moddur. Daha az çıktı üretin. -e ifadeyi yürütmek ve
çıkmaktır

Yardımınız için teşekkürler! :)
haotang

Bir yorum yazarı ile çalışabilir mi?
zx1986

1
@ zx1986 Evet ve Hayır, HEREDOC'a. Nasıl kullanmak istediğine bağlı. Değiştirmek için kullanma"command1;command2;....;commandn"Bu cevabın bir kısmını işe yaramayacaktır. Bunu kullanarak OP'ın sözdizimi içinde yönlendirilen dosyasının kullanılmasını yerine teneke işleri. Bu soruya verdiğim yanıtta bu sorunu ele aldım .
Chindraba

45

Önceki cevapların tümü harika. Çalıştırmak istediğiniz basit, tek satırlık bir sql komutu ise, -e seçeneğini de kullanabilirsiniz.

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

Çift ("") tırnak içinde sorgulama yapmam gereken şeydi. Teşekkürler
user3132107

Anlıyorum ve sanırım sorgunun sonuna noktalı virgül eklemeniz gerekiyor?
Lori

19

Bir SQL komut dosyası nasıl çalıştırılır, bu sözdizimini kullanın:

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

Eğer host'u localhost olarak kullanıyorsanız, bundan bahsetmenize gerek yoktur. Bunu kullanabilirsiniz:

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

Bu, Windows ve Linux için çalışmalıdır.

Parola içeriğinde bir !(Ünlem işareti) varsa \, önüne bir (ters eğik çizgi) eklemelisiniz .


1
Veritabanı nasıl belirlenir? -e içinde mi olmalı, -e "abc; kaynak dbscript.sql kullan" gibi mi?
Abdul Muneer

9

Sorunun özü zaten birkaç kez yanıtlandı, yalnızca geri işaretlerin hem kabuk komut dosyasında hem de SQL'de başladığını eklemeyi düşündüm. Bunları bir tablo veya veritabanı adı belirtmek için SQL'de kullanmanız gerekirse, aşağıdaki gibi kabuk komut dosyasında bunlardan çıkış yapmanız gerekir:

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

Elbette, kullanıcı girdisine güvenmediğiniz sürece, birleştirilmiş kullanıcı girdisi (iletilen bağımsız değişkenler) aracılığıyla SQL oluşturmak yapılmamalıdır.Parametre desteği / ekleme için doğru şekilde kaçan dizeler ile başka bir betik diline koymak çok daha güvenli olacaktır. MySQL'e.


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

( sql_script_filegerekirse tam yolu kullanın )

Çıkışı bir dosyaya yönlendirmek istiyorsanız

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

@Gus, Öncelikle değerli yorumlarınız için teşekkürler. Benim için bir cazibe gibi çalıştı. Çıktının bir excel veya .csv dosyası olmasını istiyorum. bunu nasıl başarabilirim. Şimdiden teşekkürler.
Ash_and_Perl

@Ash_and_Perl Ben sadece bu cevabı düzenledim, teşekkürler bana değil, onun cevabı. Kendinize ait bir sorunuz varsa ve zaten kendi başınıza bir çözüm bulmaya çalıştıysanız , bir soru oluşturmanızı öneririm. Bu şekilde neyi denediğinizi, nasıl başarısız olduğunu detaylandırabilirsiniz ve insanlar size tam ve eksiksiz bir cevap verebilir (ve bunun için puan alabilir!).
Gus

5

Unuttun -pveya --password=(ikincisi daha iyi okunabilir):

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

(Kimlik bilgilerinizin / adlarınızın boşluk veya kabuk özel karakterleri içermediğinden eminseniz, alıntılar gereksizdir.)

Man sayfasının da komut satırında kimlik bilgilerini sağlamanın güvensiz olduğunu söylediğini unutmayın. Bu yüzden, Bill'in my.cnf hakkındaki tavsiyelerine uyun.


4

Daha önce belirtildiği gibi, şifreyi sunucuya geçirmek için -p kullanabilirsiniz.

Ama şunu tavsiye ederim:

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

Parolanın orada olmadığına dikkat edin. Daha sonra parolanızı soracaktır. SONRA onu yazardım. Böylece şifreniz sunucuların komut satırı geçmişine giriş yapmaz.

Bu, temel bir güvenlik önlemidir.

Güvenlik bir sorun değilse, şifreyi veritabanı kullanıcısından geçici olarak kaldırırım. Ardından içe aktarmanın ardından - yeniden ekleyin.

Bu şekilde, aynı parolayı paylaşan diğer hesaplarınızın güvenliği ihlal edilmeyecektir.

Ayrıca, kabuk betiğinizde içe aktarmaya çalıştığınız dosyanın gerçekten var olup olmadığını görmek için beklemiyor / kontrol etmiyorsunuz. Perl betiği henüz bitmemiş olabilir.


1
Sorunun "otomatikleştirilmiş" kısmını kaçırdınız ve parolayı geçici olarak kaldırmak Gerçekten Kötü bir Fikirdir.
PointedEars

Onu "geri yükle" ve "otomatik" olarak okudum, yani "otomatik ama sonsuza kadar değil" anlamına geliyor. Ama dediğim gibi, "güvenlik sorun değilse". Katılıyorum - GERÇEKTEN kötü bir fikir.
Sterling Hamilton

Kafam karıştıysa özür dilerim. Otomatik ile kastettiğim, .sql dosyasını oluşturmak için kullanılan iki perl komut dosyam var, ancak bu dosyayı DB'ye dökmek için komut, kabuk komut dosyası tarafından çalıştırılmıyor, ancak bu komutu çalıştırırsam kesinlikle dosya olarak çalışıyor. bir komut satırında. Bu komutu komut satırında çalıştırma ve onu kabuk betiğinin kendisi aracılığıyla çalıştırma çabasını ortadan kaldırmak istiyorum.
MUFC

1
Vaibav: Sorunuzun içine gerçek kabuk komut dosyasını koyabilirseniz, size daha fazla yardımcı olabilirim.
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

kullanım

echo "your sql script;" | mysql -u -p -h db_name

3

Oluşturulan .sqldosyayı içe aktarma sürecini "otomatikleştirmek" için dosyaları iletmeye çalışırken gizlenebilecek tüm tuzaklardan kaçınırken stdinve stdoutMySQL'e oluşturulan .sqldosyayıSOURCE komutu .

Kısa, ama mükemmel sözdizimi cevap , gelen Kshitij Sood , iyi başlangıç noktası verir. Kısaca, OP'nin komutunu Kshitij Sood'un sözdizimine göre değiştirin ve içindeki komutları şu SOURCEkomutla değiştirin:

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

Veritabanı adı oluşturulan .sql dosyaya komuttan çıkarılabilir.

Buradaki varsayım, oluşturulan dosyanın kendi başına bir dosya olarak geçerli olmasıdır.sql . Dosyanın yeniden yönlendirilmemesi, borulanması veya başka bir şekilde kabuk tarafından işlenmemesi, kabuk nedeniyle üretilen çıktıdaki herhangi bir karakterden çıkma gereksinimi ile ilgili bir sorun yoktur. Bir .sqldosyada neyin kaçması gerektiğine ilişkin kurallar elbette hala geçerlidir.

Komut satırındaki veya bir my.cnfdosyadaki vb . Güvenlik sorunları ile nasıl başa çıkılacağı , bazı mükemmel önerilerle diğer yanıtlarda iyi bir şekilde ele alınmıştır. Benim favori cevap itibaren, Danny , kapaklar ile uğraşırken sorunu nasıl ele dahil olduğu, croniş, veya başka bir şey.


Bahsettiğim kısa cevapla ilgili bir yorumu (soru?) Ele almak için: Hayır, bu kabuk komutu verildiği için bir HEREDOC sözdizimi ile kullanılamaz. HEREDOC, G / Ç yeniden yönlendirmesinin inşa edildiği şey olduğundan, HEREDOC yeniden yönlendirme sürümü sözdiziminde ( -Bseseçenek olmadan ) kullanılabilir. HEREDOC işlevselliğine ihtiyacınız varsa, onu .sqlgeçici bir dosya oluştururken kullanmak ve bu dosyayı MySQL toplu iş satırıyla yürütmek için "komut" olarak kullanmak daha iyi olacaktır .

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

Kabuk genişlemesi nedeniyle HEREDOC içindeki kabuk ve ortam değişkenlerini kullanabileceğinizi unutmayın. Olumsuz tarafı, her ters vuruştan kaçmanız gerektiğidir . MySQL bunları tanımlayıcılar için sınırlayıcılar olarak kullanır, ancak dizeyi ilk alan kabuk bunları çalıştırılabilir komut sınırlayıcıları olarak kullanır. MySQL komutlarının tek bir backtickinde kaçışı kaçırırsanız her şey hatalarla patlar. Tüm sorun HEREDOC için alıntılanmış bir LimitString kullanılarak çözülebilir:

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

Kabuk genişletmesinin bu şekilde kaldırılması, geri işaretlerden ve diğer özel kabuk karakterlerinden kaçma ihtiyacını ortadan kaldırır. Ayrıca, içindeki kabuk ve ortam değişkenlerini kullanma yeteneğini de kaldırır. Bu, başlangıçta kabuk betiği içinde bir HEREDOC kullanmanın faydalarını hemen hemen ortadan kaldırır.

Diğer seçenek, Bash'de izin verilen çok satırlı alıntı dizelerini toplu sözdizimi sürümüyle (ile -Bse) kullanmaktır. Başka mermileri bilmiyorum, bu yüzden onların da orada çalışıp çalışmadığını söyleyemem. Birden fazla çalıştırmak için kullanmak gerekir .sqldosyayı SOURCEyani bu yana, zaten komutu değil bir sonlandırıldı ;diğer MySQL komutları gibi ve sadece bir satıra izin verilir. Çok satırlı dizge tek veya çift tırnaklı olabilir ve kabuk genişlemesi üzerindeki normal etkiler. Ayrıca HEREDOC sözdiziminin geri işaretler için yaptığı gibi aynı uyarılara sahiptir.

Potansiyel olarak daha iyi bir çözüm .sql, OP'nin yaptığı gibi dosyayı oluşturmak için bir komut dosyası dili, Perl, Python vb. SOURCEKullanmak ve bu dosyayı en üstteki basit komut sözdizimini kullanarak yapmak olacaktır. Komut dosyası dilleri, dize işlemede kabuktan çok daha iyidir ve çoğu MySQL ile uğraşırken gereken alıntı ve kaçış işlemlerini işlemek için yerleşik prosedürlere sahiptir.


2

Mysql'ye cron'da kullanılan bir kabuk komut dosyasından erişmek için önemli bir husus, mysql'nin yüklenecek bir .my.cnf dosyasını belirlemek için oturum açmış kullanıcıya bakmasıdır.

Bu cron ile çalışmaz. Ayrıca, su / sudo kullanıyorsanız, oturum açmış kullanıcı sizin çalıştırdığınız kullanıcı olmadığından kafa karıştırıcı olabilir.

Şöyle bir şey kullanıyorum:

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

Kullanıcı ve grup sahipliğinin ve izinlerinin .my.cnf dosyasında uygun ve sıkı bir şekilde ayarlandığından emin olun.


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

Güvenli bir parola ile bir komut satırını nasıl çalıştırırım? yapılandırma düzenleyicisini kullanın !!!

Mysql 5.6.6'dan itibaren parolayı bir yapılandırma dosyasında saklayabilir ve ardından bunun gibi cli komutlarını çalıştırabilirsiniz ...

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

--login-path değişkenleri değiştirir ... host, user AND password. mükemmel doğru!



0

Özellikler dosyasından verileri okuyacak ve ardından kabuk betiğinde mysql betiğini çalıştıracak bir kabuk betiği yazdım. bunu paylaşmak başkalarına yardımcı olabilir.

#!/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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.