cron で「13 日の金曜日」を書くと何が起きるか

Kairos

素直に書いてみる

「13 日の金曜日に何かを実行したい」。crontab を開く。フィールドは分・時・日・月・曜日。

0 0 13 * 5

毎月 13 日、0 時、金曜日の。読める。書けた。デプロイ。

2026 年、このジョブは 61 回発火する。意図は 3 回だった。

種明かし

crontab(5) の仕様にこうある——日(day of month)と曜日(day of week)の両方を指定した場合、 どちらかが一致すれば実行される。つまり AND ではなく OR0 0 13 * 5 は「13 日の金曜日」では なく「毎月 13 日、およびすべての金曜日」。2026 年なら金曜 52 本+13 日が 12 回、重なる 3 日を 引いて 61 回。

バグではない。1970 年代からの仕様であり、マニュアルにも書いてある。書いてあることと、初見で そう読めることは別の話だが。

この「事故」を式で書いてみる

Kairos は列の代数なので、cron が実際にやっていることをそのまま書ける。

@JP
fridays    = everyDay |> filter(d => weekday(d) == Fri)
thirteenth = everyDay |> within(month) |> nth(13)

fridays | thirteenth     # cron がやっていること(和)

2026 年で実体化すると 61 点。一方、意図していたのはこれ。

fridays & thirteenth     # 意図していたこと(積)
2026-02-13
2026-03-13
2026-11-13

| と &1 文字の差が 61 回と 3 回の差になる。そして cron の悲劇の正体はこう要約できる—— cron には「かつ」を書く場所がない。フィールドの並びに二つの条件を置いた瞬間、接続詞の選択権は 仕様側にあり、答えは OR と決まっている。

他の道具の成績表

  • Quartz — day-of-month と day-of-week のどちらかに必ず ?(指定なし)を書く決まり。 つまり両方は指定できず、「13 日の金曜日」は一本の式では書けない。OR で裏切る cron より潔い。
  • RRULE (iCalendar) — FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13。書ける。BYDAY と BYMONTHDAY の 同時指定は AND に定義されている。カレンダー規格の面目躍如。
  • systemd timer — OnCalendar=Fri *-*-13。書ける。曜日指定はフィルタとして AND される。 cron の後継を名乗るだけのことはある。

まとめると「かつ」を持っているかどうかが分水嶺。ジョブ起動系の古株ほど持っていない。

手元で確かめたい人へ

ブラウザで動く Playground を用意した。上の式を仕込んだリンクがこれ—— 13 日の金曜日を Playground で評価する。 開いたら & を | に書き換えて再評価してみてほしい。61 点に化ける瞬間が cron の気持ちである。 インストール不要・式はブラウザの外に出ない。

おわりに

「13 日の金曜日」自体は実務で使わない。だがこの構造——独立した二つの条件の交わり——は 「営業日かつ月末週」「五十日かつ平日」のような形で業務のあちこちに出てくる。条件を列にして & で交差させる、という書き方の練習台として、13 日の金曜日はよくできた不吉さだと思う。

Kairos の結合子の話は教本 2 級・第 5 章に まとめてある。言語本体は kairos-lang.org

次回は運用の話を一本——「サーバーが 30 分死んでいた間の発火はどこへ行くのか」。cron を使って いた頃、あれはどこへ行っていたのだろうか。

コメント

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