HEARTBEATS

実践で学ぶLogrotate の安全な使い方まとめ!

   

こんにちは、運用チームのKimです。

システム運用において、ログファイルの肥大化はディスク容量を圧迫する一般的な課題です。この課題に対して、多くの企業でLinuxの標準ツールLogrotate を使ったログ管理が行われています。

しかし、Logrotateの運用においては、設定項目の理解不足による意図しない挙動やログの欠損などが起こることがあり、その取り扱いには細心の注意が必要です。 そこで今回は、Logrotateを安全に使いこなすための実践的な方法と注意点をまとめました。特に、運用環境での事故を防ぐための検証方法に焦点を当てて解説します。

Logrotate とは?

Logrotateは、LinuxやUnix系OSで広く使われているログ管理ツールです。 増え続けるログファイルを自動的にローテートし(例:現在のログファイルを別名で保存し、新しい空のログファイルを生成すること)、圧縮、削除することで、ディスク容量の肥大化を防ぎます。

これにより、システムの安定稼働を維持し、ログの管理を効率化することができます。

Logrotate の導入手順と安全な検証

ではさっそく手を動かしてみましょう!

ここではLinuxユーザー向けに、実際に手を動かしながらLogrotateの仕組みを理解していきます。例として、Apache HTTP Server(Apache)のログをLogrotateでローテートしてみましょう。

まずはLinux環境を準備してください。Linuxの主要なディストリビューション(CentOS,RHEL, Ubuntu, AlmaLinuxなど)には、Logrotateが標準でインストールされているため、ほとんどの場合、追加の導入作業は不要です。

次に検証のためApacheの環境を利用します。Apacheの導入がまだの方はdnfコマンドまたはaptコマンド等でインストールをお願いします。

※本記事ではAlmaLinux9を利用してます。

AlmaLinuxの場合
# dnf install httpd -y

Logrotateの設定ファイルは/etc/logrotate.confという親設定ファイルと、/etc/logrotate.d/というディレクトリ内の個別設定ファイルに分かれています。この形式を模倣し、Apacheのログローテートを想定したカスタム設定をしていきます。

Step1: Logrotateの親設定ファイルの理解

まず、あらかじめ用意されているLogrotateの設定ファイルであるlogrotate.confの内容を確認してみましょう。

$ cat /etc/logrotate.conf

私の環境では出力された内容は下記のとおりでした

# see "man logrotate" for details

# global options do not affect preceding include directives

# rotate log files weekly
weekly

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# use date as a suffix of the rotated file
dateext

# uncomment this if you want your log files compressed
#compress

# packages drop log rotation information into this directory
include /etc/logrotate.d

# system-specific logs may also be configured here.

ディレクティブの説明

この親設定ファイルは、Logrotate全体の基本的な設定を定義しており、個別の設定ファイルに共通のデフォルト設定を適用します。

  • weekly: ログファイルを毎週ローテート
  • rotate 4: 4世代分のログファイルを保持し、古いものから自動的に削除
  • create:ローテート後に新しい空のログファイルを作成
  • dateext:ローテートされたログに、日付(例: access_log-20250917)を付けてリネーム。
  • compress:ローテートしたログを gzip で圧縮。
  • include /etc/logrotate.d: この行がポイント。このディレクティブは、指定されたディレクトリ(この場合はlogrotate.d)内のすべての設定ファイルを読み込み、処理するようLogrotateに指示。これにより、複数のアプリケーションのログ設定を個別のファイルで管理が可能。

※注意

これからApache用の個別設定ファイルを設定していきます。 親設定ファイルlogrotate.confで定義しているディレクティブの設定とApache用の個別設定に記載したディレクティブが共通する場合、Apache用の個別設定のディレクティブ設定が優先されます。また、個別設定にないディレクティブが親設定ファイルに定義されている場合は、全体の設定として反映されます。

  • 個別設定が優先: 親設定ファイル (/etc/logrotate.conf) と個別設定ファイル (/etc/logrotate.d/httpdなど) で同じディレクティブが重複して定義されている場合、個別設定ファイルの設定が優先
  • 親設定から引き継ぎ: 個別設定ファイルで定義されていないディレクティブは、親設定ファイルの基本的な設定が引き継がれる

個別設定が親設定の影響を受けないようにする方法

