systemdタイマー
前のレッスンでは cron が入っておらず実機で試せませんでしたが、この機械では systemd タイマーが本当に動きます。systemctl list-timers を打てば apt-daily.timer などが現に動いているのが見えます。定期実行の感覚は、ここで手を動かしてつかんでください。
「いつ」と「何を」が別のファイルに分かれる
cron では1行に「いつ」と「何を」の両方を書きました。systemd はこれを2つに分け、いつ実行するかを .timer の OnCalendar などに、何を実行するかを .service の ExecStart に書きます。
拡張子より前の名前を揃えるのが基本です。backup.timer は既定で backup.service を起動します。別の名前のサービスを起こしたいときだけ、[Timer] セクションに Unit= を書いて明示します。
置き場所は、管理者が自分で作るユニットなら /etc/systemd/system/ です。パッケージ提供のものは /lib/systemd/system/ にあり、同名を /etc/systemd/system/ に置くとそちらが優先されます。
サービス側は [Unit] に Description=、[Service] に Type=oneshot と ExecStart= を書きます。oneshot は一度走って終わる処理を表し、付けないと systemd がプロセスの終了を異常とみなすことがあります。タイマーから起動されるサービスには [Install] を書かず、enable もしません。起動はタイマーに任せるからです。
OnCalendar は 年-月-日 のあとに 時-分-秒
基本の形は曜日と年-月-日と時-分-秒です。曜日は省略でき、* は cron と同じく「すべて」です。
| 書き方 | いつ |
|---|---|
*-*-* 03:00:00 | 毎日 3時 |
*-*-* *:00:00 | 毎正時 |
Mon..Fri *-*-* 09:00:00 | 平日の 9時 |
*-*-* *:0/15:00 | 15分おき |
hourly daily weekly monthly yearly という短縮語も使えます。書式に自信がないときは次のコマンドで確かめられます。次に実行される時刻まで出るので、覚え違いをその場で見つけられます。
ターミナル
systemd-analyze calendar 'Mon..Fri *-*-* 09:00:00'タイマー側は [Timer] に OnCalendar= を、[Install] に WantedBy=timers.target を書きます。この WantedBy は決まり文句で、無いと enable しても起動時に有効になりません。
出来事からの経過時間でも指定できる
絶対時刻ではなく、ある出来事からの経過時間でも指定できます。OnBootSec= は起動から、OnActiveSec= はタイマーが有効になってから、OnUnitActiveSec= は対象サービスが最後に起動してから、OnUnitInactiveSec= は最後に終了してからの経過時間です。
OnBootSec=5min と OnUnitActiveSec=1h を組み合わせると、起動5分後に初回、その後は1時間おき、という動きになります。cron には無い表現で、起動直後の混雑を避けたいときに使います。
また、電源が入っていなくて飛んだ回を取り返したいときは Persistent=true を書きます。cron では anacron が要りましたが、systemd はこの1行です。最後に実行した時刻が記録され、次の起動時に本来なら実行されているはずだったと判断されればすぐ走ります。
enable は次回から、start は今すぐ
ファイルを置いただけでは systemd はそれを知りません。読み直させてから有効にします。
ターミナル
systemctl daemon-reload # ユニットファイルを読み直す
systemctl enable --now sample.timer # 起動時に有効化し、いま起動もする
systemctl list-timers --all # 停止中を含めてタイマーの一覧enable は次回の起動から、start はいま、--now は両方、という区別は必ず問われます。有効にするのは .timer のほうで、.service を enable するのではありません。
実行結果は journald に集まります。cron のようにメールの設定に左右されず、journalctl -u sample.service のようにユニット名で絞り込めるのが利点です。
試験で狙われるところ
.timer と .service は対で、.timer だけでは何も実行されません。有効化するのは .timer のほうです。ユニットファイルを置いたら daemon-reload が要ります。Persistent=true は取りこぼしの救済であって、遅延実行の指定ではありません。