伝統的に、cron/atq によってタイマー・スケジュール実行は管理されています。
現代のLinuxでは、systemd.timer が追加されています。いまのLinuxでは両方が存在します。
両方が存在するために、タイマーの設定ファイルが systemd.timer
/ cron
に同時に存在しています。
デフォルトのcron を見る。
takuya@:~$ ls /etc/cron.* /etc/cron.d: anacron certbot e2scrub_all php popularity-contest /etc/cron.daily: 0anacron apt-compat cracklib-runtime exim4-base man-db popularity-contest apache2 automysqlbackup dpkg logrotate mlocate /etc/cron.hourly: /etc/cron.monthly: 0anacron /etc/cron.weekly: 0anacron man-db
デフォルトの systemd.timerを見る。
takuya@:~$ systemctl status *.timer | grep enabled Loaded: loaded (/lib/systemd/system/phpsessionclean.timer; enabled; vendor preset: enabled) Loaded: loaded (/lib/systemd/system/anacron.timer; enabled; vendor preset: enabled) Loaded: loaded (/lib/systemd/system/man-db.timer; enabled; vendor preset: enabled) Loaded: loaded (/lib/systemd/system/apt-daily-upgrade.timer; enabled; vendor preset: enabled) Loaded: loaded (/lib/systemd/system/apt-daily.timer; enabled; vendor preset: enabled) Loaded: loaded (/lib/systemd/system/e2scrub_all.timer; enabled; vendor preset: enabled) Loaded: loaded (/lib/systemd/system/exim4-base.timer; enabled; vendor preset: enabled) Loaded: loaded (/lib/systemd/system/logrotate.timer; enabled; vendor preset: enabled) Loaded: loaded (/lib/systemd/system/fwupd-refresh.timer; enabled; vendor preset: enabled) Loaded: loaded (/lib/systemd/system/fstrim.timer; enabled; vendor preset: enabled)
思い切り、被ってないか?
2つを見比べると、少し気づいたことがあります。同じ名前の設定ファイルが存在します。anacron とか logroatateとか。
両方に設定が存在するもの
これらは、systemdにもcron にも登場します。つまり被ってます。
cron だけにあるもの
- apt-compat
- cracklib-runtime
- apache2
- automysqlbackup
- dpkg
- mlocate
systemd だけにあるもの
- fstrim
- fwup-refresh
被ってるものはどうなってるのか
被っていたら、正しくジョブが実行されないはずです。どうなってるのでしょうか。
anacron の例
よくこれで、重複実行されないよね。とおもったので調べました。
anacrom.timer の中身
[Unit] Description=Trigger anacron every hour [Timer] OnCalendar=*-*-* 07..23:30 RandomizedDelaySec=5m Persistent=true [Install] WantedBy=timers.target
timer 実体は anacron.service にありますね。 service/timer のペア運用を知らないと気づかないね、初見殺し。
takuya@:~$ cat /lib/systemd/system/anacron.service [Unit] Description=Run anacron jobs After=time-sync.target # By default, anacron will not run when no AC power is connected to system. # If you are using systemd and want to run anacron even when running on # battery, you should create the following file with the specified content # and then call "systemctl daemon-reload": # /etc/systemd/system/anacron.service.d/on-ac.conf: # [Unit] # ConditionACPower= # See /usr/share/doc/anacron/README.Debian for detailed information. ConditionACPower=true Documentation=man:anacron man:anacrontab [Service] EnvironmentFile=/etc/default/anacron ExecStart=/usr/sbin/anacron -d -q $ANACRON_ARGS IgnoreSIGPIPE=false KillMode=mixed # Use SIGUSR1 to stop gracefully KillSignal=SIGUSR1 [Install] WantedBy=multi-user.target
そしてこれが、cron.d
takuya@:~$ cat /etc/cron.d/anacron # /etc/cron.d/anacron: crontab entries for the anacron package SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 30 7-23 * * * root [ -x /etc/init.d/anacron ] && if [ ! -d /run/systemd/system ]; then /usr/sbin/invoke-rc.d anacron start >/dev/null; fi
cron.d/anacron では /run/systemd/system のチェックし、cronは無視される。具体的には、systemd-initがpid=1環境であれば 、cron では実行スキップ
互換性重視のために、ファイルを残している。そのような意図が見えます。
動かないけど、cronは起動するよ
でも、これってcron 自体は実行起動しますよね。testコマンドだけで負荷もないから気にしないけど。
e2scrub の場合
systemdが存在したら実行するようです。
でもこれも、cron 自体は起動しますよね?負荷は気にはならないけど、実行されるという事実が気になる。
takuya@:~$ cat /etc/cron.d/e2scrub_all 30 3 * * 0 root test -e /run/systemd/system || SERVICE_MODE=1 /usr/lib/x86_64-linux-gnu/e2fsprogs/e2scrub_all_cron 10 3 * * * root test -e /run/systemd/system || SERVICE_MODE=1 /sbin/e2scrub_all -A -r
mlocate の場合
mlocate の場合は etc/cron.daily
にあるので単純にスクリプトです。
cron の中身不要じゃね?
消したい・・・消したいけど、dist-upgrade
時に /etc/の中身変わってるよと聞かれるのがうざい。
systemd timer より、cron.dailyは可読性がいい。
systemd timer でみるより、/etc/cron.daily/logrotate
のほうが可読性が高く、何をしているのかよく分かる。
#!/bin/sh # skip in favour of systemd timer if [ -d /run/systemd/system ]; then exit 0 fi # this cronjob persists removals (but not purges) if [ ! -x /usr/sbin/logrotate ]; then exit 0 fi /usr/sbin/logrotate /etc/logrotate.conf EXITVALUE=$? if [ $EXITVALUE != 0 ]; then /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]" fi exit $EXITVALUE
mlocate は実行されないかも?
mlocate は、cron にだけ存在する。しかし、cron.daily/mlocate
ではsystemd側では動作しない。
mlocate は systemd では mask されている。
takuya@:~$ sudo systemctl status mlocate.service ● mlocate.service - Update a database for mlocate Loaded: loaded (/lib/systemd/system/mlocate.service; static) Active: inactive (dead) Docs: man:updatedb.mlocate(8) man:updatedb.conf(5) takuya@:~$ sudo systemctl status mlocate.timer ● mlocate.timer Loaded: masked (Reason: Unit mlocate.timer is masked.) Active: inactive (dead) Trigger: n/a
しかし、cron.daily
では mlocate は systemd環境下で何も実行しないよう構成されていました。
takuya@:~$ cat /etc/cron.daily/mlocate #! /bin/bash set -e # skip in favour of systemd timer if [ -d /run/systemd/system ]; then exit 0 fi # 中略 flock --nonblock /run/mlocate.daily.lock $NOCACHE $IONICE nice /usr/bin/updatedb.mlocate
cron記述では、systemdを優先する条件分岐があり、systemd.timerではマスクされる。これでは、何も実行されませんね。どうなってるのでしょうか。
タイマーは見直したほうがいい。
systemd信用できない。