個別設定が親設定の影響を完全に受けないようにするには、必要な設定項目をすべて個別設定ファイル内に記述する必要があります。これにより、親設定ファイルのグローバルな設定を個別設定で上書きできます。

たとえば、親設定ファイルに createディレクティブがあり、これを個別設定で適用したくない場合は、個別設定ファイルに明示的に nocreateディレクティブと記述します。

Step2: 検証用ログファイルの準備

今回は、アクセスログ(access_log)とエラーログ(error_log)を以下の条件でローテートします。

  • ローテートされたファイルは日付でリネームする
  • 5世代分のログファイルを保持する
  • 当日分を除きローテートされたログをgzipで圧縮する

まず、Apacheのログを模倣したファイルを用意します。通常、Apacheのログは/var/log/httpd/(CentOS/RHEL系/AlmaLinux)や/var/log/apache2/(Debian/Ubuntu系)にあります。今回はCentOS/RHEL/AlmaLinux系を想定し、/var/log/httpd/ディレクトリにログファイルを作成します。

# Apacheのログディレクトリに過去1週間分のログファイルを擬似的に作成 
$ sudo tee -a /var/log/httpd/access_log <<< "Initial access log entry" > /dev/null && sudo tee -a /var/log/httpd/error_log <<< "Initial error log entry" > /dev/null && for i in {1..7}; do date=$(date --date="${i} days ago" +%Y%m%d); echo "Dummy access log entry from ${date}" | sudo tee -a "/var/log/httpd/access_log-${date}" > /dev/null; echo "Dummy error log entry from ${date}" | sudo tee -a "/var/log/httpd/error_log-${date}" > /dev/null; done

# ファイルが正しく作成されたか確認 
$ sudo ls -l /var/log/httpd/
total 64
-rw-r--r--. 1 root root  50 Nov 13 11:39 access_log
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251106
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251107
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251108
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251109
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251110
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251111
-rw-r--r--. 1 root root  74 Nov 13 11:39 access_log-20251112
-rw-r--r--. 1 root root 732 Nov 13 11:39 error_log
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251106
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251107
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251108
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251109
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251110
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251111
-rw-r--r--. 1 root root  72 Nov 13 11:39 error_log-20251112

lsコマンドを実行すると、アクセスログ(access_log)とエラーログ(error_log)に加え、過去7日分のファイルが作成されているのが確認できます。

Step3: Apacheログファイル操作用のローテート個別設定ファイル編集

次に、親設定ファイルとApacheのローテート個別設定ファイルを編集します。通常、/etc/logrotate.d/ディレクトリ内に個別の設定ファイルを編集します。

Logrotateの設定を1つの設定ファイルに全て記載することもできますが(例えば親設定ファイルに全て記載するとか)、複数の設定内容を/etc/logrotate.d/ディレクトリ内に複数の設定ファイルを作成し、目的別に分割して管理することもできます。 設定ファイルを分割して管理することで、設定内容の整理がしやすくなり、特定のログ設定だけを変更・管理する際も容易になります。

Apacheのローテート個別設定ファイルを編集(/etc/logrotate.d/httpd)

※Apacheインストール時に自動で作成されているはずです。

$ sudo vim /etc/logrotate.d/httpd

以下の内容を開いたvimエディターの中に記述します。

/var/log/httpd/access_log /var/log/httpd/error_log {
    # 親設定で有効化されている create を明示的に無効化
    nocreate
    # 親設定のweeklyをdailyに上書き
    daily
    rotate 5
    # 親設定を上書き
    compress
    # その他の必須オプション
    delaycompress
    missingok
    notifempty
    dateext
    postrotate
        # HUPシグナルでApacheに新しいログファイルを開かせ、同時に新規ファイル作成も任せる
        /bin/kill -HUP $(cat /var/run/httpd/httpd.pid)
    endscript
}

ディレクティブの説明

この設定は、access_logerror_log の両方をまとめて管理するためのものです。 これにより、同じローテートルールを2つのファイルに簡単に適用できます。

