この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので十分ご注意ください。
はじめに
こんにちは。今日はlogrotateのお話です。
RHEL9ではlogrotateの実行タイミングはanacronではなくlogrotate.timerというsystemdのTimer unitを利用して制御されています。
今回の記事では、実際にlogrotate.timerを編集して実行時間を変えることができるかどうかを検証することが狙いとなります。
logrotate.timerによるlogrotateの制御
loglotateとは
さて、本題に入る前にlogrotateとは何だったかをおさらいしましょう。以下はmanの一部抜粋です。
logrotate(8) – Linux man page
logrotate is designed to ease administration of systems that generate large numbers of log files. It allows automatic rotation, compression, removal, and mailing of log files. Each log file may be handled daily, weekly, monthly, or when it grows too large.
参考:
https://linux.die.net/man/8/logrotate
翻訳すると以下の通りです。
logrotate は、大量のログ ファイルを生成するシステムの管理を容易にするように設計されています。ログ ファイルの自動ローテーション、圧縮、削除、メール送信が可能になります。各ログ ファイルは、毎日、毎週、毎月、またはサイズが大きくなりすぎたときに処理できます。
こうした多機能で管理者の負担を軽減してくれる素敵logrotateですが、どのタイミングで実行されるかを制御する必要があります。
その制御を担うのが今回の記事で取り上げるsytemdのlogrotate.timerというユニットです。
※ systemdの仕組みについて、次の書籍が分かりやすかったです。各unitに対する詳しい説明はありませんが、概要の把握にはぴったりだと感じました。 -> [バージョン8&9両対応! Red Hat Enterprise Linux完全ガイド ]
logrotate.timerの検証
以下では設定ファイルの確認からunitファイルの編集、結果の確認まで順番に見ていきたいと思います。
まず、デフォルトのunitファイルを確認してみます。
次のように、/usr/lib/systemd/system/配下にある、logrotateに関するunitファイルはlogrotate.timerとlogrotate.serviceの2つです。
[root@ip-10-0-2-46 ~]# ls -lrt /usr/lib/systemd/system/ | grep logrotate
-rw-r--r--. 1 root root 191 Oct 14 2019 logrotate.timer
-rw-r--r--. 1 root root 870 Aug 21 2020 logrotate.service
中身を見てみます。
まず、logrotate.timeユニットの方からです。
[root@ip-10-0-2-46 ~]# cat /usr/lib/systemd/system/logrotate.timer
[Unit]
Description=Daily rotation of log files
Documentation=man:logrotate(8) man:logrotate.conf(5)
[Timer]
OnCalendar=daily
AccuracySec=1h
Persistent=true
[Install]
WantedBy=timers.target
日次で実行することを意味する
が設定されていることが分かります。OnCalendar=daily
ちなみに、
は後述するanacronと同様の動作をする設定になります。Persistent=true
参考: systemd.timer(5) — Linux manual page
https://man7.org/linux/man-pages/man5/systemd.timer.5.html
Persistent=
Takes a boolean argument. If true, the time when the service unit was last triggered is stored on disk. When the timer is activated, the service unit is triggered immediately if it would have been triggered at least once during the time when the timer was inactive. Such triggering is nonetheless subject to the delay imposed by RandomizedDelaySec=. This is useful to catch up on missed runs of the service when the system was powered down. Note that this setting only has an effect on timers configured with OnCalendar=. Defaults to false.
翻訳:
Persistent= ブール値の引数を受け取ります。 true の場合、サービス ユニットが最後にトリガーされた時刻がディスクに保存されます。タイマーがアクティブ化されると、タイマーが非アクティブな間にサービス ユニットが少なくとも 1 回トリガーされていた場合、サービス ユニットはすぐにトリガーされます。ただし、このようなトリガーは、RandomizedDelaySec= によって課される遅延の影響を受けます。これは、システムの電源がオフになったときにサービスが実行されなかった場合にそれを取り戻すのに役立ちます。この設定は、OnCalendar= で構成されたタイマーにのみ影響することに注意してください。デフォルトは false です。
次はlogrotate.serviceユニットの方を見てみます。
[root@ip-10-0-2-46 ~]# cat /usr/lib/systemd/system/logrotate.service
[Unit]
Description=Rotate log files
Documentation=man:logrotate(8) man:logrotate.conf(5)
RequiresMountsFor=/var/log
ConditionACPower=true
[Service]
Type=oneshot
ExecStart=/usr/sbin/logrotate /etc/logrotate.conf
# performance options
Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7
# hardening options
# details: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
# no ProtectHome for userdir logs
# no PrivateNetwork for mail deliviery
# no NoNewPrivileges for third party rotate scripts
# no RestrictSUIDSGID for creating setgid directories
LockPersonality=true
MemoryDenyWriteExecute=true
PrivateDevices=true
PrivateTmp=true
ProtectClock=true
ProtectControlGroups=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectSystem=full
RestrictNamespaces=true
RestrictRealtime=true
logrotate.serviceには、
とある通り、実際に起動するプログラムとその設定ファイルがそれぞれ記載されていることが分かります。ExecStart=/usr/sbin/logrotate /etc/logrotate.conf
つまり、.timerユニットでタイミングを設定して、.serviceユニットで何を実行するのかを指定しているというわけですね。
では、いよいよこのユニットファイルをカスタムして、1時間に1回実行されるように変更したいと思います。
なお、ユニットファイルをカスタムする時は、以下の引用に言及されている通り/etc/systemd/system/ディレクトリ配下にunitファイルを作成します。
システムにインストールされるサービスは、/usr/lib/systemd/system/ ディレクトリーに保存されるデフォルトのユニットファイルと共に提供されます。システム管理者はこのファイルを直接変更できないため、カスタマイズは /etc/systemd/system/ ディレクトリーの設定ファイルに制限される必要があります。
また、unit名については.timerと.serviceとの間で統一する必要があります。
参考: systemd.timer(5) — Linux manual page(前掲)
For each timer file, a matching unit file must exist, describing the unit to activate when the timer elapses. By default, a service by the same name as the timer (except for the suffix) is activated. Example: a timer file foo.timer activates a matching service foo.service. The unit to activate may be controlled by Unit= (see below).
翻訳:
各タイマー ファイルには、タイマーの経過時にアクティブ化するユニットを記述する、一致するユニット ファイルが存在する必要があります。デフォルトでは、タイマーと同じ名前 (サフィックスを除く) のサービスがアクティブ化されます。例: タイマー ファイル foo.timer は、一致するサービス foo.service をアクティブにします。
以上2つの注意点をおさえたうえで、デフォルトのunitファイルをコピーします。
cp /usr/lib/systemd/system/logrotate.timer /etc/systemd/system/
cp /usr/lib/systemd/system/logrotate.service /etc/systemd/system/
OnCalendar=dailyをOnCalendar=hourlyに変更してみます。
参考: 時間指定方法について
https://takuya-1st.hatenablog.jp/entry/2020/04/24/032822
sed -i s/OnCalendar=daily/OnCalendar=hourly/ /etc/systemd/system/logrotate.timer
変更の反映にはdeamon reloadしてあげる必要がありますが、先に変更前のlogrotate予定時刻を確認しておきます。
[root@ip-10-0-2-46 ~]# systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Sun 2023-12-03 05:31:06 JST 2min 37s left Sun 2023-12-03 05:26:06 JST 2min 22s ago nm-cloud-setup.timer nm-cloud-setup.service
Sun 2023-12-03 05:59:39 JST 31min left Sun 2023-12-03 04:28:08 JST 1h 0min ago dnf-makecache.timer dnf-makecache.service
Mon 2023-12-04 00:00:00 JST 18h left Sun 2023-12-03 05:00:08 JST 28min ago logrotate.timer logrotate.service
Mon 2023-12-04 03:40:08 JST 22h left Sun 2023-12-03 03:40:08 JST 1h 48min ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
4 timers listed.
Pass --all to see loaded but inactive timers, too.
出力結果から、2023-12-04 00:00:00予定ということが分かりました。
変更を反映してみます。
systemctl daemon-reload
systemctl restart logrotate.service
変更反映後の予定時刻を確認してみます。
[root@ip-10-0-2-46 ~]# systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Sun 2023-12-03 05:31:06 JST 37s left Sun 2023-12-03 05:26:06 JST 4min 22s ago nm-cloud-setup.timer nm-cloud-setup.service
Sun 2023-12-03 05:38:08 JST 7min left Sun 2023-12-03 04:28:08 JST 1h 2min ago dnf-makecache.timer dnf-makecache.service
Sun 2023-12-03 06:00:00 JST 29min left Sun 2023-12-03 05:00:08 JST 30min ago logrotate.timer logrotate.service
Mon 2023-12-04 03:40:08 JST 22h left Sun 2023-12-03 03:40:08 JST 1h 50min ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
4 timers listed.
Pass --all to see loaded but inactive timers, too.
2023-12-03 06:00:00 予定となり、予定時刻が変更されたのが確認できました。
ただし、これでお終いではありません。
logrotate.timerはlogrotate.serviceをトリガーしますが、logrotate.serviceは実質的に
を実行しているだけでした。/usr/sbin/logrotate /etc/logrotate.conf
つまり、logrotate.timerのおかげで1時間に1回/usr/sbin/logrotateが実行されるようになりましたが、実際にログがローテーションされるかどうかは/etc/logrotate.conf(もしくは個別に設定している/etc/logrotate.d/ディレクトリ配下のファイル)の内容に依存しています。
そこでlogrotate.confの内容を確認してみます。
[root@ip-10-0-2-46 ~]# cat /etc/logrotate.conf
# see "man logrotate" for details
# global options do not affect preceding include directives
# rotate log files weekly
weekly
# 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 be also be configured here.
weeklyになっていますので、このままではlogrotateが実行されてもローテーションはされません。
そのためweeklyをhourlyに変更します。
sed -i s/weekly/hourly/ /etc/logrotate.conf
実際にログがローテされているか/var/log/messagesを例に確認してみます。
[root@ip-10-0-2-46 ~]# ls -lrt /var/log/messages*
-rw------- 1 root root 15324 Dec 3 05:59 /var/log/messages-2023120306
-rw------- 1 root root 351 Dec 3 06:00 /var/log/messages
ちゃんとできてましたね!!!
※/var/log/messagesのログローテについては、デフォルトで/etc/logrotate.d/rsyslogにおいて個別に追加設定されていますが、時間設定はされていません。デフォルトの設定を変更していない今回に限っては、/etc/logrotate.d/rsyslogの設定内容は関係ありません。
余談: anacronによるlogrotateの制御
systemdのteimerユニットによるlogrotateの制御についてみてきました。
しかし、よりよく理解するためには以前のやり方がどうであったか、比較の対象についても合わせて知ることが時として肝要かと思いますので、以下ではanacronでlogrotateを実行する場合について見ていきます。
anacronとは
manページには以下のように書かれてあります。
anacron(8) – Linux man page
Anacron is used to execute commands periodically, with a frequency specified in days. Unlike cron(8), it does not assume that the machine is running continuously. Hence, it can be used on machines that aren’t running 24 hours a day, to control regular jobs as daily, weekly, and monthly jobs.
参考:
https://linux.die.net/man/8/anacron
翻訳すると以下の通りです。
Anacron は、日単位で指定された頻度でコマンドを定期的に実行するために使用されます。 cron(8) とは異なり、マシンが継続的に実行されていることを前提としていません。したがって、24 時間稼働していないマシンでも使用して、定期的なジョブを日次、週次、月次のジョブとして制御できます。
このanacronですが、例えば、AmazonLinux2でもlogrotateを実行するために利用されています。
以下では、設定の内容を確認してみます。
Amazon Linux 2の場合
Amazon Linux 2のanacrontabを見てみると、1日1回、コマンドとして/etc/cron.dailyを実行する設定がなされてあります。
[root@ip-10-0-2-89 ~]# cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22
#period in days delay in minutes job-identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
7 25 cron.weekly nice run-parts /etc/cron.weekly
実際に、/etc/cron.dailyを見てみるとディレクトリになっており、その配下にlogrotateというファイルがあることが分かります。
[root@ip-10-0-2-89 ~]# ls -lrt /etc/cron.daily
total 12
-rwx------ 1 root root 219 Jul 27 2018 logrotate
-rwx------ 1 root root 208 Jul 27 2018 mlocate
-rwxr-xr-x 1 root root 618 Apr 29 2019 man-db.cron
さらにその中身を見てみると、設定ファイル/etc/logrotate.confを引数に、/usr/sbin/logrotateを起動するシェルスクリプトであることが分かります。
[root@ip-10-0-2-89 ~]# 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
つまり、Amazon Linux2においては、/usr/sbin/logrotateを起動するためのシェルスクリプトが日次で実行されるよう/etc/anacrontabによって定義されているということです。
ちなみにRHEL9を覗いてみると以下の通りになっており、anacrontab自体は存在しますが、cron.daily/ディレクトリ配下にはlogrotateのスクリプトが存在しません。
# anacrontabは存在するが...。
[root@ip-10-0-2-89 ~]# cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22
#period in days delay in minutes job-identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
7 25 cron.weekly nice run-parts /etc/cron.weekly
@monthly 45 cron.monthly nice run-parts /etc/cron.monthly
# logrotateスクリプトが存在しない。
[root@ip-10-0-2-46 ~]# ls -lrt /etc/cron.daily
total 4
-rwxr-xr-x. 1 root root 341 Oct 27 10:47 update-client-config-packages
もちろん、このようになっているのは、先述した通りRHEL9ではsystemdのtimerユニットを利用しているからですね。
さて、以上でsystemdとanacronによるlogrotateの相違点についても理解できたかと思います。
おわりに
いかがだったでしょうか。
それではまたお会いしましょう!!
あでゅー!!