ITエンジニアによるITエンジニアのためのブログ

logrotateでログローテーションを行なう方法

本記事では、Linuxの標準的なログ管理ツールである logrotateを使用したログローテーションをUbuntuサーバーで設定する方法を紹介します。

例として、RubyのデプロイツールであるCapistranoでデプロイされたRuby on Railsのアプリケーションログをローテーションさせる方法を記載します。 但し、logrorateはLinuxのあらゆるログのローテーションに使用できますので、Railsを使っていなくても参考になる部分はあるはずです。

目次

  1. logrotate設定ファイルの作成
  2. 設定内容の記述
  3. 設定のテスト
  4. 設定の強制実行(任意)
  5. ローテーション確認
  6. 補足:巨大なログファイルのコピーによるディスクフルの懸念
    • 方法1:【推奨】初回のみ手動でローテーションし、ログを保持する
    • 方法2:既存のログが不要な場合、ログファイルを空にする
  7. まとめ

1. logrotate設定ファイルの作成

logrotate の設定は、/etc/logrotate.d/ ディレクトリにアプリケーションごとの設定ファイルを作成することで行います。

まず、SSHでサーバーに接続し、以下のコマンドでRailsアプリケーション用の設定ファイルを新規作成します。ファイル名は任意ですが、アプリケーション名など分かりやすいものにしましょう。(例: my_app_name

# Bash
sudo vim /etc/logrotate.d/my_app_name

2. 設定内容の記述

作成したファイルに、ログローテーションのルールを記述します。Capistranoでデプロイした場合、ログファイルは /var/www/APP_NAME/shared/log/ ディレクトリにあります。(APP_NAME はご自身のアプリケーション名に置き換えてください)

以下は、一般的な設定例です。

/var/www/APP_NAME/shared/log/*.log {
  daily
  missingok
  rotate 7
  compress
  delaycompress
  notifempty
  copytruncate
}
オプション説明
dailyログを毎日ローテーションします。(weeklymonthly も指定可能)
missingokログファイルが存在しなくてもエラーにしません。
rotate 77世代分のログファイルを保持します。7日経過したものは削除されます。(他の数字も指定可能)
compressローテーションされたログファイルを圧縮します。(gzip)
delaycompress1世代前のログファイルから圧縮を開始します。これにより、直近のログをすぐに確認できます。
notifemptyログファイルが空の場合はローテーションを行いません。
copytruncate【重要】 現在のログファイルをコピーした後、元のログファイルを空にします。これにより、Railsアプリケーションを再起動することなくログの切り替えが可能です。アプリケーションは同じログファイルを掴み続けたまま、中身だけが空になります。

通常は、上記の設定を行っておけば、システムのcronによって毎日自動的に logrotate が実行され、ログが肥大化するのを防ぐことができます。cron設定は/etc/cron.daily/logrotateなどに記載されています。

3. 設定のテスト

設定ファイルが正しく記述できているか、以下のコマンドでテストできます。このコマンドは実際にはローテーションを実行せず、どのような処理が行われるかを表示するだけです(Dry Run)。

# Bash
sudo logrotate -d /etc/logrotate.d/my_app_name

4. 設定の強制実行(任意)

設定が正しいことを確認した後、すぐにローテーションを試したい場合は、以下のコマンドで強制的に実行できます。

sudo logrotate -f /etc/logrotate.d/my_app_name

5. ローテーション確認

設定から1日経ったら、再びサーバーにログインしてログアーカイブファイルが作成されているか、元のログファイルが一旦空になった後に新しい書き込みがされているかを確認します。

ls -l /var/www/APP_NAME/shared/log/

特に問題がなければ、これでログローテーションの設定は完了です。

補足:巨大なログファイルのコピーによるディスクフルの懸念

すでにログファイルが巨大化している場合、logrotatecopytruncate が実行されると、コピー処理中に一時的にディスク容量を2倍近く消費し、ディスクフルになる危険性があります。

この問題を安全に解決するための方法を、状況に応じて2つ紹介します。

方法1:【推奨】初回のみ手動でローテーションし、ログを保持する

既存のログを失うことなく、安全に logrotate の運用を開始するための最も確実な方法です。手順は以下の通りです。

1. 既存のログファイルの名前を変更する (mv)

mv コマンドは、同じディスク内での移動であればディスク容量を消費せず、一瞬で完了します。

# アプリケーションのログディレクトリに移動
cd /var/www/APP_NAME/shared/log/

# 既存のログファイルの名前を変更して退避させる
sudo mv production.log production.log.old

2. アプリケーションを再起動する

ログファイルの名前を変更しただけでは、アプリケーションは古いファイル(名前が変わった production.log.old)を掴んだままです。新しい production.log を作成させ、そちらに書き込みを始めさせるために、アプリケーションの再起動が必要です。 CapistranoでデプロイしているPumaやUnicornの再起動コマンドを実行してください。

# 例: Capistranoのpuma再起動タスク
cap production pumactl:restart

再起動後、アプリケーションは新しい空の production.log を自動で作成し、ログの書き込みを開始します。

3. 退避させた古いログファイルを処理する

名前を変更した production.log.old は、必要に応じて圧縮、バックアップ、または削除します。

# 圧縮して容量を節約する
sudo gzip production.log.old

# 内容を確認後、不要であれば削除する
# sudo rm production.log.old.gz

gzip圧縮後は1/10程の容量になりますが、gzip 実行中は元のファイルは残っているので、一時的に元のファイル容量に加えて圧縮ファイル分の容量を消費することになります。gzipした方が別のサーバーにバックアップする際の転送スピードは早くなりますが、本当にディスク容量がギリギリの時は圧縮せずにそのままバックアップして元のファイルは削除します。

4. logrotate の設定を行う

この状態で、本記事で説明した /etc/logrotate.d/ への設定ファイル作成を行います。 新しく作られた production.log はサイズが小さいため、次回以降 logrotatecopytruncate を実行してもディスク容量を圧迫する心配はありません。

方法2:既存のログが不要な場合、ログファイルを空にする

開発環境や、過去のログを保持する必要がない場合は、この方法が最も手軽です。アプリケーションを再起動する必要もありません。手順は以下の通りです。

ログファイルを空にする

truncate コマンドで、ファイルの中身だけを0バイトにします。

sudo truncate -s 0 /var/www/APP_NAME/shared/log/production.log

このコマンドは、ファイルを削除せずに中身だけを消去します。アプリケーションはファイルを掴んだままなので、処理後も問題なくログを書き込み続けます。

logrotate の設定を行う ログファイルが0バイトになった状態で、前回ご説明した logrotate の設定を行えば、安全に自動ローテーションを開始できます。

状況推奨する方法特徴
過去のログを保持したい方法1:手動で初回ローテーション最も安全で確実。ログの欠損なし。ただしアプリの再起動が必要。
過去のログは不要方法2:ログファイルを空にする最も簡単で迅速。アプリの再起動が不要。

ご自身のアプリケーションの要件に合わせて、適切な方法を選択してください。基本的には、本番環境であれば 方法1 を強くお勧めします。

7.まとめ

ログは肥大化するとサーバー容量を逼迫します。自身のログ保存ポリシーに従って、logrorateで適切なログローテーションを行いましょう。