状況
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
設定名 | 値 | 説明 |
---|---|---|
Type | oneshot | 一度だけ実行する |
ExecStart | /usr/sbin/logrotate /etc/logrotate.conf | 実行するコマンドライン |
Nice | 19 | プロセススケジューリングの優先度 19 は最低 |
IOSchedulingClass | best-effort | 実行されたプロセスの I/O スケジューリング クラスを設定します。 |
IOSchedulingPriority | 7 | 実行されたプロセスの I/O スケジューリングの優先度を設定します。7 は最低 |
LockPersonality | true | システム コールをロックダウンして、カーネル実行ドメインがデフォルトまたはPersonality= ディレクティブで選択されたパーソナリティから変更されないようにします。 |
MemoryDenyWriteExecute | true | 同時に書き込み可能で実行可能なメモリマッピングの操作を禁止します。 |
PrivateDevices | true | 実行されたプロセスの新しいマウントをセットアップします。 |
PrivateTmp | true | 実行されたプロセス用に新しいファイル システムの名前空間を設定します。 |
ProtectClock | true | ハードウェア クロックまたはシステム クロックへの書き込みが拒否されます。 |
ProtectControlGroups | true | アクセス可能な Linux cgloup 階層は、ユニットのすべてのプロセスに対して読み取り専用になります。 |
ProtectHostname | true | 実行されたプロセスの新しい UTS 名前空間を設定します。 |
ProtectKernelLogs | true | カーネル ログ リング バッファへのアクセスは拒否されます。 |
ProtectKernelModules | true | 明示的なモジュールの読み込みは拒否されます。 |
ProtectKernelTunables | true | アクセスできるカーネル変数は、ユニットのすべてのプロセスに対して読み取り専用になります。 |
ProtectSystem | true | このユニットによって呼び出されるプロセスに対して読み取り専用でマウントします。 |
RestrictNamespaces | true | このユニットのプロセスの Linux 名前空間機能へのアクセスを制限します。 |
RestrictRealtime | true | 設定されている場合、ユニットのプロセスでリアルタイム スケジューリングを有効にしようとすると拒否されます。 |
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 | リアルタイムタイマーで毎日実行される |
AccuracySec | 1h | タイマー精度(消費電力最適化のための設定) |
Persistent | true | タイマーが非アクティブで実行されなかった場合にアクティブになった瞬間に実行される |
まとめ
過渡期だからなのか cron にも systemd にも両方設定があってややこしい
cron のスクリプトは systemd があるかないかしか検出しておらず事実上動かない仕様になっている。
mlocate などはインストール時に有効になるが logrotate は有効にならないようだ。
今後の大きな流れとして cron が systemd に統合されていくと思われるので書き方などに慣れておきたい。
おしまい