補足: 本記事で紹介しているのは主要なディレクティブのみです。Logrotateの設定ファイルには他にも多数のディレクティブが存在します。他の設定項目や詳細な仕様を確認したい場合は、Linuxのターミナルで man logrotate コマンドを実行して、マニュアル(manページ)を参照してください。

  • /var/log/httpd/access_log, /var/log/httpd/error_log: ローテートの対象となるファイルへのパス。
  • nocreate: ローテート後に新しい空のログファイルを作成しないようにする。
    • 今回はpostrotateディレクティブで定義したスクリプト処理より、Apache設定ファイルの再読み込みが発生し、httpd.confの設定に基づきログファイルを作成するためcreateディレクティブは不要
  • daily: ログファイルを毎日ローテートする。
  • rotate 5:5世代分のログファイルを保持し、古いものから自動的に削除する。
  • compress: ローテートしたログを gzip で圧縮する。
  • delaycompress: compressの処理を次回のローテート時まで遅らせる。これにより、直近にリネームされたログがすぐに圧縮されるのを防ぎ、アプリケーションの書き込みを妨げないようにする。
  • missingok: 対象のログファイルが存在しなくてもエラーにしない。
  • notifempty: ログファイルが空の場合はローテートしない。
  • dateext: ローテートされたログに、日付(例: access_log-20250917)を付けてリネームする。
  • postrotate: ログローテートが完了した後に実行されるスクリプトを定義する。
    • Apacheでは/bin/kill -HUP $(cat pidファイル)のスクリプトを定義しApacheがログファイルを再読み込みできるように設定する例が多い。
    • HUPシグナルとはLinuxやUNIX系OSで使用されるソフトウェアシグナルの一つで、「SIGHUP (Signal Hang Up)」とも表記される。
    • /bin/kill -HUP $(cat pidファイル)が必要になる理由はApacheはHUPシグナルを受け取ると、Apacheのプロセスを再起動せずに設定ファイルを再読み込みし、同時に現在開いているログファイルへのハンドル(ファイル記述子)を閉じ、新しいファイルを開き直す動作をする。これにより新しく作成された空の access_log には何も書き込まれないという状態を回避する。
    • endscript: postrotateなどのスクリプトを定義するブロックの終了を示すディレクティブ。
    • 補足:上記定義しているkillコマンドについて
      • AlmaLinux9 のApacheのローテート個別設定ファイルのデフォルト設定では、killコマンドの代わりにsystemctl httpd reloadを利用。停止を挟まない条件は同じなので、どちらを利用しても問題なし。
      • 実装例:/bin/systemctl reload httpd > /dev/null 2>/dev/null || true
    • postrotateディレクティブをなぜ利用するかについては後半の方で詳しく解説。

Step4: debugモードで安全に設定を検証

設定ファイルを更新したら、--debugオプションでdebugモードと呼ばれる機能(実行した時の一連の挙動を確認する機能)を実施し、シミュレーションします。

これから利用するdebugモードでは、Logrotateコマンドを実際に実行した際に出力されるメッセージを確認できます。実際のファイル操作は行われないため、設定内容の適切さを安全に検証することが可能です。

