web-dev-qa-db-ja.com

シェルスクリプトからMySQLコマンドを実行する方法

自動化できるように、シェルスクリプトを介して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

これを行う正しい方法は何ですか?

110
MUFC

パスワードを送信するには-pフラグを使う必要があります。 -pとパスワードの間にスペースを入れないでください。

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

-pの後にスペースを使用すると、mysqlクライアントは対話的にパスワードの入力を要求し、それから次のコマンド引数をdatabase-nameとして解釈します。

$ 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コマンドをコマンドラインとシェルスクリプトで常に実行しています。正確なスクリプトやエラー出力を共有していないため、Shellスクリプトの問題点を診断するのは困難です。上記の元の質問を編集して、問題が発生した例を示してください。

また、シェルスクリプトのトラブルシューティングを行うときは、-xフラグを使用して、各コマンドがどのように実行されているかを確認できます。

$ bash -x myscript.sh
155
Bill Karwin

この構文を使用してください。

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

前の答えはすべて素晴らしいです。実行したい単純な1行のSQLコマンドであれば、-eオプションを使用することもできます。

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

SQLスクリプトの実行方法は、次の構文を使用してください。

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

ローカルホストとしてホストを使用している場合は、言及する必要はありません。これを使うことができます:

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

これはWindowsとLinuxで動作するはずです。

パスワードの内容に!(感嘆符)が含まれる場合は、その前に\(円記号)を追加する必要があります。

18
Milinda Bandara

質問の核心はすでに数回回答されています、私はちょうど私がバックスクリプツ( `s)がシェルスクリプトとSQLの両方でBean化を持っていると付け加えたいと思いました。テーブルやデータベースの名前を指定するために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に。

8
Li1t

-pまたは--password=を忘れました(後者の方が読みやすいです)。

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

(資格情報/名前にスペースやシェル特殊文字が含まれていないことが確実な場合は、引用符は不要です。)

マンページにも、コマンドラインで資格情報を提供するのは安全ではないと書かれていることに注意してください。だから、my.cnfに関するBillのアドバイスに従ってください。

5
PointedEars
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
5
vine

前述のように、-pを使用してパスワードをサーバーに渡すことができます。

しかし私はこれをお勧めします:

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

パスワードがないことに注意してください。それはそれからあなたのパスワードを促すでしょう。パスワードをサーバーのコマンドライン履歴にログインさせないようにしてください。

これは基本的なセキュリティ対策です。

セキュリティが問題にならない場合は、データベースユーザーから一時的にパスワードを削除します。その後、インポートした後 - それを再度追加します。

これにより、同じパスワードを共有している他のアカウントが危険にさらされることはありません。

また、あなたのシェルスクリプトでは、あなたがインポートしようとしているファイルが実際に存在するかどうかを確認するのを待っている/チェックしていないようです。 Perlスクリプトはまだ完成していないかもしれません。

4

Cronで使用されているシェルスクリプトからmysqlにアクセスする際の重要な考慮事項は、mysqlがログインユーザーを調べてロードする.my.cnfを決定することです。

これはcronでは機能しません。ログインユーザーがあなたが実行しているユーザーではないかもしれないのでsu/Sudoを使用している場合も混乱を招く可能性があります。

私はのようなものを使います:

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

ユーザーとグループの所有権とアクセス許可が.my.cnfファイルに適切かつ厳密に設定されていることを確認してください。

2
Danny

つかいます

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

私は、プロパティファイルからデータを読み込み、シェルスクリプト上で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
0
flopcoder
mysql_config_editor set --login-path=storedPasswordKey --Host=localhost --user=root --password

安全なパスワードでコマンドラインを実行する方法設定エディタを使用してください。

Mysql 5.6.6以降では、パスワードを設定ファイルに保存してから次のようなcliコマンドを実行できます。

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

--login-pathは変数を置き換えます...ホスト、ユーザー、パスワード。いいね!

0
Artistan
#!/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
0
kartavya soni

生成された.sqlファイルをインポートするプロセスを「自動化」するには、ファイルをstdinおよびstdoutを通過させようとして隠される可能性のあるすべてのトラップを回避しながら、MySQLにSOURCEコマンドを使用して生成された.sqlファイルを実行するように指示します。

簡潔ではあるが優れた、 Kshitij Sood からの answer の構文が最良の出発点となります。つまり、Kshitij Soodの構文に従ってOPのコマンドを変更し、その中のコマンドをSOURCEコマンドに置き換えます。

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

データベース名が生成された.sqlファイルに含まれている場合は、コマンドから削除することができます。

ここでの仮定は、生成されたファイルはそれ自身で.sqlファイルとしてvalidであるということです。ファイルをリダイレクト、パイプ処理、またはその他の方法でシェルで処理しないようにすることで、シェルのために生成された出力内の文字をエスケープする必要がなくなります。 .sqlファイルでエスケープする必要があるものに関する規則は、もちろん適用されます。

コマンドラインまたはmy.cnfファイルなどのパスワードに関するセキュリティ問題に対処する方法は、いくつかの優れた提案とともに、他の回答でよく取り上げられています。 Danny からの私の お気に入りの回答 は、cronの仕事を扱うときの問題をどう処理するかなどを含みます。


私が言った短い答えで コメント (質問?)に対処するには:いいえ、そのシェルコマンドが与えられているので、HEREDOC構文と一緒に使用することはできません。 HEREDOCはredirectionバージョン構文で使用できます(-Bseオプションなし)。HEREDOCは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内でシェル変数と環境変数を使用できることに注意してください。欠点はevery and everyバックティックをエスケープする必要があるということです。 MySQLは識別子の区切り文字としてそれらを使用しますが、シェルは最初に文字列を取得し、実行可能なコマンド区切り文字としてそれらを使用します。 MySQLコマンドの1つのバッククォートでエスケープを見逃すと、全体がエラーで爆発します。問題全体は、HEREDOCに引用符付きのLimitStringを使用することで解決できます。

#!/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を使用する利点をほとんど取り除きます。

もう1つの選択肢は、Bashでバッチ構文バージョン(-Bseを含む)で許可されている複数行の引用符付き文字列を使用することです。私は他のシェルを知りません、それで彼らが同様にそこで働くかどうか私は言うことができません。 SOURCEコマンドで複数の.sqlファイルを実行するには、これを使用する必要があります。これは、他のMySQLコマンドと同様にnot;で終了し、1行に1つだけ許可されるためです。複数行の文字列は一重引用符または二重引用符のどちらでもかまいませんが、通常のシェル展開には影響があります。また、バックティックなどにHEREDOC構文を使用するのと同じ警告があります。

よりよい解決策は、OPがそうであったように、スクリプト言語、Perl、Pythonなどを使用して.sqlファイルを作成し、そのファイルをSOURCEで上部に作成することです。スクリプト言語はシェルよりも文字列操作がはるかに優れており、ほとんどの場合、MySQLを扱うときに必要な引用符とエスケープを処理するための組み込みプロシージャがあります。

0