systemd-analyze calendarで次の実行時刻を予測する ― OnCalendarとPersistentの違い

Linux・CLI・DevOpsカテゴリを表すパンダのイラスト Linux・CLI・DevOps

この記事について
この記事は、生成AIを活用した自動生成フローで作成しています。systemd-analyze、systemd.timer、systemd.timeの公式マニュアルを確認し、次の起動時刻を読み取り専用で調べるサンプルを作成しました。対象Ubuntuでの実行確認はまだ行っていません。

検証ステータス:📘 systemd公式マニュアル確認済み・Ubuntu実機未確認

Ubuntuで*.timerを設定したのに、想定した時刻にサービスが動かないことがあります。よくある勘違いは、カレンダー式が正しいことと、実際のタイマーが有効になっていることを同じと考える点です。

systemd-analyze calendarを使うと、タイマーを有効化せずに、OnCalendar=と同じ形式の式を解釈し、次の実行予定日時を一覧できます。さらにPersistent、AccuracySec、タイムゾーンを分けて確認すると、見落としを減らせます。

最小実験:2時間ごとの時刻を計算してみる

例えば、日本時間で00:05、02:05、04:05、…、22:05に実行したい場合、カレンダー式は次のように記述します。

[Timer]
OnCalendar=*-*-* 00,02,04,06,08,10,12,14,16,18,20,22:05:00 Asia/Tokyo
Persistent=false

これは設定例です。まだサービスやタイマーは有効にしません。

Ubuntuで次のコマンドを実行してください。

systemd-analyze calendar --iterations=8 \
  '*-*-* 00,02,04,06,08,10,12,14,16,18,20,22:05:00 Asia/Tokyo'

この操作ではsudoは不要で、WordPressなどの本番サービスも起動しません。日時の構文を解析し、次の8回の発火予定を計算するだけです。出力される年月日や曜日は、実行する時点によって変わります。

Original form: ... Asia/Tokyo
Normalized form: ...
Next elapse: (次の偶数時05分に相当する日時)
Iter. #2: (さらに2時間後)
...

※上記は表示項目の例示であり、実機ログの転記ではありません。

1か所変えて観察する

確認したいのは、毎時00分と2時間に1回の違いです。

# 毎時00分

systemd-analyze calendar --iterations=4 \
  '*-*-* *:00:00 Asia/Tokyo'

# 偶数時05分

systemd-analyze calendar --iterations=4 \
  '*-*-* 00,02,04,06,08,10,12,14,16,18,20,22:05:00 Asia/Tokyo'

両者の出力でNext elapseとIter. #2の間隔を比較します。前者は約1時間間隔、後者は約2時間間隔で計算されるはずです。これで、意図したスケジュールが式に落ちているかを、実サービスを動かさず確認できます。

Daily-Code-Samplesのスクリプトには、この確認をひとまとめにしたpreview-calendar.shを保存しました。任意のカレンダー式を引数として渡せます。

bash preview-calendar.sh
bash preview-calendar.sh '*-*-* 08:30:00 Asia/Tokyo'

「予定時刻が正しい」と「実際に動く」の違い

調べたいこと確認するもの分かること
カレンダー式の文法systemd-analyze calendar次回の発火予定
タイマーが登録・有効化済みかsystemctl list-timers --all現在管理されているタイマー
Unitの定義systemctl cat 名前.timerOnCalendarやPersistent等の設定
直近のサービス実行結果systemctl status 名前.service現在のプロセス状態と直近の実行
エラーの詳細journalctl -u 名前.serviceサービスのログ

カレンダー式が正しくても、timerがinactiveやdisabledなら、通常は予定どおり自動実行されません。またタイマーが動いても、サービス本体が失敗すれば処理は完了しません。

次の操作は既存設定を読み取るだけです。調査対象は自分が管理する名前に置き換えてください。

