web-dev-qa-db-ja.com

logrotateとLog4jの「ローリング」ファイルアペンダーを組み合わせる方法は?

Log4jを使用し、独自のログを毎日ローテーションするJavaアプリケーションがあります。

  • 現在使用されているログファイルは/var/log/foo/foo.logです
  • 日が変わると/var/log/foo/foo.log.YYYY-MM-ddに移動します

設定を変更したくない...

ただし、次のことを行います。

  1. 名前が変更されたらファイルを圧縮します
  2. それらの特定の数のみを保持します

両方を実行するcronジョブを作成することは難しくありませんが、logrotate...のフレームワークに留まることをお勧めします。

次の/etc/logrotate.d/fooを作成します。

/var/log/foo/foo.log.* {
        daily
        rotate 2
        compress
        delaycompress
        missingok
        notifempty
}

しかしそれは何もしません:

reading config file /etc/logrotate.d/foo

Handling 1 logs

rotating pattern: /var/log/foo/foo.log.*  after 1 days (2 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/foo/foo.log.2017-06-28
  log does not need rotating
considering log /var/log/foo/foo.log.2017-06-29
  log does not need rotating
considering log /var/log/foo/foo.log.2017-06-30
  log does not need rotating
considering log /var/log/foo/foo.log.2017-07-01
  log does not need rotating
considering log /var/log/foo/foo.log.2017-07-02
  log does not need rotating
considering log /var/log/foo/foo.log.2017-07-03
  log does not need rotating
considering log /var/log/foo/foo.log.2017-07-04
  log does not need rotating

ファイルの総数が2を超えた場合、ファイルを圧縮して最も古いファイルを削除するにはどうすればよいですか?

3
Mikhail T.

アプリチームはログとファイル名の形式、およびlog4jを使用したローテーションスケジュールの制御を維持する必要があるため、この動作を実行する必要がありました。 man logrotateを読むと、すべての事前/事後/最終アクションスクリプトは、少なくとも1つのログがローテーションされた場合にのみ実行されることがわかります。したがって、size 999Gなどの到達不能なものを設定しても機能しません。

代わりに、次のようにcopyおよびextensionオプションを設定しました。

  1. 元のログファイルは変更されていません(log4jによって管理されています)
  2. Logrotateによってローテーションされたログには、フィルタリングできる別の拡張子があります
/var/log/<service>/<service>.log {
    copy  # don't touch the orig. log file, it's managed by log4j
    extension .log  # End rotated files in ".log" so we can find and delete them
    rotate 1
    hourly
    missingok

    prerotate
        find /var/log/<service>/ -iname "*service.log.*" ! -iname "*.gz" -exec gzip {} \; && \
        aws s3 sync /var/log/<service>/ s3://<bucket>/<environment>/<ec2_id>/<service>/ --exclude "*" --include "*<service>*.gz" && \
        find /var/log/<service>/ -iname "*<service>.log.*" -mtime +7 -delete
    endscript

    lastaction
        find /var/log/<service>/ -iname "*<service>.*.log" -delete
    endscript
}

はい、cronジョブを作成することができます。 logrotateを使用する理由は、すべてのログローテーション構成管理を単一のAnsibleロールに保持することです。将来的には、log4jローテーションを無効にし、代わりにlogrotateを使用するようにします。変化する。

1
Ryan Fisher

いくつかの外部コマンドなしでlogrotateを使用して必要なことを実行できるとは思えません。また、パターン/var/log/foo/foo.log.*は、ローテーションされる一連のファイルとしてではなく、ローテーションされる個別のログであるかのように各ファイルを扱います。

man logrotate

ワイルドカードは注意して使用してください。 *を指定すると、logrotateは、以前にローテーションされたファイルを含め、すべてのファイルをローテーションします。

とにかく、おそらくこのようなものですか? log4jがすでにローテーションを部分的に処理しているため、到達しないローテーション条件を設定するだけです。次に、残りをprerotateスクリプトに入れますか?

/var/log/foo/foo.log {
    size 100G # something big that will never be reached/rotated since log4j does this.
    missingok
    notifempty
    # delete the other logs over 7 days old
    prerotate
        find /var/log/foo/ -name 'foo.log.*' -mtime +7 -delete
        Nice gzip /var/log/foo/foo.log.*
    endscript
}
1
Zoredache

Log4jローリングファイルアペンダーとlogrotateには互換性がありません。 log4jローテーションは、logrotateに干渉します。

まず、アプリケーションのlog4j構成ファイルを見つけ、ローリングファイルアペンダーを単純なファイルアペンダーに置き換える必要があります。これにより、log4jによるファイルのローテーションが停止します。次に、logrotateを使用して、必要に応じてログファイルをローテーションできます。

アプリケーションのlog4j構成を変更できない場合は、独自のlog4j構成を作成し、アプリケーションが開始されたときにクラスパスでこれを指定できます。

-Dlog4j.configurationFile=path/to/log4j2.xml

参照: https://logging.Apache.org/log4j/2.0/faq.html#config_location

0
Oz.