ようへいの日々精進XP

よかろうもん

インフラエンジニヤが MySQL のメンテナンススクリプトを書く時とかに役立ちそうなこと

はじめに

どうも。自称インフラエンジニヤ*1のかっぱです。わたくしが MySQL のテーブルメンテナンスのシェルスクリプトを書いた際に役立ったことを幾つか書いてみることにします。


参考文献


mysql --execute オプションでクエリを標準出力した際の出力結果を調整する

インフラエンジニヤは mysql のコンソールにログインしてしまったら負けだと自負*2しているので頻繁に --execute オプションを利用してクエリーを投げて結果の取得を繰り返しております...

mysql -uroot -p  --execute="show databases"

以下のように出力されます。

f:id:inokara:20140111053314p:plain

おお。上図だと見た目は綺麗でスクリーンショットを撮って資料に添付すると大変喜ばれることうけ合いですが、このテーブル表示をスクリプトでどうこうしようとするととにかく面倒極まりない。そんなお困りの皆様に朗報です。

-N オプション

まずは -N オプション。

f:id:inokara:20140111054811p:plain

ヘルプによると出力結果でカラムの表示を抑制します。

mysql -uroot -p -N --execute="show databases"

以下のような結果になります。

f:id:inokara:20140111055046p:plain

確かに -N オプションを付けない場合に比べるとカラム名が表示されなくなりました。でも、これでも何か物足りなさを感じます。ということで...

-B オプション

合わせ技で -B を付けてしまいましょう。

f:id:inokara:20140111055423p:plain

ヘルプの言葉を借りるとバッチオプション。対話式の表示を抑制してより簡潔な出力となるようです。ということで、-N-B を合わせて使うと...

mysql -uroot -p -N -B --execute="show databases"

以下のように出力されます。

f:id:inokara:20140111061001p:plain

おお、これでスクリプトから取得して加工もし易くなりましたな。尚、こちらによるとバッチモードでは出力をタブ区切りで出力してくれるとのことですので出力をそのまま Excel 等にコピペも出来そうですね。


条件に該当するテーブルを取得する

テーブルの中のレコードから条件に該当するレコードを取得する場合には WHERE 句を利用しますが...

f:id:inokara:20140111062301p:plain

データベース内にあるテーブル名を取得する場合には以下のようにして取得出来ます。

 mysql -uroot -p hoge --execute="show tables from hoge like 'hoge_01'"

以下のように表示されます。

f:id:inokara:20140111062902p:plain

おお、条件に合致したテーブル名が取得出来ました。これを先ほどの -N-B を組み合わせることでテーブルの操作をシェルスクリプトで書くことが出来るようになると思います。もちろん、ヒアドキュメントを駆使してそのまま SQL 文を流した方が MySQL への接続効率も良いとは思いますがちょっとしたことならコレで十分かなーと考えています。


MySQL とは関係ないけど test コマンドの -n について

シェルの test コマンドはシェルスクリプターにとって無くてはならないものだと思っています。その test コマンドで文字列評価演算子の一つ -n オプションについて少しハマったので記録を残しておきます。

f:id:inokara:20140111064007p:plain

この -n オプションですが、上図の man にもあるように評価する文字列長が 0 で無ければ真と判断されます。ちなみに -z だとその逆の評価する文字列長が 0 であれば真と判断されます。この -n オプションや -z オプションを利用して以下のような変数内の文字列長をチェックするシェルスクリプトを書いた場合...

HOGE=""
if [ -n ${HOGE} ]; then echo "string nonzero"; else echo "string zero"; fi

string zero という結果が返ってきて欲しいのですが、以下のように期待通りにはなりません。

f:id:inokara:20140111065537p:plain

また、以下のようにすると状態が解りやすいかもしれません。

# 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.c493 行目あたりに上記のように記載されていました。この部分から以下のように推測します。

  • n オプション時は続く引数の長さをチェックするしている
  • ちなみに z オプションは続く引数(文字列)が空であることをチェックしている

n オプション時には引数の文字列の長さが 0 以外であることが条件ですが、何も引数を与えない場合には 0 以外と判断されて真を返してしまうのかもしれませんので明示的に "(ダブルクォート)で括って文字列長を認識させて上げる必要があるのではないかと思われます。

ということで、だいぶん回り道をしてしまいましたが、以下のように変数はダブルクォートで囲って上げることで文字列長を判断してくれるようになりました。

if [ -n "${HOGE}" ]; then echo "string nonzero"; else echo "string zero"; fi

さいごに

  • 変なテンションで記事を書いてしまったことをお詫び申し上げます

*1:インフラエンジニ屋

*2:ネタです