はじめに
今回はLinux(CentOS8)でログローテーションを設定する方法を説明します。
ログローテーションって?
例えば、監視対象から監視サーバー(またはログサーバー)へのログ転送の設定をして、ログ監視をするという話はよくあります。しかし、ログを無事に取得できるようになったので「もうこれで安心♪」というわけではないのです。
取得したログは当然勝手に消えてくれないので(勝手に消えるのも困りますが)、このまま放っておくとログは指定したファイルに溜まり続けます。いきなりストレージを圧迫するなんてことはありませんが、じわじわと容量が増え続けます。たとえシステム全体の容量に問題がなくても、ファイル自体の容量が大きくなりすぎると、ファイルを開くために時間がかかってしまうなんてことも起こります。
cronやmessagessといったログファイルは、デフォルトで設定されているログファイルです。デフォルトで設定されているログファイルを見てみると、すでに定期的にログを保管し、一定期間保管すると削除する設定がされていることが多いです。一定期間ためたログをルールに従って保存・破棄をすることを「ログローテーション」と言います。自分でログ転送を設定した際には、是非ログローテーションの設定もセットで実行しましょう。
知らないと設定時にハマる?
私自身がハマっただけですが…ログローテーションは「設定ファイルを更新した→すぐにファイルがルール通り作られる」というわけではない!ということです。
今回は、ログローテーションの設定ファイルの例から設定方法を実際に検証した結果と共に紹介したいと思います。
検証
検証環境
設定するOSはCentOS8を使用しています。今回はsyslogのファイルをログローテーションさせるので、転送元が存在しますが、ログローテションの設定には関係ないので、割愛します。
検証する2つのファイル
今回ログローテーションするファイルは以下の2つです。
- /var/log/logtest/rt01 …既にログローテーションされているログファイル
- /var/log/logtest/testlog …今回の検証ではじめてログローテーションされるファイル
/var/log/logtest/rt01はすでに/etc/logrotate.d/syslog(ログローテーションの設定ファイル)に記載されているファイルで、すでにログローテーションが実行されているファイルです。
一方の/var/log/logtest/testlogは、今回の検証のために初めてログローテーションに登録します。
ログローテーションは「すでにログローテーションされているファイル」と「初めてログローテションに設定させたファイル 」では、ログローテーションが実行された際の結果が変わります。この辺りを理解していないと混乱しますので、是非とも検証した結果をみていただきたいと思います。
既存のログローテーション設定を確認
設定ファイルを見る
まずは、現状の設定を見ます。ログローテーションしたいファイルの指定やログローテーションの設定ファイルは、ログローテーション全体に反映させる/etc/logrotate.confという設定ファイルと、各ファイルごとに設定できる/etc/logrotate.d配下の設定ファイルがあります。今回は/etc/logrotate.d配下にあるファイルで設定をして行きます。設定ファイルは種類分けされているおり、cronで/etc/logrotate.d配下の設定ファイルを1つずつ参照してログローテーションを実行していきます。
今回はsyslogに関するログをログローテションを設定するので、/etc/logrotate.d/syslogを見てみます。
1 2 3 4 5 6 7 8 9 10 11 12 |
[root@localhost ~]# cat /etc/logrotate.d/syslog /var/log/logtest/rt01 { missingok daily ifempty rotate 10 sharedscripts postrotate /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true endscript } |
/var/log/logtest/testlogについては、まだ記述がありません。/var/log/logtest/testlogは設定を確認した後、追加します。
設定ファイルの書式について
上記の通り、設定ファイルには「missingok」や「daily」といった単語を記述します。これらの意味については、別でまとめているのでこちらを参考にしてみてください。
上記の「daily」によって、1日おきにログを再生成する設定になっています。
crontabに記述 ※検証のために設定
次にクーロンの設定をします。/etc/cron.daily配下のファイルを毎日12時15分に実行するようにします。
見出しにも書いてありますが、この設定は検証を見やすくするためなので、本来は不必要な設定です。環境にもよりますが、少なからずCentOS8のデフォルト設定ではanacronによって実行されるように設定されています。今回は明示的に実行される時間を設定したいので、crontabに記載します。
以下のようにcrontabを書き換えます。毎日12時15分に実行させる設定を入れます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[root@localhost ~]# cat /etc/crontab SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root # For details see man 4 crontabs # Example of job definition: # .---------------- minute (0 - 59) # | .------------- hour (0 - 23) # | | .---------- day of month (1 - 31) # | | | .------- month (1 - 12) OR jan,feb,mar,apr ... # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat # | | | | | # * * * * * user-name command to be executed 15 12 * * * root run-parts /etc/cron.daily |
繰り返しになりますが、「run-parts /etc/cron.daily」という記載については、CentOS8のデフォルトの設定ではanacronで行う設定になっています。この検証が終わったら、この設定は消します。
…とはいえ、個人的な話ではありますが以前業務で扱ったLinuxOSはバージョンが古く、crontabに /etc/cron.dailyや /etc/cron.monthが書かれていました(まだまだあるのかな?)。
さっきから何回も出てくるanacronって何?という方は、次の記事を参考にしてみてください。
logrotateファイルの存在を確認する
ログローテーションを実行するファイルがある場所を確認します。/etc/cron.daily配下を見てみます。
1 2 |
[root@localhost ~]# ls /etc/cron.daily/ logrotate rhsmd |
logrotateというファイルが、ログローテーションを実行するファイルになります。ちゃんと/etc/cron.daity配下にありました。これをcronでが実行することで、ログローテーションが実行されます。
ログローテーションのステータスを見る
ログローテーションにはステータスが書かれた/var/lib/logrotate/logrotate.statusというファイルが存在します。まずは何が書かれているのかを見ましょう。実際にはたくさん書かれていますが、以下は抽出して表示しています。
1 2 |
[root@localhost ~]# cat /var/lib/logrotate/logrotate.status |grep test "/var/log/logtest/rt01" 2020-10-1-12:50:59 |
見ての通り、ステータスというのは日付が記載されています。これは、原則ログローテーションされた日付を意味します(原則というのがポイントです)。cronで実行されたlogroteは、まずこのステータスを参照してログローテーションを実行するかどうかを判断します。
上記はログローテーションを2020-10-1-12:50:59に実行したということになります。
新たにログローテーションさせるファイル
最初に示した通り、今回の検証では新しくログローテーションを設定してみたいと思います。/var/log/logtest/testlogを/etc/logrotate.d/syslogに追記してみます。ルールは/etc/logrotate.d/rt01と同じルールでログローテーションするように追記します。
/etc/logrotate.d/syslogに追記する
以下のように、書き換えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[root@localhost ~]# cat /etc/logrotate.d/syslog /var/log/logtest/rt01 /var/log/logtest/testlog { missingok daily ifempty rotate 10 sharedscripts postrotate /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true endscript } |
/var/log/logtest/testlogを追加しました。
バックアップファイルを作る際の注意点
設定変更するバックアップファイルを作成する際には、作成するディレクトリに注意が必要です。cronで実行されるlogrotateは、/etc/logrotate.d配下にあるファイルを全て参照し、実行します。つまり同じ階層にバックアップファイルを作成すると、「ログローテーション対象が重複して設定されている」というエラーログを出します。バックアップを作成する際には、別の階層に作成しましょう。
もう一度ステータスを見る
logrotate.statusのステータスがどう変化するのか見てみましょう。
1 2 |
[root@localhost ~]# cat /var/lib/logrotate/logrotate.status |grep test "/var/log/logtest/rt01" 2020-9-29-12:50:59 |
ステータスは原則ログローテーションを実行した日付が入るので、先ほど追加した/var/log/logtest/testlogについては何も記載がありません。
ログローテーションを実行させる
ステータスを変更する
では、意図的にログローテーションを実行させます。ログローテーションを意図的に実行させるには、OSの時刻を変更してcronを実行させる方法もありますが、ステータスを変更することでも実行させることができます。
以下のように、logrotate.statusを編集して、実行された日を巻き戻します。実行された日付を9月29日にしてみました。
1 2 |
[root@localhost ~]# cat /var/lib/logrotate/logrotate.status |grep test "/var/log/logtest/rt01" 2020-9-29-12:50:59 |
日付と時刻を変更する
指定した時刻を待ってられないので、crontabに指定した時刻の直前に時刻を設定します。以下のように、dateコマンドで日付をステータス以降かつ、時刻も12時14分に設定します。
1 2 |
[root@localhost ~]# date 10011214 2020年 10月 1日 木曜日 12:14:00 JST |
これで、1分後にcrontabで指定した12時15分を迎え、ログローテーションを実行させるようにします。
ログローテーションが実行されたかを確認する
ログローテーションが実行されたかどうかは、cronのログを見ることで確認できます。
1 2 3 4 5 6 7 |
[root@localhost ~]# cat /var/log/cron Oct 1 12:15:01 localhost CROND[46709]: (root) CMD (run-parts /etc/cron.daily) Oct 1 12:15:01 localhost run-parts[46709]: (/etc/cron.daily) starting logrotate Oct 1 12:15:01 localhost run-parts[46709]: (/etc/cron.daily) finished logrotate Oct 1 12:15:01 localhost run-parts[46709]: (/etc/cron.daily) starting rhsmd Oct 1 12:20:01 localhost run-parts[46709]: (/etc/cron.daily) finished rhsmd |
どうやら無事に実行されたようです。結果を見てみます。
ログローテーションして作成されたファイルを確認する
findコマンドで/var/log/logtest/配下に日付が「1001」が含まれているファイルを探します。lsコマンドでも良いんですけどね…。検証した時の私はfindコマンドを使ってますので、その時のノリをそのまま反映しますね。
1 2 |
[root@localhost ~]# find /var/log/logtest/ -name "*1001" /var/log/logtest/rt01-20201001 |
注目すべきは2020/10/01の分のログローテーションが実行されたのに、rt01の分しかファイルしかありません。testlogのログファイルはログローテーションで生成されていません。
しかし、ここで焦ってはいけません。決して設定ミスでログローテーションされていないわけではないのです。
ステータスを確認する
再度ステータスを確認してみましょう。
1 2 3 |
[root@localhost ~]# cat /var/lib/logrotate/logrotate.status |grep test "/var/log/logtest/testlog" 2020-10-1-12:0:0 "/var/log/logtest/rt01" 2020-10-1-12:15:1 |
ログローテーションのファイルが作成されていませんが、/var/lib/logrotate/logrotate.statusにはtestlogの記録が追加されています。
つまり、
ログローテーションの初回は、実行されないでステータスに記録されるだけ!
ということです。この記事で一番言いたいことなので、大きく書かせてもらいますね。
ステータスに実行された日付ではない記録が残る
もう1つ注目すべきは、”/var/log/logtest/testlog” 2020-10-1-12:0:0という記載です。実行時刻とは関係ない12時という情報が記録されています。
/var/lib/logrotate/logrotate.statusには原則ログローテーションが実行された時刻が記録されると述べてきましたが、これが原則に対する例外になります。初回は実行された時刻とは関係ない時刻が記録されるということになります。
再度ログローテーションを実行する
日付をさらに1日進める
以下のように、dateコマンドで日付を変更します。
1 2 |
[root@localhost logrotate]# date 10021214 2020年 10月 2日 金曜日 12:14:00 JST |
2020/10/02の12時14分にしました。
ログを見る
ログローテーションが実行されたを、ログをみて確認します。
1 2 3 4 5 6 7 |
[root@localhost ~]# cat /var/log/cron Oct 2 12:15:01 localhost CROND[47026]: (root) CMD (run-parts /etc/cron.daily) Oct 2 12:15:01 localhost run-parts[47026]: (/etc/cron.daily) starting logrotate Oct 2 12:15:01 localhost run-parts[47026]: (/etc/cron.daily) finished logrotate Oct 2 12:15:01 localhost run-parts[47026]: (/etc/cron.daily) starting rhsmd Oct 2 12:20:01 localhost run-parts[47026]: (/etc/cron.daily) finished rhsmd |
無事に実行されました。
ログローテーションして作成されたファイルを確認する
先ほどと同様に「1002」というファイル名のファイルを探します。
1 2 3 |
[root@localhost ~]# find /var/log/logtest/ -name "*1002" /var/log/logtest/rt01-20201002 /var/log/logtest/testlog-20201002 |
今度は無事に2つとも作成されています。2回目でようやくログローテーションされることがわかりました。
ステータスを確認する
ステータスも確認します。
1 2 3 |
[root@localhost ~]# cat /var/lib/logrotate/logrotate.status |grep test "/var/log/logtest/testlog" 2020-10-2-12:15:1 "/var/log/logtest/rt01" 2020-10-2-12:15:1 |
今度は2つともログローテーションが実行された時刻になっています。
その他
以下はログローテーションに関する確認コマンドです。
logrotateを強制的に実行する
上記の検証ではcronで少しではありますが待って実行されるのを待ちましたが、以下のコマンドではcronの設定に関係なく実行することが可能です。
1 |
[root@localhost log]# /usr/sbin/logrotate -fv /etc/logrotate.conf |
logrotateの実行結果を確認する(実際には実行しない)
以下は、実際には実行しないで、結果をデバックします。
1 |
[root@localhost log]# /usr/sbin/logrotate -d /etc/logrotate.d/syslog |
まとめ
ログローテーションの設定はいかがだったでしょうか?
ログローテーションを設定した後に確認する際に、1回目のローテーションでファイルが生成されないのが一番ややこしい部分かと思います。個人的にはanacronの理解も乏しかったので、crontabの実行とanacronの実行が重なって、何が起こっているのか訳がわからない状況に陥りました(笑)。
ログローテーションの設定をする際には、是非ファイルの存在とステータス(/var/lib/logrotate/logrotate.statu)の確認をセットにして作業をしてみてください。