MySQL一覧

【Linux/MySQL】logrotateでmysqlのログファイルを簡単にローテーションする

MySQLの運用中に問題が発生したとき、原因の切り分けに真っ先に確認するのがログファイルです。
しかし、MySQLのログファイルはデフォルトでローテーションの仕組みを持たないため、放っておくとどんどん肥大化していきます。

Linuxにはこのような問題を解消するために、logrotateという機能が備わっています。
logrotateを使うことで、任意のスケジュールに従ってログファイルをローテーションさせることができます。

バージョン

  • CentOS7
  • MySQL5.7

MySQLのログファイル

logrotateの説明の前に、念のためMySQLのログファイルの種類と配置先を確認しておきます。
デフォルトでは以下の3種類のログが、CentOSならば/var/log/mysqlに出力されています。

query.log 一般クエリログ。実行された全てのクエリが記録されます。
slow_query.log スロークエリログ。処理に時間のかかったクエリが記録されます。
error.log エラーログ。MySQLサーバーから出力されるエラーメッセージが記録されます。

query.logは基本的にデバッグの用途で使用するものなので、開発中のみ出力させて本番運用では出力を止めるのが一般的です。
他の二つは問題が発生したときの手掛かりとなるため、本番運用でも必ず出力させましょう。

logrotateって何?

logrotateは、ほとんどのLinuxディストリビューションで初期から導入されているファイル世代管理用のコマンドです。
cron(またはcronから起動されるanacron)によって実行され、自動的にファイルのローテーションを行ってくれています。

ローテーションの対象はbootログやsecureログなどのシステムログですが、設定を追加すれば任意のファイルをローテーションさせることができます。
logrotateという名前ですが、ログファイルに限らずどんなファイルでもローテーションさせることができます。
たとえば日次取得するバックアップファイルの世代管理をlogrotateで行うことも可能です。

基本的にLinuxでのファイル世代管理は、logrotateにお任せしてしまって問題ないでしょう。

logrotateで任意のファイルをローテーションする方法

logrotateへの設定追加方法はとても簡単で、設定ファイルを作成し、/etc/logrotate.dディレクトリに格納するだけです。
/etc/logrotate.dを確認すると、既にデフォルトでいくつかの設定ファイルが配置されていると思います。

/etc/logrotate.d
├ bootlog
├ httpd
├ mysql
├ syslog
├ yum


今回のケースでも、MySQLログファイル用のローテーション設定を作成し、/etc/logrotate.d配下に置くことで、cronが自動的にlogrotateを実行してくれるようになります。

logrotate設定ファイルの作成

それでは、設定ファイルを作成します。
/etc/logrotate.d/mysql-logsというファイルを作成し、以下の例を参考に設定を記述してみましょう。

/var/log/mysql/error.log
/var/log/mysql/slow_query.log
{
    create 644 mysql mysql  # ローテーション後に空のログファイルを新規作成する(パーミションとオーナーを指定)
    notifempty  # ファイルが空の場合はローテーションしない
  daily  # 毎日ローテーソンを実行する
    rotate 30  # 30世代分古いログを残す
    missingok  # ログファイルが存在しなくてもエラーを出さずに処理を続行する
    nocompress  # ローテーションしたログの圧縮を行わない
    dateext  # ローテーションしたファイルの名称に日付を付与する
    sharedscripts  # ログファイルを複数指定している場合、postrotate内に記述したスクリプトを一回だけ実行
  postrotate  # ログローテーション後に以下のスクリプトを実行
  if test -x /usr/bin/mysqladmin && \
     /usr/bin/mysqladmin ping &>/dev/null
  then
     /usr/bin/mysqladmin --defaults-extra-file=/root/.my.cnf flush-logs
  fi
  endscript
}

/var/log/mysql/query.log
{
    create 644 mysql mysql
    notifempty
  daily
    rotate 14  # 14世代分古いログを残す
    missingok
    nocompress
    dateext
  postrotate
  # just if mysqld is really running
  if test -x /usr/bin/mysqladmin && \
     /usr/bin/mysqladmin ping &>/dev/null
  then
     /usr/bin/mysqladmin --defaults-extra-file=/root/.my.cnf flush-logs
  fi
  endscript
}

ここではerror.logとslow_query.logは30日分保存し、query.logのみ14日とするよう設定しました。
保持日数は運用状況にあわせて変更してください。
すべて同一の保持日数にするなら、query.logの設定を分けて記述する必要はありません。

また、MySQLログファイルの注意点として、ローテーションした後にflush-logsを実行する必要があります。
flush-logsを実行しないと、ローテーション実行後もMySQLが古いファイルにログを出力してしまいます。

logrotateではpostrotateオプションを使用することで、ログファイルをローテーションした後に任意のスクリプトを実行することができます。
ここでは13-17行目でflush-logsを実行させていますが、この際に接続情報を/root/.my.cnfファイルから取得させています。
このため、/root/.my.cnfファイルに接続情報を記述して奥必要があります。

[mysqladmin]
password = [mysqladmin実行ユーザのパスワード]
user= [mysqladmin実行ユーザ名]

以上でMySQLログファイル用のlogrotate設定ファイル作成は完了です。
cron(またはcronから起動されたanacron)により毎日自動で実行されますが、logrotateをデバッグモードで実行することで動作確認を行うことができます。

logrotate -dv /etc/logrotate.d/mysql-logs

上記のコマンドを実行するとデバッグの結果が出力されますので、エラー等が出力されないかチェックしてください。

終わりに

以上、logrotateによってMySQLログファイルのローテーションを行う方法を解説しました。
MySQLログに限らず、Linuxでファイルの世代管理は基本的にlogrotateに任せてしまって問題ないと思います。
もちろん自分で開発するソフトウェアのログ世代管理にも利用できますので、ぜひ使いこなしてください。