📝

CentOS Stream 9でlogrotateが動かないのを治す
March 22, 2023February 20, 2024
#CentOS#Develop#systemd

状況

logrotate が動いておらずディスクがいっぱいになってしまった。 構築時に設定していたが動作していなかったので原因を探った。

conf の間違いを探す

logrotate -d /etc/logrotate.conf

cron で実行しているスクリプトを叩いても実行されない

 /etc/cron.daily/logrotate

logrotate のコマンドを叩くと実行される

logrotate /etc/logrotate.conf

CentOS Stream 9 は systemctl で logrotate を実行するようになっている

bash -x /etc/cron.daily/logrotate
+ '[' -d /run/systemd/system ']'
+ exit 0

bash -x でデバックしてみると/run/systemd/system のディレクトリがあると終了するようになっている。 OS 的には systemd.timer を使ってほしいみたい。

# systemctl status *.timer|grep ena
     Loaded: loaded (/usr/lib/systemd/system/dnf-makecache.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/usr/lib/systemd/system/unbound-anchor.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/usr/lib/systemd/system/mlocate-updatedb.timer; enabled; vendor preset: enabled)
     Loaded: loaded (/usr/lib/systemd/system/certbot-renew.timer; enabled; vendor preset: enabled)

systemd には logrotate は登録なし

# systemctl enable logrotate.timer
Created symlink /etc/systemd/system/timers.target.wants/logrotate.timer → /usr/lib/systemd/system/logrotate.timer.
# systemctl start logrotate.timer

有効にしてスタートした。 スタートしないと再起動するまで有効にならないので注意

systemd timer

簡単な使い方

.timer ユニットに対応した.service ユニットが存在し動作する。 .service には[install]セクションは必要ない 別の service ユニットも動作させたい場合は Unit オプションを利用する。

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
設定名説明
Typeoneshot一度だけ実行する
ExecStart/usr/sbin/logrotate /etc/logrotate.conf実行するコマンドライン
Nice19プロセススケジューリングの優先度 19 は最低
IOSchedulingClassbest-effort実行されたプロセスの I/O スケジューリング クラスを設定します。
IOSchedulingPriority7実行されたプロセスの I/O スケジューリングの優先度を設定します。7 は最低
LockPersonalitytrueシステム コールをロックダウンして、カーネル実行ドメインがデフォルトまたはPersonality=ディレクティブで選択されたパーソナリティから変更されないようにします。
MemoryDenyWriteExecutetrue同時に書き込み可能で実行可能なメモリマッピングの操作を禁止します。
PrivateDevicestrue実行されたプロセスの新しいマウントをセットアップします。
PrivateTmptrue実行されたプロセス用に新しいファイル システムの名前空間を設定します。
ProtectClocktrueハードウェア クロックまたはシステム クロックへの書き込みが拒否されます。
ProtectControlGroupstrueアクセス可能な Linux cgloup 階層は、ユニットのすべてのプロセスに対して読み取り専用になります。
ProtectHostnametrue実行されたプロセスの新しい UTS 名前空間を設定します。
ProtectKernelLogstrueカーネル ログ リング バッファへのアクセスは拒否されます。
ProtectKernelModulestrue明示的なモジュールの読み込みは拒否されます。
ProtectKernelTunablestrueアクセスできるカーネル変数は、ユニットのすべてのプロセスに対して読み取り専用になります。
ProtectSystemtrueこのユニットによって呼び出されるプロセスに対して読み取り専用でマウントします。
RestrictNamespacestrueこのユニットのプロセスの Linux 名前空間機能へのアクセスを制限します。
RestrictRealtimetrue設定されている場合、ユニットのプロセスでリアルタイム スケジューリングを有効にしようとすると拒否されます。

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
設定名説明
OnCalendardailyリアルタイムタイマーで毎日実行される
AccuracySec1hタイマー精度(消費電力最適化のための設定)
Persistenttrueタイマーが非アクティブで実行されなかった場合にアクティブになった瞬間に実行される

まとめ

過渡期だからなのか cron にも systemd にも両方設定があってややこしい cron のスクリプトは systemd があるかないかしか検出しておらず事実上動かない仕様になっている。 mlocate などはインストール時に有効になるが logrotate は有効にならないようだ。 今後の大きな流れとして cron が systemd に統合されていくと思われるので書き方などに慣れておきたい。
おしまい

参考

https://www.timbreofprogram.info/blog/archives/1553



sakakinox

Written by sakakinox
Server enginier

Copyright © sakakinox.net 2021-2024.