はじめに
どうも。自称インフラエンジニヤ*1のかっぱです。わたくしが MySQL
のテーブルメンテナンスのシェルスクリプトを書いた際に役立ったことを幾つか書いてみることにします。
参考文献
- C言語において、NULL と 0 と '\0' の違いは何ですか?
- C言語の基礎(5-3 main関数に引数を渡す)
- Coreutils - GNU core utilities
- GNU
- Where can I find source code for Linux core commands?
- シェルスクリプトで空文字列かどうか調べる。
- 3.5. バッチモードでの mysql の使用
- MySQLをコマンドラインから直接実行&出力形式の変更方法
mysql --execute オプションでクエリを標準出力した際の出力結果を調整する
インフラエンジニヤは mysql
のコンソールにログインしてしまったら負けだと自負*2しているので頻繁に --execute
オプションを利用してクエリーを投げて結果の取得を繰り返しております...
mysql -uroot -p --execute="show databases"
以下のように出力されます。
おお。上図だと見た目は綺麗でスクリーンショットを撮って資料に添付すると大変喜ばれることうけ合いですが、このテーブル表示をスクリプトでどうこうしようとするととにかく面倒極まりない。そんなお困りの皆様に朗報です。
-N オプション
まずは -N
オプション。
ヘルプによると出力結果でカラムの表示を抑制します。
mysql -uroot -p -N --execute="show databases"
以下のような結果になります。
確かに -N
オプションを付けない場合に比べるとカラム名が表示されなくなりました。でも、これでも何か物足りなさを感じます。ということで...
-B オプション
合わせ技で -B
を付けてしまいましょう。
ヘルプの言葉を借りるとバッチオプション。対話式の表示を抑制してより簡潔な出力となるようです。ということで、-N
と -B
を合わせて使うと...
mysql -uroot -p -N -B --execute="show databases"
以下のように出力されます。
おお、これでスクリプトから取得して加工もし易くなりましたな。尚、こちらによるとバッチモードでは出力をタブ区切りで出力してくれるとのことですので出力をそのまま Excel
等にコピペも出来そうですね。
条件に該当するテーブルを取得する
テーブルの中のレコードから条件に該当するレコードを取得する場合には WHERE
句を利用しますが...
データベース内にあるテーブル名を取得する場合には以下のようにして取得出来ます。
mysql -uroot -p hoge --execute="show tables from hoge like 'hoge_01'"
以下のように表示されます。
おお、条件に合致したテーブル名が取得出来ました。これを先ほどの -N
と -B
を組み合わせることでテーブルの操作をシェルスクリプトで書くことが出来るようになると思います。もちろん、ヒアドキュメントを駆使してそのまま SQL
文を流した方が MySQL
への接続効率も良いとは思いますがちょっとしたことならコレで十分かなーと考えています。
MySQL とは関係ないけど test コマンドの -n について
シェルの test
コマンドはシェルスクリプターにとって無くてはならないものだと思っています。その test
コマンドで文字列評価演算子の一つ -n
オプションについて少しハマったので記録を残しておきます。
この -n
オプションですが、上図の man
にもあるように評価する文字列長が 0 で無ければ真と判断されます。ちなみに -z
だとその逆の評価する文字列長が 0 であれば真と判断されます。この -n
オプションや -z
オプションを利用して以下のような変数内の文字列長をチェックするシェルスクリプトを書いた場合...
HOGE="" if [ -n ${HOGE} ]; then echo "string nonzero"; else echo "string zero"; fi
string zero
という結果が返ってきて欲しいのですが、以下のように期待通りにはなりません。
また、以下のようにすると状態が解りやすいかもしれません。
# return 0 test -n abc && echo $? # return 0 test -n && echo $? # return 1 test -n "" && echo $?
理由について test
コマンドのソースコードを見るとなんとなく推測出来そうです。
case 'n': /* True if arg has some length. */ unary_advance (); return argv[pos - 1][0] != 0; case 'z': /* True if arg has no length. */ unary_advance (); return argv[pos - 1][0] == '\0';
こちらをダウンロードしてきて展開して src/test.c
の 493
行目あたりに上記のように記載されていました。この部分から以下のように推測します。
n
オプション時は続く引数の長さをチェックするしている- ちなみに
z
オプションは続く引数(文字列)が空であることをチェックしている
n
オプション時には引数の文字列の長さが 0
以外であることが条件ですが、何も引数を与えない場合には 0
以外と判断されて真を返してしまうのかもしれませんので明示的に "
(ダブルクォート)で括って文字列長を認識させて上げる必要があるのではないかと思われます。
ということで、だいぶん回り道をしてしまいましたが、以下のように変数はダブルクォートで囲って上げることで文字列長を判断してくれるようになりました。
if [ -n "${HOGE}" ]; then echo "string nonzero"; else echo "string zero"; fi
さいごに
- 変なテンションで記事を書いてしまったことをお詫び申し上げます