lulu

【log】logrotateでnginxのログをrotateしてみる

logrotateとは

  • 「ファイル数が○○MBより大きくなったら」
  • 「毎日・毎月」

のように、ログファイルをサイズや時間軸で分割する機能

検証環境

  • Amazon Linux
  • nginx

Amazon Linux上のnginxでlogrotateを実験する.

nginxのログ出力場所

/var/log/nginx/access.log
/var/log/nginx/error.log

nginxのlogrotateの設定ファイル

$ cat /etc/logrotate.d/nginx
/var/log/nginx/*log {
    create 0644 nginx nginx
    daily
    rotate 10
    missingok
    notifempty
    compress
    sharedscripts
    postrotate
        /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
    endscript
}

初期状態でも以上の設定が記述されています。
今回は、この設定を破棄して、0から検証していきます

logrotateの実行

$ which logrotate
/usr/sbin/logrotate

ほぼすべての環境で、logrotateはinstallされていると思います。(されていなかったらinstallしましょう)

$ logrotate -d /etc/logrotate.d/nginx
reading config file /etc/logrotate.d/nginx
Allocating hash table for state file, size 15360 B

Handling 1 logs

rotating pattern: /var/log/nginx/*log  after 1 days (10 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/nginx/access.log
  log does not need rotating (log has been already rotated)considering log /var/log/nginx/error.log
  log does not need rotating (log has been already rotated)not running postrotate script, since no logs were rotated

※「-d」オプションを付与することで、実際にrotateせずにplanだけ表示することができます。

logrotateの各オプション

missingokオプション

指定したファイルがない場合でもエラー終了しないようにするオプション

/etc/logrotate.d/nginxファイルを修正(存在しないファイル名を指定)

$ vi /etc/logrotate.d/nginx
/var/log/nginx/*log_dummy {
}
$ logrotate -d /etc/logrotate.d/nginx
reading config file /etc/logrotate.d/nginx
Allocating hash table for state file, size 15360 B

Handling 1 logs

rotating pattern: /var/log/nginx/*log_dummy  1048576 bytes (no old logs will be kept)
empty log files are rotated, old logs are removed
considering log /var/log/nginx/*log_dummy
error: stat of /var/log/nginx/*log_dummy failed: No such file or directory
# エラー終了

/etc/logrotate.d/nginxファイルを修正(missingokオプションを追加)

$ vi /etc/logrotate.d/nginx
/var/log/nginx/*log_dummy {
    missingok
}
$ logrotate -d /etc/logrotate.d/nginx
reading config file /etc/logrotate.d/nginx
Allocating hash table for state file, size 15360 B

Handling 1 logs

rotating pattern: /var/log/nginx/*log_dummy  1048576 bytes (no old logs will be kept)
empty log files are rotated, old logs are removed
considering log /var/log/nginx/*log_dummy
  log /var/log/nginx/*log_dummy does not exist -- skipping
# スキップ

maxsizeオプション

rotateする閾値を設定
今回は50kでrotateさせてみます(検証環境のため、小さめです)

$ vi /etc/logrotate.d/nginx
/var/log/nginx/*log {
    missingok
    maxsize 50K
}
$ pwd
/var/log/nginx

$ ls -lh
合計 260K
-rw-r--r-- 1 root root 146K  210 07:23 access.log
-rw-r--r-- 1 root root 1.6K  210 06:27 error.log

$ logrotate -d /etc/logrotate.d/nginx
reading config file /etc/logrotate.d/nginx
Allocating hash table for state file, size 15360 B

Handling 1 logs

rotating pattern: /var/log/nginx/*log  1048576 bytes (no old logs will be kept)
empty log files are rotated, log files >= 51200 are rotated earlier, old logs are removed
considering log /var/log/nginx/access.log
  log needs rotating
considering log /var/log/nginx/error.log
  log does not need rotating (log size is below the 'size' threshold)
rotating log /var/log/nginx/access.log, log->rotateCount is 0
dateext suffix '-20210210'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
renaming /var/log/nginx/access.log.1 to /var/log/nginx/access.log.2 (rotatecount 1, logstart 1, i 1),
renaming /var/log/nginx/access.log.0 to /var/log/nginx/access.log.1 (rotatecount 1, logstart 1, i 0),
renaming /var/log/nginx/access.log to /var/log/nginx/access.log.1
disposeName will be /var/log/nginx/access.log.1
removing old log /var/log/nginx/access.log.1
error: error opening /var/log/nginx/access.log.1: No such file or directory

accessログが50kごとにrotateされることがわかります。
また、rotateしたファイルを削除しようとするがそのファイルが見つからないためエラーになることがわかります

rotateオプション

rotateする際に、何世代前までログを保持するかを設定しましょう

$ vi /etc/logrotate.d/nginx
/var/log/nginx/*log {
    missingok
    maxsize 50K
    rotate 10
}

rotateオプションにて、10世代分のログを保持するように設定しました

$ logrotate -d /etc/logrotate.d/nginx
reading config file /etc/logrotate.d/nginx
Allocating hash table for state file, size 15360 B

Handling 1 logs

rotating pattern: /var/log/nginx/*log  1048576 bytes (10 rotations)
empty log files are rotated, log files >= 51200 are rotated earlier, old logs are removed
considering log /var/log/nginx/access.log
  log needs rotating
considering log /var/log/nginx/error.log
  log does not need rotating (log size is below the 'size' threshold)
rotating log /var/log/nginx/access.log, log->rotateCount is 10
dateext suffix '-20210210'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
renaming /var/log/nginx/access.log.10 to /var/log/nginx/access.log.11 (rotatecount 10, logstart 1, i 10),
renaming /var/log/nginx/access.log.9 to /var/log/nginx/access.log.10 (rotatecount 10, logstart 1, i 9),
renaming /var/log/nginx/access.log.8 to /var/log/nginx/access.log.9 (rotatecount 10, logstart 1, i 8),
renaming /var/log/nginx/access.log.7 to /var/log/nginx/access.log.8 (rotatecount 10, logstart 1, i 7),
renaming /var/log/nginx/access.log.6 to /var/log/nginx/access.log.7 (rotatecount 10, logstart 1, i 6),
renaming /var/log/nginx/access.log.5 to /var/log/nginx/access.log.6 (rotatecount 10, logstart 1, i 5),
renaming /var/log/nginx/access.log.4 to /var/log/nginx/access.log.5 (rotatecount 10, logstart 1, i 4),
renaming /var/log/nginx/access.log.3 to /var/log/nginx/access.log.4 (rotatecount 10, logstart 1, i 3),
renaming /var/log/nginx/access.log.2 to /var/log/nginx/access.log.3 (rotatecount 10, logstart 1, i 2),
renaming /var/log/nginx/access.log.1 to /var/log/nginx/access.log.2 (rotatecount 10, logstart 1, i 1),
renaming /var/log/nginx/access.log.0 to /var/log/nginx/access.log.1 (rotatecount 10, logstart 1, i 0),
renaming /var/log/nginx/access.log to /var/log/nginx/access.log.1
removing old log /var/log/nginx/access.log.11
error: error opening /var/log/nginx/access.log.11: No such file or directory

10世代分ログを保持して、11世代目をdeleteしようとしています(diskがいっぱいになってしまうので)
ただ、現状11世代目のファイルはないのでエラーになります。試しに11世代目のファイルを配置してみます.

$ touch access.log.11
$ logrotate -d /etc/logrotate.d/nginx
reading config file /etc/logrotate.d/nginx
Allocating hash table for state file, size 15360 B

Handling 1 logs

rotating pattern: /var/log/nginx/*log  1048576 bytes (10 rotations)
empty log files are rotated, log files >= 51200 are rotated earlier, old logs are removed
considering log /var/log/nginx/access.log
  log needs rotating
considering log /var/log/nginx/error.log
  log does not need rotating (log size is below the 'size' threshold)
rotating log /var/log/nginx/access.log, log->rotateCount is 10
dateext suffix '-20210210'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
renaming /var/log/nginx/access.log.10 to /var/log/nginx/access.log.11 (rotatecount 10, logstart 1, i 10),
renaming /var/log/nginx/access.log.9 to /var/log/nginx/access.log.10 (rotatecount 10, logstart 1, i 9),
renaming /var/log/nginx/access.log.8 to /var/log/nginx/access.log.9 (rotatecount 10, logstart 1, i 8),
renaming /var/log/nginx/access.log.7 to /var/log/nginx/access.log.8 (rotatecount 10, logstart 1, i 7),
renaming /var/log/nginx/access.log.6 to /var/log/nginx/access.log.7 (rotatecount 10, logstart 1, i 6),
renaming /var/log/nginx/access.log.5 to /var/log/nginx/access.log.6 (rotatecount 10, logstart 1, i 5),
renaming /var/log/nginx/access.log.4 to /var/log/nginx/access.log.5 (rotatecount 10, logstart 1, i 4),
renaming /var/log/nginx/access.log.3 to /var/log/nginx/access.log.4 (rotatecount 10, logstart 1, i 3),
renaming /var/log/nginx/access.log.2 to /var/log/nginx/access.log.3 (rotatecount 10, logstart 1, i 2),
renaming /var/log/nginx/access.log.1 to /var/log/nginx/access.log.2 (rotatecount 10, logstart 1, i 1),
renaming /var/log/nginx/access.log.0 to /var/log/nginx/access.log.1 (rotatecount 10, logstart 1, i 0),
renaming /var/log/nginx/access.log to /var/log/nginx/access.log.1
removing old log /var/log/nginx/access.log.11

エラーがなくなりました

dateextオプションとdateformatオプション

ログの末尾を数字ではなく、わかりやすいように、dateフォーマットにします

$ vi /etc/logrotate.d/nginx

/var/log/nginx/*log {
    missingok
    maxsize 50K
    rotate 10
    dateext
    dateformat _%Y%m%d-%s
}
$ logrotate -d /etc/logrotate.d/nginx
reading config file /etc/logrotate.d/nginx
Allocating hash table for state file, size 15360 B

Handling 1 logs

rotating pattern: /var/log/nginx/*log  1048576 bytes (10 rotations)
empty log files are rotated, log files >= 51200 are rotated earlier, old logs are removed
considering log /var/log/nginx/access.log
  log needs rotating
considering log /var/log/nginx/error.log
  log does not need rotating (log size is below the 'size' threshold)
rotating log /var/log/nginx/access.log, log->rotateCount is 10
Converted ' _%Y%m%d-%s' -> '_%Y%m%d-%s'
dateext suffix '_20210210-1612946815'
glob pattern '_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
renaming /var/log/nginx/access.log to /var/log/nginx/access.log_20210210-1612946815

今回はdata プラス unix-timeを末尾につけるように設定しました。

copytruncateオプション

一度、-dオプションを外して、logrotateを実行してみます。

$ logrotate  /etc/logrotate.d/nginx
$ ls -lh
合計 568K
-rw-r--r-- 1 root root 372K  210 08:45 access.log_20210210-1612946676
-rw-r--r-- 1 root root 122K  210 08:49 access.log_20210210-1612946942
-rw-r--r-- 1 root root 1.7K  210 08:45 error.log

そうすると、access.logが指定した通りにrotateされていることはわかりますが、access.logがrenameされてrotateされるため、起動しているnginxのログを書き込むaccess.logがなくなることがわかります。
そのため、既存のaccess.logをrenameするのではなく、access.logをcopyしてrotateし、copy後のaccess.logを空にするオプションがcopytruncateオプションです。

$ ls -lh
合計 640K
-rw-r--r-- 1 root root  92K  210 08:52 access.log
-rw-r--r-- 1 root root 372K  210 08:45 access.log_20210210-1612946676
-rw-r--r-- 1 root root 133K  210 08:49 access.log_20210210-1612946942
-rw-r--r-- 1 root root 2.1K  210 08:51 error.log
$ logrotate /etc/logrotate.d/nginx
$ ls -lh
合計 612K
-rw-r--r-- 1 root root 2.8K  210 08:52 access.log
-rw-r--r-- 1 root root 372K  210 08:45 access.log_20210210-1612946676
-rw-r--r-- 1 root root 133K  210 08:49 access.log_20210210-1612946942
-rw-r--r-- 1 root root  96K  210 08:52 access.log_20210210-1612947154
-rw-r--r-- 1 root root 2.1K  210 08:51 error.log

この状態でrotateを実行すると、上記のようにaccess.logへのファイルキャッチを逃さないままlogrotateが可能です。

compressオプション

ディスクを節約するために、rotate後のファイルは圧縮したいですよね。そのためのオプションがcompressオプションです.

$ vi /etc/logrotate.d/nginx
/var/log/nginx/*log {
    missingok
    maxsize 50K
    rotate 10
    dateext
    dateformat _%Y%m%d-%s
    copytruncate
    compress
}
$ ls -lh
合計 736K
-rw-r--r-- 1 root root  66K  210 08:54 access.log
-rw-r--r-- 1 root root 372K  210 08:45 access.log_20210210-1612946676
-rw-r--r-- 1 root root 133K  210 08:49 access.log_20210210-1612946942
-rw-r--r-- 1 root root  96K  210 08:52 access.log_20210210-1612947154
-rw-r--r-- 1 root root 2.1K  210 08:51 error.log
$ logrotate /etc/logrotate.d/nginx
$ ls -lh
合計 616K
-rw-r--r-- 1 root root 1.3K  210 08:54 access.log
-rw-r--r-- 1 root root 372K  210 08:45 access.log_20210210-1612946676
-rw-r--r-- 1 root root 133K  210 08:49 access.log_20210210-1612946942
-rw-r--r-- 1 root root  96K  210 08:52 access.log_20210210-1612947154
-rw-r--r-- 1 root root  847  210 08:54 access.log_20210210-1612947290.gz
-rw-r--r-- 1 root root 2.1K  210 08:51 error.log

このように、rotate後のファイルがgzip圧縮されました。

notifemptyオプション

ログファイルが空ならrotateしないオプションです

daily, weekly, monthlyオプション

ログローテーションの間隔を決めるオプションです。

  • daily(日次)
  • weekly(週次)
  • monthly(月次)