Logrotateは通常、親設定ファイル(/etc/logrotate.conf)を起点として、そこから全ての個別設定ファイル(/etc/logrotate.d/*)を読み込んで実行されます。 今回は実際の運用環境と同じような条件で正確に検証するためにも、シミュレーションは親設定ファイルを指定して実行します。

※親設定ファイルを指定して実行する理由についてはStep4の最後にまとめています

以下のコマンドを実行して、作成した設定が意図通りに動くか確認してみましょう。

# 親設定ファイルを指定してdebugモードを実行
$ sudo logrotate --debug /etc/logrotate.conf

出力の読み解き方:

コマンドを実行すると、以下のようなメッセージが表示されます。 出力を略していますが、下記「does not exist -- skipping」を見ると検証の結果が上手く行ってなさそうです。

親設定ファイル経由で全ての設定が読み込まれますが、httpd の検証結果に注目します。

(全出力のうち、一部を省略しています)

(略)
reading config file /etc/logrotate.conf
including /etc/logrotate.d
reading config file btmp
reading config file chrony
reading config file dnf
reading config file httpd
reading config file psacct
reading config file sssd
reading config file wtmp
Reading state from file: /var/lib/logrotate/logrotate.status
Allocating hash table for state file, size 64 entries
(略)
Handling 7 logs
(httpの出力のみ抜粋)
rotating pattern: /var/log/httpd/hoge_log /var/log/httpd/error_log after 1 days (5 rotations) empty log files are not rotated, old logs are removed 
considering log /var/log/httpd/hoge_log 
    log /var/log/httpd/hoge_log does not exist -- skipping Creating new state
considering log /var/log/httpd/error_log
    Now: 2025-11-13 11:42
    Last rotated at 2025-11-13 11:00
    log does not need rotating (log has already been rotated)
(略)

実行結果の読み解き方

  • reading config file httpd:
    • 親設定ファイル(/etc/logrotate.conf)が、作成したApacheの設定ファイルを正しく読み込んでいることを示す。
  • rotating pattern: /var/log/httpd/hoge_log /var/log/httpd/error_log after 1 days (5 rotations):
    • 設定ファイルで指定したローテート対象のローテーション頻度(daily→after 1 days)および保存世代数(rotate 5)が正しく認識されたことを示す。
  • empty log files are not rotated, old logs are removed:
    • notifempty ディレクティブが有効になっているため、ファイルが空の場合はローテートしないこと、および古いログファイルは削除されること(rotateディレクティブの働き)が確認された。
  • log /var/log/httpd/hoge_log does not exist -- skipping:
    • 赤字で記載した上記出力が今回の問題となった部分について
    • access_logではなくhoge_logというファイルが存在しないため、このファイルのローテートをスキップしたことを意味する。今回は意図的にパス名をミスしてみた。
  • log does not need rotating (log has already been rotated):
    • ローテートの条件を満たしていないため、ローテートが必要ではないと判断。
    • 理由は、無の状態からログファイルを手動で作成したため、最後にローテートを実行してから日付が経過したというローテートステータスが存在しない。よって、ローテートを実行する条件を満たしていないことを意味する。
    • 参照しているローテートステータスファイルはlogrotate.status。 今回の出力では意図した内容なので問題はなし。
    • ローテートの条件を満たしてた場合はlog needs rotatingと出力される。

does not exist -- skipping」の出力を確認致しました。 この出力は、設定したパスにファイルが存在しないためスキップしたことを示しています。 今回の場合、設定したローテート対象のパスが間違っていたため、発生したエラーであることがdebugモードのシミュレーション結果から判明しました

パスを修正し、再度検証コマンドを実行してみます。

$ sudo vim /etc/logrotate.d/httpd
$ sudo logrotate --debug /etc/logrotate.conf

実行結果の読み解き方

コマンドを実行すると、以下のようなメッセージが表示されました。 成功していそうですね。

warning: logrotate in debug mode does nothing except printing debug messages! Consider using verbose mode (-v) instead if this is not what you want.
(略)
rotating pattern: /var/log/httpd/access_log /var/log/httpd/error_log after 1 days (5 rotations) 
empty log files are not rotated, old logs are removed considering log /var/log/httpd/access_log 
    Now: 2025-11-13 11:57
    Last rotated at 2025-11-13 11:00
    log does not need rotating (log has already been rotated)
considering log /var/log/httpd/error_log
    Now: 2025-11-13 11:57
    Last rotated at 2025-11-13 11:00
    log does not need rotating (log has already been rotated)
not running postrotate script, since no logs were rotated
(略)

先程のdebugの実行では出力結果を省略しましたが、実行するとwarning(警告)メッセージが表示されます。一見するとwarning(警告)が出ているため不安に感じるかもしれませんが、最初のwarningメッセージは、「--debugモードは、デバッグメッセージの表示以外には何も実行しない」という、このオプションの仕様を説明しているものです。

成功した出力内容について確認してみます。

  • considering log /var/log/httpd/access_log:
    • 今回は does not exist のようなエラーは表示されていない。
    • ローテート対象のファイル名を正しく認識。
  • log does not need rotating (log has already been rotated):
    • ローテートの条件を満たしていないため、ローテートが必要ではないと判断。
    • 理由は、無の状態からログファイルを手動で作成したため、最後にローテートを実行してから日付が経過したというローテートステータスが存在しない。よってローテートを実行する条件を満たさないことを意味する。
    • 参照しているローテートステータスファイルはlogrotate.status。
    • 今回の出力では意図した内容なので問題はなし。
    • 満たしていた場合はlog needs rotatingと出力される。
  • not running postrotate script, since no logs were rotated:
    • ローテート条件を満たしていないため実行されなかった。
    • 成功していた場合running postrotate scriptと出力。

--debugモードは、このように実行前に問題を特定できるため、本番環境で「思ったように動かない!」といったトラブルを未然に防ぐことができる非常に重要なStepでした。 このStepで問題がなければ、次の段階に進みましょう。

注意

does not exist -- skipping」はよく見かけるエラーです。 簡単な例の場合は以下の状況が考えられます。

  • ファイル名のスペルミス
    • 設定ファイルに記載したファイル名が間違っていると、 Logrotateはファイルを見つけられずにエラーを返す。
    • 原因: access_loghoge_logのように誤ってタイプした、など。
    • 対策: 設定ファイル内のファイルパスをもう一度確認し、正しいパスに修正する。
  • ファイルの削除
    • なんらかの理由で、サービスがログを出力する前にログファイルが削除されてしまうと、Logrotateがファイルを見つけられなくなる。
    • 原因: 手動でログファイルを削除してしまった、など。
    • 対策: Logrotateのdebugモード前に処理前にファイルが存在しているか確認する。
  • ログの出力先が異なる
    • サービスの設定(例:Apacheの設定ファイルhttpd)で指定されているログファイルの出力先が、Logrotateの設定と異なっている場合もこのエラーが発生する。
    • 原因: サービスは/var/log/httpd/access_logにログを出力しているのに、Logrotateの設定は/etc/httpd/logs/access_logになっている、など。
    • 対策: サービスの設定とLogrotateの設定の両方を確認し、ログの出力先を一致させる。

※親設定ファイルを指定して実行する理由について

実際の運用環境では、ローテート設定を編集した後、cronなどによってローテートが自動的に実行されるのを待ち、結果が反映されるのを待つことが多いです。

すぐに実行する場合でも、logrotate.dディレクトリ内の個別ファイルで実行するのではなく、logrotate.confという親設定ファイルを起点に実行するのが一般的です。個別ファイルでローテートを実行すると、親ファイルで定義された共通の設定が適用されず、実際の運用時の挙動と異なる可能性があります。そのため、本番環境で試す場合は親設定ファイルを指定して実行するか、もしくはローテートのcronの自動実行を待つのが最も安全です。

良くない例を簡単に紹介します。

良くない設定例: ローテートの親設定にApacheのローテート個別設定の代わりにdailyディレクティブが設定されているとします。

# rotate log files daily
daily
# packages drop log rotation information into this directory
include /etc/logrotate.d

また、下記Apacheのローテート個別設定ファイルにてdailyディレクティブが設定されていないとします。

/var/log/httpd/access_log /var/log/httpd/error_log {
    nocreate
    rotate 5
    compress
    delaycompress
    missingok
    notifempty
    dateext
    postrotate
        /bin/kill -HUP $(cat /var/run/httpd/httpd.pid)
    endscript
}

※上記設定状態でApacheの個別設定ファイルのみを指定してlogrotateを実行。

# Apacheの個別設定ファイルのみを指定してコマンドを実行
$ logrotate --debug /etc/logrotate.d/httpd

本来であれば上記親設定のローテートが実行されることによりdailyディレクティブの設定がApacheのローテート個別設定ファイルにも読み込まれるはずです。

しかし、Apacheのローテート個別設定ファイルを単体で実行してしまった場合、dailyディレクティブが適応されずに、意図しないローテート結果となってしまいます。この挙動は、以下の--debugモードの実行結果からも確認できます。

赤字に注目に注目

[root@ip-172-31-46-155 ~]# logrotate --debug /etc/logrotate.d/httpd
...(略)
Handling 1 logs
rotating pattern: /var/log/httpd/access_log /var/log/httpd/error_log  1048576 bytes (5 rotations)
...(略)
considering log /var/log/httpd/error_log
...(略)
log does not need rotating (log size is below the 'size' threshold)

dailyディレクティブがない状態で個別ファイルを実行すると、上記rotating pattern:に(1048576 bytes)ファイルサイズ1MBの判定が適用され、サイズ指定でローテートの判定が行われてしまいました。

以上のことから、このような予期しない挙動を防ぎ、安全かつ予測可能な結果を得るためにも、ローテートは必ず親設定ファイル(/etc/logrotate.conf)を起点に実行するか、ローテートが自動実行されるまで待つ必要があります。

Step5: 実際にローテートを実行してみる

--debugモードでのシミュレーション結果に問題がないことを確認したら、いよいよ実際にローテートを実行します。通常、Logrotateはcronやsystemd のタイマー機能によって自動的に実行されますが、今すぐローテートの挙動を確認したい場合は、手動でコマンドを実行する必要があります。

--forceオプションについて補足

--forceオプションは、dailyやweeklyといった設定ファイルに記述されたローテートのタイミングを無視して、強制的にローテートを実行するためのものです。

メリット:

  • 即時検証: 設定変更が正しく機能するかを、日次や週次の自動実行を待たずにすぐに確認できる。
  • 緊急対応: ディスク容量がひっ迫しているなど、緊急でログファイルをローテートする必要がある場合に役立つ。

デメリット:

  • 運用から乖離: 実際の運用環境では--forceオプションはあまり使わない。本来のローテートタイミングを無視するため、本番環境でのテストは基本的に使わないようにする。
  • 意図しない挙動: 複数のログファイルがローテート対象になっている場合、--forceによって全てのログファイルが一度にローテートされてしまい、意図しないタイミングで別のログファイルのローテートが行われる可能性がある。

前置きが長くなりましたが、ローテートの実行結果を確認しましょう。

# 親設定ファイルを指定して実行
$ sudo logrotate --force /etc/logrotate.conf
# 実行後のファイルを確認
$ sudo ls -l /var/log/httpd/
total 44
-rw-r--r--. 1 root root    0 Nov 13 12:01 access_log
-rw-r--r--. 1 root root   60 Nov 13 11:39 access_log-20251109.gz
-rw-r--r--. 1 root root   60 Nov 13 11:39 access_log-20251110.gz
-rw-r--r--. 1 root root   59 Nov 13 11:39 access_log-20251111.gz
-rw-r--r--. 1 root root   60 Nov 13 11:39 access_log-20251112.gz
-rw-r--r--. 1 root root   50 Nov 13 11:39 access_log-20251113
-rw-r--r--. 1 root root 1206 Nov 13 12:01 error_log
-rw-r--r--. 1 root root   59 Nov 13 11:39 error_log-20251109.gz
-rw-r--r--. 1 root root   59 Nov 13 11:39 error_log-20251110.gz
-rw-r--r--. 1 root root   58 Nov 13 11:39 error_log-20251111.gz
-rw-r--r--. 1 root root   59 Nov 13 11:39 error_log-20251112.gz
-rw-r--r--. 1 root root  856 Nov 13 12:01 error_log-20251113

実行後、access_logerror_logがそれぞれaccess_log-20251113error_log-20251113にリネームされ、 過去のファイルが圧縮されたり削除されたりしているのが確認できます。

一連の手順を通じて、複数のログファイルを一元管理する方法があるということが理解できたのではないでしょうか?

現場で「ハマらない」ための重要ポイント

ログローテートはどのタイミングで実行される?

Logrotate は、cron や systemd のタイマー機能を使って定期的に実行されるように設定されています。

多くの Linux ディストリビューションでは、/etc/cron.daily/logrotate のようなスクリプトが用意されており、これが定期的に Logrotate コマンドを実行します。この仕組みがあるため、手動でコマンドを実行しなくても、設定ファイルに記述されたルール(例:dailyディレクティブやweeklyディレクティブ)に基づいて自動的にログローテートが行われるのです。

「設定ファイルを作成したのに動かない」という場合は、まずこの自動実行の仕組みが正しく動作しているか確認することも念頭に入れると良いです。

ログが追記されない!?postrotate ディレクティブの重要性

postrotateディレクティブ は、ログが途切れることなく記録されるようにするための、Logrotate で重要な設定の一つです。

なぜ postrotateディレクティブが必要か?

Apacheやphp-fpmのような多くのミドルウェアは、一度ログファイルを開くと、そのファイルハンドルを保持し続けます。Logrotateがファイルをリネームしたり削除したりしても、ミドルウェアは古いファイルハンドルを参照し続けるため、ログが新しいファイルに追記されなくなる問題が発生します。

この問題を解決するのが、postrotate ディレクティブです。

postrotateディレクティブが問題を解決する!

postrotateディレクティブは、ログローテート完了後に実行されるスクリプトやコマンドを定義するディレクティブです。

postrotateディレクティブに、ミドルウェアが新しいログファイルに正しくログを追記できるよう、ログファイルを再読み込みさせるためのスクリプト、コマンドなどを記述します。今回の検証に利用したApacheであればHUPシグナルを利用できるため、ローテート実行後に、Apacheのプロセスを再起動せずに設定ファイルを再読み込みし、同時に現在開いているログファイルへのハンドル(ファイル記述子)を閉じ、新しいファイルを開き直す動作を実現できます。これにより、クライアントとのサービスを維持したまま、ログが途切れることなく新しいファイルに正しく記録されます。

prerotate ディレクティブの設定について

prerotateディレクティブは、postrotateディレクティブとは逆で、ログファイルがローテートされる直前に実行されるスクリプトを定義するディレクティブです。主な利用方法としては、ローテート処理中のログ欠損やファイル破損を防ぐ際に利用します。

主な役割

ログファイルに書き込みを行っているサービス、プロセスが存在する場合、そのサービス、プロセスを停止させずにローテート処理を実行すると、一部ログデータの欠損やファイル破損を招く可能性があるため、prerotateディレクティブが使用されるケースがあります。

  • 利用方法: ログを出力しているサービスを一時的に停止し、postrotateディレクティブと併用しサービスを再開する運用が行われるケースがある。
  • 注意点: リアルタイム性が求められるWebサービスにおいて、サービスの一時停止はユーザーへの影響が大きいため利用は推奨されない。この運用は、バッチ処理やメンテナンス期間がある環境に推奨。
  • 推奨される環境
    • 定期的に実行停止されるバッチ処理やcronジョブ
    • 開発・ステージング環境
    • 重要度の低いバックグラウンドサービス
    • HUPシグナルを利用できるApacheやNginxとは違い、HUPシグナルを利用できないサービス

記述形式方法はpostrotateディレクティブと似ています。 endscriptディレクティブまでの間に実行したいスクリプトを下記のとおり記述します。

prerotate
    # ここに実行したいスクリプトやコマンドを記述
    /usr/bin/systemctl stop some-service.service
endscript

Logrotate対象にならないログとは?

Logrotateは、ログファイルへの追記のみを行うプレーンテキスト形式のログに最適です。以下のログはLogrotateの適用対象外、または利用が推奨されません。

1. ログの「形式」:バイナリである(プレーンテキストではない)

これは技術的にLogrotateが処理できないケースです。

  • 対象: ログファイルの内容がテキストエディタで開いても読めない、または構造化されたバイナリデータ
  • 理由: Logrotateはファイルの読み書きを直接行わず、ファイル名のリネームやシグナル送信に依存します。しかし、バイナリ形式のログは、その構造上、システムやアプリケーション独自のツールでなければ安全に管理(パース、分割)ができないため
  • : systemd-journaldのようなジャーナル形式のログ(バイナリログ)

2. ログの「管理主体」:アプリケーション自身がファイル操作を行う

これはLogrotateの操作と競合するため、適用が推奨されないケースです。

  • 対象: アプリケーション(ミドルウェア)自身が、容量や時間に応じてログファイルをリネーム、圧縮、削除する機能(つまり、独自のローテート機能)を持っている場合。
  • 理由: Logrotateがログファイル名をリネームした直後に、アプリケーションもログファイルをリネームしようとするなど、操作が競合し、ログの欠損やファイルハンドルのエラーを引き起こすリスクがあるため
  • : Javaロギングフレームワーク (Logback/Log4j)など、フレームワーク自身がローテート機能を担う物

おわりに:Logrotateを使いこなすための3つのポイント

Logrotate を安全かつ効果的に運用するには、以下の3つのポイントを押さえることが重要です。

  • 検証の徹底: 本番環境に適用する前に、必ず--debug(debugモード)で設定をシミュレーションし、問題がないことを確認する。
  • 仕組みの理解: Logrotateの自動実行の仕組みと、postrotateの役割を把握することが不可欠。これにより、ログの欠損を防いだり、ログのアプリケーションが正常に動作し続けることを確認する。
  • ログの特性把握: すべてのログがLogrotateで管理できるわけではない。対象のログが、Logrotateが処理できないバイナリ形式であったり、アプリケーションが独自のログ管理機能を持っていないかを確認する。

本記事が、日々のログ管理の一助となれば幸いです。最後までお読みいただき、ありがとうございました!

参照情報源

logrotateのmanページ(公式ドキュメント)※manコマンドより確認

Apache HTTP Server(Apache)公式ドキュメント

株式会社ハートビーツの技術情報やイベント情報などをお届けする公式ブログです。



ハートビーツをフォロー

  • Twitter:HEARTBEATS
  • Facebook:HEARTBEATS
  • HATENA:HEARTBEATS
  • RSS:HEARTBEATS

殿堂入り記事