awk で条件に合致する最後の行のみ処理する

経緯

次のようなシチュエーションを考えます。

  • Docker 環境で MySQL の初期パスワードを変更するシェルスクリプトをエントリポイントで実行
  • MySQL のログ (特に mysql-error.log) をボリュームマウントしてファイルの永続化を実施している
  • このプロジェクトでディレクトリを使い回して1回目の MySQL のログを削除せずに2回目のビルドを実行する

このとき、 mysql-error.log 内に初期パスワードが2回記録されることになります。

すると、条件に合致する最初の行(1回目の初期パスワード)を処理しようとした際に(2回目のパスワードが設定されているため)パスワードが合致せず、処理が失敗してしまう遭遇したので対処しました。

対処

-    DB_INIT_PASSWORD=$(sudo grep 'temporary password' /var/log/mysql/mysql-error.log | sudo awk '{print $13}')
+    DB_INIT_PASSWORD=$(sudo grep 'temporary password' /var/log/mysql/mysql-error.log | sudo awk 'END{print $13}')

エントリポイントのシェルスクリプトで、 awkEND を付け加えました。処置としてはこれだけ。

検証

試しに、中身のシェルスクリプトを該当環境で手動で実行してみます。

変更前

# sudo grep 'temporary password' /var/log/mysql/mysql-error.log | sudo awk '{print $13}'
XXXXXXXXXXXX
YYYYYYYYYYYY

変更前では複数マッチしていることが確認できます。このうち、最初のパスワード XXXXXXXXXXXX で認証をくぐって理しようとすると冒頭のようにパスワードが合致せず失敗します。

変更後

# sudo grep 'temporary password' /var/log/mysql/mysql-error.log | sudo awk 'END{print $13}'
YYYYYYYYYYYY

そこで変更後。今度は1回目のパスワード XXXXXXXXXXXX がヒットせず、2回目のパスワード YYYYYYYYYYYY のみがヒットするようになりました。

これで Docker Compose 全体のビルドもコケなくなりました。

参考

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。