シェルスクリプトから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"

-pmysqlクライアントがインタラクティブにパスワードを要求するようにした後でスペースを使用すると、次のコマンド引数がデータベース名として解釈されます。

$ 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:これは私が
受け取っ

さて、私はあなたの現在の作業ディレクトリがids.sqlファイルが置かれている場所ではないと推測します。また、スクリプトに改行が埋め込まれている場合もあります。
Bill Karwin

すべてのコマンドの後に、シェルスクリプトに新しい行が埋め込まれています。シェルスクリプトに含まれているのは3つのコマンドラインコマンドだけで、個別に実行したくないため、介入なしで実行できるようにシェルスクリプトを作成し、すべてのコマンドに改行を追加しました。それが問題の原因ですか?
MUFC

-pパスワードがnullまたは空の文字列の場合は回避するのが最善です。投稿を更新できますか?:)
James Oravec、2015年

118

次の構文を使用します。

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

8
私はグーグルからこのページに着きました、そしてこれは私が期待した解決策です(質問のタイトルと一致しています)。
Janaka R Rajapaksha

15
マニュアルのオプションの詳細:-Bはバッチの場合で、タブを列の区切りとして使用し、各行を新しい行に出力します。このオプションを使用すると、mysqlは履歴ファイルを使用しません。バッチモードでは、表形式ではない出力形式と特殊文字のエスケープが行われます。-sはサイレントモードです。出力を減らします。-eはステートメントを実行して終了します
wranvaud

ご協力いただきありがとうございます!:)
haotang 2017年

ヒアドキュメントで実行できますか?
zx1986

1
@ zx1986はい、いいえ、HEREDOCに。それをどのように使用するかによって異なります。これを使用して"command1;command2;....;commandn"この回答の一部を置き換えることはできません。これを使用して、OPの構文でリダイレクトされたファイルの使用を置き換えることができます。私はこの問題への私の答えでその問題に対処しました。
チンドラバ

45

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

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

double( "")引用符内のクエリは、私がする必要があるものでした。ありがとう
user3132107

わかりました。クエリの最後にセミコロンを含める必要があると思いますか。
ロリ

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 "use abc; source dbscript.sql"のように-e内にある必要がありますか?
Abdul Muneer 2014年

9

質問の核心はすでに何度か回答されていますが、バックスクリプト( `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 2014年

@Ash_and_Perl私はこの回答を編集しただけです。私ではなくvineに感謝します。それは彼の回答です。自分の質問があり、自分で解決策を見つけようとした場合は、質問を作成することをお勧めします。そうすることで、何を試したか、どのように失敗したかを詳しく説明でき、人々はあなたに完全で完全な答えを与えることができます(そしてそのためのポイントを獲得できます!)。
ガス

5

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

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

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

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


4

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

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

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

パスワードがないことに注意してください。次に、パスワードの入力を求めます。次に、それを入力します。これにより、パスワードがサーバーのコマンドライン履歴に記録されなくなります。

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

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

これにより、同じパスワードを共有する他のアカウントが侵害されることはありません。

また、シェルスクリプトでは、インポートしようとしているファイルが実際に存在するかどうかを確認または確認するために待機していないようです。Perlスクリプトはまだ完了していない可能性があります。


1
あなたは質問の「自動化された」部分を見逃しており、一時的にパスワードを削除することは本当に悪い考えです。
PointedEars

私はそれを「復元」と「自動化」と読みました。しかし、私が言ったように「セキュリティが問題ではない場合」。私は同意します-それは本当に悪い考えです。
スターリングハミルトン

ご迷惑をおかけして申し訳ございません。自動化とは、.sqlファイルの生成に使用される2つのperlスクリプトを持っていることですが、そのファイルをDBにダンプするコマンドはシェルスクリプトでは実行されませんが、そのコマンドを実行すると完全に機能しますコマンドラインで。コマンドラインでそのコマンドを実行する手間を省き、シェルスクリプト自体で実行したいと考えています。
MUFC

1
Vaibav:実際のシェルスクリプトを質問の中に入れることができれば、私はさらにお手伝いできるかもしれません。
スターリングハミルトン

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

使用する

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

3

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

Kshitij Soodからの短いが優れた回答の構文は、最良の開始点を提供します。つまり、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ファイルなどでパスワードに関するセキュリティの問題に対処する方法は、いくつかの優れた提案とともに他の回答で十分に対処されています。ダニーからの私のお気に入りの回答は、仕事や他の何かを扱うときに問題を処理する方法を含め、それをカバーしています。cron


私が述べた短い回答に関するコメント(質問?)に対処するには:いいえ、そのシェルコマンドが指定されているため、HEREDOC構文では使用できません。I / OリダイレクションはHEREDOCが構築されているため、HEREDOCはリダイレクションバージョンの構文で使用できます(-Bseオプションなし)。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コマンドの単一のバックティックでエスケープを逃すと、すべてがエラーで爆発します。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)で使用することです。私は他のシェルを知らないので、それらがそこでも動作するかどうかはわかりません。とにかくコマンドで複数の.sqlファイルを実行するには、これを使用する必要があります。これは、他のMySQLコマンドのようにで終了され、1行に1つしか許可されないためです。複数行の文字列は一重引用符または二重引用符で囲むことができ、シェルの展開に対する通常の影響があります。また、バッククォートなどにHEREDOC構文を使用する場合と同じ注意事項があります。SOURCE;

潜在的に優れたソリューションは.sql、OPと同じように、スクリプト言語、Perl、Pythonなどを使用してファイルを作成し、SOURCEそのファイルを上部の単純なコマンド構文を使用して作成することです。スクリプト言語は、シェルよりも文字列操作がはるかに優れており、ほとんどの場合、MySQLを処理するときに必要な引用とエスケープを処理する組み込みのプロシージャがあります。


2

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

これはcronでは機能しません。ログインしたユーザーが実行しているユーザーではない可能性があるため、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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.