Debian 9 (Stretch)のanacronについて

以前、サーバーとしてdebianを運用していた環境ではanacronは動いてませんでした。
基本的に電源を落とすことがないのでcronのみで大丈夫だったからです。

cronはタスクを定期実行するためのサービスです。
anacronはcronと同じように定期実行のサービスですが、常時電源が入っていることを想定していないPCのために、電源ONの際に本来実行すべきだったタスクを実行してくれます。

cronとanacronは別物ですが、cronからanacronを呼んだり、anacronからcron.dailyを呼んだりと切り離せない関係にあります。

ノートPCにdebianを普通にインストールしたらanacronも入っていたのですが、電源入れっぱなしだとcron.dailyが日付変更直後に動きました。
crontabの指定時刻は全然別の時間なのにです。
そこでanacronの仕組みを調査してみました。

まず/etc/crontabを確認してみると以下のようになっていました(一部のみ抜粋)

17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 3 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )

上の行はcron.hourlyは毎時17分に実行されるとなっており、これは特に問題ありません。
下の行は3時25分に/usr/sbin/anacronを実行し、失敗だった場合は/etc/cron.dailyを実行するとなっており、こちらも問題なさそうに見えます。

しかし実際には/etc/cron.dailyにあるタスクは0:05など日付が変わって少しして実行されるのです。
(logwatchのレポートが0時過ぎに届くので気付きました)

本来、負荷分散させるためにcronのdailyやweekly、monthlyは夜中から明方のランダムな時間にセットされます。
が、anacronが入っていると0時過ぎにdailyやweekly、monthlyが動き始め、負荷分散の意味がありません。
(サーバーはanacron使うなということでしょうが、調べ始めたので最後まで行きますw)

次にanacronの設定である/etc/anacrontabを覗いてみました。

# These replace cron’s entries
1 5 cron.daily run-parts --report /etc/cron.daily
7 10 cron.weekly run-parts --report /etc/cron.weekly
@monthly 15 cron.monthly run-parts --report /etc/cron.monthly

一番左の数字は何日おきに実行するか。
上から1日、7日、1カ月という風になっており、後ろのdaily weekl monthlyとも一致しています。
左から2番目の数字は遅延時間です。
例えば一番上だと5分遅延という設定になっています。
この遅延時間は5分後に実行されるということではなく、0秒~5分の間でランダムな時間で遅延するというものです。

ここまで見てanacronには実行時間の概念がないことに気付きました…
だから0時過ぎに/etc/cron.dailyが実行されるのか。

ちなみにanacronが実行されると/var/spool/anacron以下の
cron.daily、cron.weekly、cron.monthlyというファイルにそれぞれ実行した日付が書き込まれます。
その日付を参照して同じ日に2回、同じ週に2回など重複して実行されないようになっています。
(逆にいえば、この日付を変更して再起動すれば、即時実行させることも可能です)

anacronには実行時間の設定がないのか?と調べたところSTART_HOURS_RANGEという設定があることが分かりました。
早速/etc/anacrontabに設定してみることに。

START_HOURS_RANGE=3-22

これで3-22の間しかanacronは実行されないはず!
ですが、また0時過ぎに実行されてしまう事態に。

更に詳しく調べたら、debian、ubuntuなどではこの設定は効果がないとのこと…

困りました。
そもそもanacronはどこで実行されているのかを調べました。

どうもsystemdがtimerで行しているようです。
/etc/systemd/system/timers.target.wants/anacron.timer

上記のパスはシンボリックリンクで、実際のパスは以下になります。
/lib/systemd/system/anacron.timer

中身を見てみると以下のようになっています。
[Unit]
Description=Trigger anacron every hour

[Timer]
OnCalendar=hourly
RandomizedDelaySec=5m
Persistent=true

[Install]
WantedBy=timers.target

/lib/systemd/system/anacron.serviceが毎時ランダムの最大5分遅延で実行されるということです。
Persistent=trueはPCが起動した直後に実行するかどうかです。

なるほど、ではこのタイマー自体を指定時刻内でしか動かないようにすればいいのではないか、と思ったわけです。
調べると指定時間の設定をどう書けばいいのかが書いてありました。
systemd.time

書き方がちょっとわかりにくいですが「..」でレンジ指定、カンマ区切りで複数指定が出来そうです。
もちろんアスタリスクでワイルドカード指定も可能です。
レンジ指定はなんか上手く動かなかったので、最終的にカンマ区切りで指定することに。
朝の6時~23時まで毎時実行(それ以外の時間はanacronはタイマーで動かない)が以下の設定です。
(起動時即時実行は残しているので、対象外の時間でも起動したり再起動すれば実行されます)

[Timer]
#OnCalendar=hourly
OnCalendar=*-*-* 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23:00
RandomizedDelaySec=5m
Persistent=true

但し、cronはcrontabに書いた時刻に実行され、そこからanacronが呼び出されるようになっています。
なのでanacronが23:00~6:00まで動かなくても、crontabに書いてある時間にanacron経由でcron.dailyのタスクは実行されます。
仕組みを知れば理解できますが、何も知らないと非常に複雑です。

crontabからanacronが呼び出されてると思いますが、anacronの動作対象外の時間だとcron.dailyは動きませんでした。
タイマーの設定がここまで影響しないとは思うので、何か他で影響が出てるのではないかと思います。

やはりサーバー運用の場合はanacronを止めた方が分かりやすい気がします(笑)

コメントを残す

メールアドレスが公開されることはありません。