logrotateでログを1時間単位で分割し、zstdで圧縮する
サーバ
Lastmod: 2023-11-30
Published: 2021-03-29

logrotateでzstdで圧縮しつつ、1時間ごとにnginxのログを分割したかった時の
メモを残しておきます。

概要

素直に、/etc/logrotate.conf/etc/logrotate.d/ に設定を入れると基本的に
/etc/cron.daily/logrotate のデイリーCRONで実行されてしまう。

今回は1時間ごとのログローテートをしたいので、logroateの設定を別に用意して、
systemdのtimer機能を使い実行するようにしてみました。

ztsdを使えるようにする

# apt install zstd

logrotate

/etc/logrotate-nginx.conf を作ることにします。
今回はzstdですが、bzip2なども設定同じようにすれば変更することが可能です。

# cat << _EOF_ > /etc/logrotate-nginx.conf
compresscmd /usr/bin/zstd # zstdのパスを指定
compressoptions -12       # zstdに渡すオプション。個人的には-12がいい感じだった
compressext .zst          # 付与する拡張子

/var/log/nginx/*.log {
        missingok
        rotate 720 # 24時間 * 30日 
        dateext
        dateformat -%Y%m%d%H
        compress
        notifempty
        create 0640 www-data adm
        sharedscripts
        prerotate
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                        run-parts /etc/logrotate.d/httpd-prerotate; \
                fi \
        endscript
        postrotate
                invoke-rc.d nginx rotate >/dev/null 2>&1
        endscript
}
_EOF_

systemd

  • serviceを定義
# cat << _EOF_ > /etc/systemd/system/logrotate-nginx.service
[Unit]
Description=logrotate-nginx
After=network.target
[Service]
Type=simple
ExecStart=/usr/sbin/logrotate -f /etc/logrotate-nginx.conf
PrivateTmp=true
[Install]
WantedBy=multi-user.target
_EOF_
  • timerを定義
# cat << _EOF_ > /etc/systemd/system/logrotate-nginx.timer
[Unit]
Description=logrotate-nginx
[Timer]
OnCalendar=*:00:00
[Install]
WantedBy=timers.target
_EOF_
  • systemdの設定を読み込み
# systemctl daemon-reload
  • timerをenableにする
# systemctl enable logrotate-nginx.timer
  • timerの開始
# systemctl start logrotate-nginx.timer
  • timerのステータスを確認
# systemctl status logrotate-nginx.timer
● logrotate-nginx.timer - logrotate-nginx
     Loaded: loaded (/etc/systemd/system/logrotate-nginx.timer; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2021-03-29 20:00:00 JST; 5h 58min ago
    Trigger: n/a
   Triggers: ● logrotate-nginx.service

Mar 29 19:00:00 log systemd[1]: Started logrotate-nginx.

Activeで次回実行される時間、ログで過去に実行された時間を知ることができます🎉

2023年11月追記

1時間ごとであればあまり気になりませんが、1分単位でログを分割するとtimerの精度で、 ズレが生じてしまい、想定した時間以外が含まれてしまいます。

そのため、きっちり0秒で実行してほしい場合は、以下のように設定するとよいです。

[Unit]
Description=logrotate-nginx
[Timer]
OnCalendar=*:*:00
AccuracySec=1s
[Install]
WantedBy=timers.target

AccuracySecを指定することで、1秒単位で実行することができます。