systemctl list-timers --all --no-pager
systemctl cat example.timer
systemctl show example.timer \
  -p ActiveState -p Unit -p NextElapseUSecRealtime -p LastTriggerUSec
journalctl -u example.service --no-pager -n 30

見つからないUnitを指定してもよいわけではありません。実際のtimer名を確認してから読み替えます。閲覧権限によっては一部のJournalを読めない場合があります。

Persistentをtrueにすると、何が起こる?

Persistent=trueは、OnCalendarに基づくタイマーが停止・未稼働だった間に発火予定を逃した場合、再起動時などに追いつく動作を可能にする設定です。

設定主な意味実務上の注意
Persistent=false停止中の発火を無条件に取り戻す設定にしない公開・課金処理などの予期しない遅延実行を防ぎやすい
Persistent=true停止中に逃したカレンダー実行の追いつきを可能にする復旧直後に想定外の実行が起きないか確認
AccuracySec発火時刻の精度ウィンドウ予定時刻ぴったりではない場合がある

誤解しやすいのは、Persistent=trueにすれば「逃した分を1件ずつ全部再実行する」と思ってしまうことです。これは保証されません。タイマーはサービスを起動する仕組みであり、処理対象キューの未処理件数や公開の重複まで管理しません。

例えば2時間ごとにブログを1本投稿する場合、サーバーが12時間停止していたからといって、過去の6回分を一括で投稿するのは危険です。タイマーには遅延発火を制限する設定を使い、アプリ側で「当日分だけ」「この2時間枠では最大1本」を検査する必要があります。

タイムゾーンが違う場合

OnCalendar=*-*-* 08:30:00とだけ書いた場合、ホストのタイムゾーン設定が影響します。クラウドサーバーがUTCの場合、日本で見た08:30と一致しません。

timedatectl
date '+%Y-%m-%d %H:%M:%S %Z'
systemd-analyze calendar '*-*-* 08:30:00 Asia/Tokyo'

カレンダー式にAsia/Tokyoと書くことで、時刻の基準を明示できます。ただし、サーバーの時計の同期状態そのものが不正確なら、カレンダーの解釈が正しくても実際の動作がずれます。

AccuracySecとサービス処理時間

OnCalendarに時刻を指定しても、AccuracySecの精度幅やサービスの起動待ちなどで、指定した秒と完全一致する保証はありません。一般的なLinuxの性能問題だけではなく、Unitの設定も確認してください。

また、同じサービスが起動中かどうか、サービス実行にどれだけ時間がかかるかも運用の重要な条件です。タイマー側の予定が2時間間隔でも、アプリが無制限に再試行する設計なら2時間に1回の処理上限にはなりません。

時刻制御=timer、対象の妥当性=アプリ、実行結果=ログやDBと責任を分けることで原因を追いやすくなります。

実務で確認したい5項目

  1. OnCalendarをsystemd-analyze calendarで評価できるか。

  2. タイムゾーンを明示しているか。

  3. timer自体が有効で、次の予定時刻を持つか。

  4. PersistentとAccuracySecが意図した振る舞いか。

  5. 発火後のserviceの終了状態・ログまで照合したか。

この順に確認すれば、「時刻指定が間違っている」「タイマーが無効」「サービスが異常終了」「実際の業務処理は0件だった」という異なる原因を分けられます。

一次情報

文書情報

記事タイトル
systemd-analyze calendarで次の実行時刻を予測する ― OnCalendarとPersistentの違い
作成日
更新日
Source URL
https://papanda925.com/?p=18071

ライセンス: 本記事のうち、当サイトが権利を有する本文・自作図表は、特記なき限り CC BY 4.0 で利用できます。生成AIを活用して作成・編集した内容を含みます。コードについて、別途ライセンス表示またはリンク先GitHubリポジトリのライセンスがある場合は、その条件を優先します。引用・第三者資料・画像・商標等は本ライセンスの対象外です。 利用ポリシー

タイトルとURLをコピーしました