はじめに
ログを日次や指定した時間でローテートすることができる、logrotate
を使ってみる。
アプリケーションのログや、自作のログなどはlogrotate
をすると良いので、この機会に覚えておきたい。
環境
Windows 10 Professional
WSL2 (Ubuntu22.04 LTS)
logrotate 3.19.0
準備
logrotate
が入っていることを確認する。
which logrotate
ない場合は下記で入れる。
sudo apt-get install logrotate
logrotateの実践
設定ファイルの確認
まずは、logrotate
の大元の設定ファイルを確認する。
cat /etc/logrotate.conf
# see "man logrotate" for details
# global options do not affect preceding include directives
# rotate log files weekly
weekly
# use the adm group by default, since this is the owning group
# of /var/log/syslog.
su root adm
# 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.
上記のようになっている、 /etc/logrotate.d
に Apache
での設定やら、 nginx
での設定など、アプリケーションごとの設定ファイルを入れるのが良い。
ちなみに、 /etc/logrotate.d
は下記のようになっている。
/etc/logrotate.d$ ll
total 52
drwxr-xr-x 2 root root 4096 May 13 14:05 ./
drwxr-xr-x 98 root root 4096 Jun 10 11:46 ../
-rw-r--r-- 1 root root 120 Sep 12 2021 alternatives
-rw-r--r-- 1 root root 126 Nov 12 2019 apport
-rw-r--r-- 1 root root 173 Apr 8 2022 apt
-rw-r--r-- 1 root root 91 Mar 18 2022 bootlog
-rw-r--r-- 1 root root 130 Oct 14 2019 btmp
-rw-r--r-- 1 root root 112 Sep 12 2021 dpkg
-rw-r--r-- 1 root root 374 Dec 24 2021 rsyslog
-rw-r--r-- 1 root root 270 Mar 8 2022 ubuntu-advantage-tools
-rw-r--r-- 1 root root 209 Sep 19 2021 ufw
-rw-r--r-- 1 root root 235 Feb 19 2021 unattended-upgrades
-rw-r--r-- 1 root root 145 Oct 14 2019 wtmp
設定ファイルを作成する
/etc/logrotate.d
に 自分が作成するアプリケーションのログを設定する。
$ sudo touch /etc/logrotate.d/mylog
上記で作成を行う。
$ sudo vim /etc/logrotate.d/mylog
/var/log/test/test.log { # 対象
ifempty
dateformat .%Y%m%d
missingok
compress
daily
rotate 10
}
※設定の種類 (ChatGPTに出力してもらった。)
設定オプション | 説明 |
---|---|
compress | ローテーション後にログファイルを圧縮するかどうかを指定します。 |
copytruncate | ログファイルを切り詰めずにコピーしてから新しいファイルを作成します。 |
daily | ローテーションの間隔を日単位で指定します。 |
weekly | ローテーションの間隔を週単位で指定します。 |
monthly | ローテーションの間隔を月単位で指定します。 |
rotate <count> | ログファイルをローテーションする回数を指定します。 |
size <size> | ログファイルのサイズが指定したサイズに達した場合にローテーションを実行します。 |
maxsize <size> | ログファイルの最大サイズを指定します。ログファイルがこのサイズを超えた場合にローテーションを実行します。 |
notifempty | ログファイルが空の場合にはローテーションを実行しません。 |
create | ローテーション後に新しいログファイルを作成するかどうかを指定します。既存のログファイルは空にされます。 |
dateext | ローテーションされたログファイルに日付を追加します。 |
dateformat | ローテーションされたログファイルの日付のフォーマットを指定します。 |
postrotate | ローテーション後に実行するコマンドを指定します。 |
prerotate | ローテーション前に実行するコマンドを指定します。 |
sharedscripts | postrotate またはprerotate スクリプトを1回だけ実行します(すべてのローテーション対象のログファイルに対して)。 |
missingok | ローテーション対象のログファイルが存在しない場合でもエラーを発生させずに処理を続行します。 |
動作
- ログファイルが書き込まれる場所を作成する。
sudo mkdir -p /var/log/test
sudo chmod 777 /var/log/test
- cronで自動的にログファイルを書き込むように設定する。
crontab -e
- 1分置きに自動で書き込むようにする。
crontab
*/1 * * * * echo "[`date "+%Y%m%d-%H%M%S"`] Hello, World" >> /var/log/test/test.log
- 書き込まれているかの確認
less /var/log/test/test.log
ちゃんと書き込まれているっぽい。
[20230610-122449] Hello, World
- 設定ファイルでのローテートをさせる。
sudo logrotate -df /etc/logrotate.d/mylog
-d
・・・デバッグモード
-f
・・・強制的にローテートさせる。
下記のようにエラーが出た。 親ディレクトリの権限による問題みたい。
error: skipping "/var/log/test/test.log" because parent directory has insecure permissions (It's world writable or writable by group which is not "root") Set "su" directive in config file to tell logrotate which user/group should be used for rotation.
権限を適切なものに修正する。
sudo chmod 700 /var/log/test
sudo chmod 666 /var/log/test/test.log
また、これに伴い、crontab -e
を行い、下記のように修正する。
*/1 * * * * sudo sh -c 'echo "[`date "+%Y%m%d-%H%M%S"`] Hello, World" >> /var/log/test/test.log'
この状態で再度実行をする。
sudo logrotate -df /etc/logrotate.d/mylog
ログがローテートされている!
$ sudo ls test/
test.log.1.gz
何回もローテートされることを確認。
10世代までだが、2世代まで確認する。
$ sudo sh -c 'echo "[`date "+%Y%m%d-%H%M%S"`] Hello, World" >> /var/log/test/test.log'
$ sudo logrotate -f /etc/logrotate.d/mylog
$ sudo sh -c 'echo "[`date "+%Y%m%d-%H%M%S"`] Hello, World" >> /var/log/test/test.log'
$ sudo ls test/
test.log test.log.1.gz test.log.2.gz
疑問に思った点
logrotate
はどのように行われるのか?
日次でログファイルを切りかえる際に、いずれかなのかと考えた。
- 既存のログファイルをリネーム→新しくログファイルを作成
- 既存のファイルをコピー+リネームし、古いログとして作成。既存のログファイルを
cp /dev/null
などで空にする。
どうやら調べると、1番目がデフォルトの動作で、2番目が copytruncate
を指定したときの動作とのこと。
ChatGPT
に聞いてみると、下記の回答を得られた。
copytruncateは、logrotateの設定オプションの1つです。このオプションが指定された場合、logrotateはログファイルを切り詰めずに、新しいファイルを作成します。
通常、logrotateは既存のログファイルをリネーム(または削除)して新しいログファイルを作成します。しかし、copytruncateオプションが指定されると、logrotateは既存のログファイルを切り詰めずにそのままの状態でコピーし、同じ名前の新しいログファイルを作成します。
これにより、アプリケーションがログファイルに直接書き込んでいる場合でも、ログの追加は中断されずに継続されます。なお、この方法では、元のログファイルの内容は失われますが、ファイルディスクリプタは変更されないため、アプリケーションはログの書き込みを続けることができます。
copytruncateは、特定のアプリケーションがログファイルを開いたままにする必要がある場合や、ログファイルを分割してもファイルディスクリプタを維持する必要がある場合などに便利です。ただし、注意点として、切り詰められたログファイルは一部のログエントリが欠落している可能性があるため、データの完全性が重要な場合には適切なオプションを選択する必要があります。
そのため、 1番目の方法の場合は、 ローテートする際に postscript
を書いてアプリケーションをリロードや再起動をして、ログファイルを新しいものに再度読み込ませる必要がある。
2番目の方法( copytruncate
)では、上記のような設定はいらないが、ログエントリが欠落する可能性があるとのことだ。
postscriptはcopytruncateを指定しない場合、必ず必要か?
1点目の疑問で思った、ローテートする際に postscript
を書いてアプリケーションをリロードや再起動をして、ログファイルを新しいものに再度読み込ませる必要がある。
の部分だが、これも ChatGPT
に聞いてみる。
copytruncateオプションを指定しない場合、logrotateは既存のログファイルをリネーム(または削除)して新しいログファイルを作成します。そのため、アプリケーションは新しいログファイルに対してファイルディスクリプタを持っていないため、再起動やリロードが必要になる場合があります。
多くのアプリケーションでは、ログファイルへの書き込みはファイルディスクリプタを介して行われます。logrotateによって既存のログファイルがリネームされると、アプリケーションは古いファイルディスクリプタを使用し続けることになります。新しいログファイルが作成された後、アプリケーションは新しいファイルディスクリプタを取得する必要があります。
したがって、アプリケーションがログファイルのリロードや再起動をサポートしていない場合、ログファイルの切り替え後にログの書き込みが正常に継続されない可能性があります。この場合、アプリケーションを再起動するか、ログの書き込みを再開するための特定の手順を実行する必要があります。
ただし、アプリケーションによっては、logrotateの信号を受け取ってログファイルを再オープンする機能を備えている場合もあります。この場合、特別な処理や再起動は不要であり、アプリケーションは新しいログファイルに対して正常にログの書き込みを続けることができます。
アプリケーションのドキュメントやログ関連の設定を確認し、logrotateの挙動に関するアプリケーション固有の要件や推奨事項を確認することをおすすめします。
ということなので、アプリケーションによっては、 postscript
で再起動、リロードがなくてもローテートしてくれるらしい。
参考
- 任意のログをlogrotateを使って管理する
https://qiita.com/Esfahan/items/a8058f1eb593170855a1 - logrotateの備忘録
https://qiita.com/may-bee-39/items/4fb6beb19c6f4fe8b587 - Logrotate | ArchLinux
https://wiki.archlinux.jp/index.php/Logrotate
おわりに
logrotate
を勉強した。
巨大な1個のログファイルとならないように、アプリケーションのログは適切にローテートする必要がある。
そのため、logrotate
を設定していないログがある場合については、使用することを検討したほうが良い。