Linux ログローテーションのやり方と cron との関係

Linux にはログローテーション用のコマンドとして “logrotate” が存在します。logrotate は設定に基づき世代管理やファイルのリネームなどを行ってくれる便利なコマンドです。

しかし logrotate はデーモンではないので、利用する度に実行する必要があります。人間が定期的に logrotate コマンドを実行するのは現実的ではありません。Linux ではその定期的な実行を実現するための手段として crond を利用します。

crond の設定

CentOS7.4 では、インストール直後の状態でも以下のように日次の cron として logrotate を実行するようになっています。

[root@localhost ~]# ls /etc/cron.daily/
logrotate  man-db.cron

[root@localhost ~]# cat /etc/cron.daily/logrotate
#!/bin/sh
/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
    /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0

つまりログローテーションにおいて cron 側の設定箇所というものは基本的に存在しません。

logrotate.conf の設定

logrotate もデフォルトで設定が入っています。以下のように、/etc/logrotate.conf が logrotate の共通設定です。

weekly           # 毎週ログファイルをバックアップ(分割)
rotate 4         # バックアップファイルを4つ残す。ログファイルと合わせると5つ
create           # バックアップ時logrotateが空ファイルを作成する
dateext          # バックアップファイルの末尾が数字の羅列ではなく日付になる
include /etc/logrotate.d          # 個別設定の読み込み
/var/log/wtmp {                   # 個別設定
    monthly
    create 0664 root utmp
    minsize 1M
    rotate 1
}
/var/log/btmp {                   # 個別設定
    missingok
    monthly
    create 0600 root utmp
    rotate 1
}

/etc/logrotate.d を include しているので logrotate.d にも設定を分けて記載することができます。勿論上記の /var/log/wtmp や /var/log/btmp のように logrotate.conf に全て記載しても構いません。デフォルトだと以下のようにいくつかの設定が外出しされています。

[root@localhost ~]# ls  /etc/logrotate.d
bootlog  chrony  syslog  wpa_supplicant  yum

logrotate.d 配下のファイルで記載が省略されている項目に関しては logrotate.conf の設定を継承します。

[root@localhost ~]# cat /etc/logrotate.d/syslog
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
    missingok
    sharedscripts
    postrotate
        /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
    endscript
}
postrotate の意味

postrotate オプションで、バックアップファイル作成後に rsyslogd のプロセスに対して HUP シグナルを送信しています。サーバプロセスの多くは HUP シグナルを受け取るとプロセスを終了して再起動します。その為再起動にも使用されます。つまりログファイル分割時に rsyslogd を再起動しているということです。

postrotate
        /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true

なぜそのようなことをするのでしょうか。実は、これを行わないと rsyslogd は分割したバックアップファイルの方にログを出力し続けてしまいます。

rsyslog がログを出力している場合には絶対に忘れないようにしましょう。rsyslog が出力しているログは /etc/rsyslog.conf を確認すれば分かります。

実際の設定例

logrotate の設定例は以下のようなパターンがあります。なお、詳細は後述しますが省略した値が logrotate.conf から継承されないケースがありますので、個別ファイルでも明確に定義した方がよいでしょう。

weekly            # 基本的にはweeklyかmonthlyで事足りる
rotate 4          # logrotate.confと同じ値でも個別に定義した方がよい
compress          # 基本的に圧縮した方がいい
nocreate          # アプリケーション側で空ファイルを作成する場合はnocreateの方がよい
ifempty           # 空ファイルをローテーションする。他システム的に空でもローテした方がよい
dateext           # バックアップファイルの末尾が数字ではなく日付になる
olddir /var/log/backup           # ログの保存場所を指定

logrotate のテスト方法

logrotate のテストは “logrotate -f” コマンドで実行することが可能です。例えば「logrotate -f /etc/logrotate.conf」を実行すれば全てのログを即時ローテーションすることが可能です。

ただ、logrotate -f には注意点がいくつかあるので、確実に把握しておくようにしましょう。

rotate を定義していない個別ファイルを logrotate -f してはいけない

まずは最も注意しなければならない点から。例えば squid というサービスのログを個別で定義するために /etc/logrotate.d/squid というファイルを用意し、rotate の間隔は logrotate.conf と同じなので省略したとします。

この時「logrotate -f /etc/logrotate.conf」を実行すれば問題はありませんが、ログファイル全体に影響は与えたくないと思い「logrotate -f /etc/logrotate.d/squid」を実行したとします。この時点で問題発生です。

実は logrotate -f で個別ファイルを強制ローテーションした場合、logrotate.conf は読み込まれません。結果 “rotate 0” という扱いになり、ログファイルが削除されます。

logrotate -f /etc/logrotate.conf が1度しかできない

dateext が定義されているとファイル名が「フィル名-YYYYMMDD」となる為、同じ日にログローテーションしようとするとファイル名が重複します。その為 logrotate -f で強制的にログローテーションするテストが1日1回しか成功しません(エラーも出ません)。

dateformat -%Y%m%d%s

上記のようにファイル名に秒も含めるようにすることで回避が可能です。

オプションの順番について

これは logrotate -f 実行時だけの注意点ではありませんが、オプションの順番にも注意しなければなりません。

例えば下記のように include の後に dateformat でファイル名の書式を変更した場合、logrotate.conf に設定が定義されている wtmp や btmp は書式が期待した通りに変更されますが、include で 読み込んだ cron などの個別に設定されているログファイルは書式が変更されません。

dateext
include /etc/logrotate.d
dateformat -%Y%m%d%s

これは include した後に dateformat を変更しているからです。logrotate.conf は基本的に共通設定として扱いますので、include は必ずオプションの最後に記載するようにしましょう。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)