世界を動かす技術を、日本語で。

午前2時と午前3時のcronジョブを避ける (2013)

概要

  • cronジョブ のスケジュール時刻に関する注意点
  • サマータイム(DST) による予期せぬ挙動のリスク
  • vixie-cron での具体的なトラブル事例
  • 回避策 やベストプラクティスの提案
  • 根本的解決策 への提言

cronジョブとサマータイムの落とし穴

  • 日曜日午前2時または3時 にcronジョブを設定しない注意喚起
  • サマータイム(DST) の切り替え時にジョブが異常動作するリスク
  • 他の曜日 でも、設定変更により日曜に移る可能性を考慮
  • 大半の場合は正常動作 だが、年2回のDST切り替えで問題発生
  • 具体例 :Linuxの vixie-cron で、DST開始時に3:00〜3:01の間ジョブが1秒ごとに約60回実行
  • 複数ジョブが重複実行 し、メール通知等で混乱発生の事例
  • 深刻な被害は回避 できたが、タスク内容によっては重大な障害につながる懸念

回避策とベストプラクティス

  • より高度なジョブスケジューラ (重複防止やタイムリミット指定可能)の導入検討
    • 例: systemd timers, Airflow, Fugue, Quartz Scheduler など
  • cronの普及度 を考慮し、現状では一部環境でcron利用が避けられない現実
  • サーバーのタイムゾーンをUTC に設定し、DSTの影響を排除する手段
  • 最も推奨 :サンデー午前2時・3時のcronジョブ設定自体を避ける運用ルール
  • 根本解決案 :世界的にサマータイム制度の廃止を提案

まとめ

  • cronジョブのスケジューリング はサマータイム切替時刻を避けることが重要
  • 運用ポリシー として、日曜午前2時・3時のジョブ設定禁止を徹底
  • より安全な運用 のためのツール導入やタイムゾーン設定の見直し推奨
  • 制度的課題 としてサマータイム廃止を望む声も存在

Hackerたちの意見

僕が働いてたところは、サーバーがUTCじゃなくてBSTに設定されてて、レポート用にcronジョブをめっちゃ使ってたんだ。これが年に2回、混乱を引き起こして、また年に2回ビジネスにその理由を説明しなきゃいけなかった。結局、修正される前に会社は潰れちゃったよ。ほんと、UTCを使った方がいいよ、特に理由がない限りはね。

「うちの顧客はUTCにいない」っていうのは、よくある説得力のある理由だよね。人々は一般的に、使用制限が夜中にリセットされることを期待してるから、UTCの真夜中じゃなくてさ。これらはしばしばバッチジョブの結果に暗黙的に結びついてるし。請求を含む金融関連のジョブも大きなカテゴリーだね。

Marin Softwareでは、各顧客ごとにサーバーを分けて、顧客が定義したタイムゾーンに設定してたんだ。もう終わりのないcronジョブの悪夢だったよ。今は彼らも破産しちゃった。最近、誰かが会社を再起動しようとしてるって聞いた。頑張ってほしいね。 https://x.com/Austen/status/1981904435539280324

特定の時間に何が起こったかのレポートが欲しいときは、そのレポートを現地時間で必要なんだ。僕は、24時間運用管理チームから毎日8時UK時間にいろんなことのステータスレポートをもらってる。つまり、先週は0700UTCで、今週は0800UTCに実行されたってこと。これは運用イベントやシフト変更に基づいてるんだ。他にも、シドニーで0630から1630現地時間で運用されてるシステムがあって、これによってUKのシフトパターンと重なるメンテナンスウィンドウが週によって変わるけど、システムがUK時間で2130-0730の時もあれば、2030-0630の時も、1930-0530の時もあるんだ。UTCが「答え」ってわけじゃないよ。時にはUTC時間で動かしたい時もあれば、現地時間で動かしたい時もある。火曜日と木曜日の午前10時ロンドン時間に定期的な会議があるんだけど、これは季節によって変わるからUTCに保存できないんだ。タイムゾーンを保存して、アクションを起こさなきゃいけないんだよ。

「本当に理由がない限り、みんなUTCを使おうよ。もしチーム全体が太平洋時間にいるなら、ログを読むときに難しい計算をしなくて済むように、PTに近い時間を使うよ。アメリカにいるなら、アメリカの時間がいいな。計算が楽だから。」

デスクにUTC時間のアナログ時計を置いてるんだ。ログを変換するのにすごく役立ってるよ。

公開/本番サーバーにはUTCを使ってるけど、クローゼットのラックにあるホームラボサーバーは全部ローカルタイムにしてる。これでホームラボサーバーの時間を把握しやすくなるんだよね。ただし、データベースの挿入や更新の日時は常にUTCで保存してる。

基本的にはそうだけど、意外と重要なケースが多いから一般化するのが難しい。例えば、金融業界は市場の時間や規制の理由で気にすることが多いんだよね。

それに、cronは使わない方がいいよ。もっと洗練されたスケジューラーをアプリに組み込むか、既製品を使った方がいい。

どうやら、キューバやエジプト、レバノンみたいに、DSTの変更が真夜中に行われるタイムゾーンがあるらしいから、そこも気をつけてね! https://mas.to/@mpirnat/115395859892135002

タイムゾーンのルールには、いろんな面白いことがあるよ。

え、DSTの変更が真夜中に起こらないタイムゾーンってあるの?それは初耳だわ。この記事がやっと理解できた。02:00と03:00が特別な理由が何か気になってたんだ。ブラジルでは子供の頃から00:00から01:00、00:00から23:00にDSTが変わるのが普通だったから。もしかして、他の国では02:00から03:00にDSTが変わるところもあるのかな?

それと、真夜中(00:00)にジョブを設定するのはやめた方がいいよ。誰も何日か分からなくなっちゃうから。00:01とかに設定した方がいいし、正直なところ、時間ちょうどにジョブを走らせるのもやめた方がいい。みんなその時間に始めるからね。01:45とか02:15に設定するのがいいと思うよ。(これらの提案は時間変更に関連してるわけじゃないけどね)

一般的には、cronジョブには変な時間を設定するようにしてる。バックアップはXX:13に始めて、分析スクリプトはXX:23、データエクスポートはXX:42とかね。これで「なんで23:23にシステムがおかしくなるの?」って疑問が簡単になるんだ。

でも、イギリスの鉄道ソフトウェアに関わってるなら、公式には日が2:00amに始まって1:59amに終わるからね :)

僕は、時間のトップでcronを避けるようにしてるんだ。これが理由の一部でもあるし… あと、(共有サーバーやサーバーレスのインフラでは)もっと多くの人が「時間ちょうど」にcronを設定してると思うから、リソースの競合が増えるんだよね。それに、できるだけ「午前4時以降」や「真夜中前」を狙うようにしてる。この範囲を避けるためにね。

その戦術を少しずつ改善するために、systemdにはRandomizedDelaySecがあって、スケジューリングの競合の可能性を減らす便利な方法なんだ。

cronのトリックの一つは、crontabの実際のコマンドの前に「sleep $(( $(od -N1 -tuC -An /dev/urandom) % 60 ))m ;」を追加すること。これで0分から59分の間でランダムに遅延させることができる。

前にも話したことがあるけど、ここではめっちゃ関係ある話だよ。redditのサーバーを全部セットアップしたとき、全部アリゾナ時間にしたんだ。アリゾナは夏時間がなくて、カリフォルニア(みんながいたところ)とは5ヶ月間だけ1時間の時差があって、残りの期間は同じ時間になる。UTCは使わなかったんだけど、生のログを読むときに8を引くのは1を引くよりずっと難しいからね。今はUTCを使ってるけど、グローバルなチームがいるし、表示するタイムゾーンを自動で変えられるログリーディングインターフェースがあるから納得だよね。

コンピュータは色々できるよ。ログを読むためのUXを作って、自動でログをパース/変換してローカル時間を表示するようにすればいいんじゃない?

これは賢いことじゃなくて、次にあなたの「スマート」なトリックを維持する人にとって驚きだよ。UTCに切り替えてくれて本当に良かった、みんなが期待してることだからね。

「生のログを読むときに8を引くのは1を引くよりずっと難しいからUTCは使わなかったんだ。ここで重要なのは、日付が同じままなんだよね!UTCを直感的に解読するのには慣れてきたけど、その部分は時々イライラすることもある。」

似たような早い決定の後始末をしなきゃいけなかったことがあって、すごく大変だった。みんな、全体でUTCを使ってくれ!いつか誰かがあなたの残したゴミを片付けなきゃいけなくなるかもしれないから。

Javaではjvmレベルでデフォルトのタイムゾーンを設定できて、うちの組織ではみんな好きなTZを設定してたんだ。大体PSTが多かったけど、アプリのログとシステムログでタイムスタンプが違ってて、誰かが特定のDBカラムを「yyyy-mm-dd hh:mm:ss」形式の文字列にしなきゃいけないって決めたんだ。複数のシステムのログを特定の時間にデバッグするのがどれだけ混乱したか想像できるでしょ。最終的には、あるリーダーが「アプリはまずPSTに設定するべき」って言って、DBカラムも特に必要がない限りPSTと見なすことにしたんだ。

これに関連するイライラポイント: 表示タイムゾーンを選べるログ表示のWeb UIが、UTCを選ぶと絶対にブラウザの言語設定から12時間制か24時間制を決めようとするのが本当に嫌。少なくとも、UTCを選ぶことは「YYYY-MM-DDと24時間形式を解析できる」っていう強いヒントになるはずなんだけど。

アリゾナは気まぐれでタイムゾーンの定義を変えるかもしれないから、これもちょっとリスキーだね。俺は大手カレンダーアプリのエンジニアなんだけど、こういうことが世界中でどれだけ頻繁に起こるか、時には短期間の通知で(数週間前)あるのが本当に驚きだよ。いつも頭が痛くなる。

午前2時はプネのオフィスでは午後の真ん中なんだよね。24時間365日運営してるのに、全員がPSTにいると大変なことになるよ。でも、2013年から変わったことの一つは、ほとんどの人がオートスケーリングを使ってるってこと。特定の時間帯には補助サーバーのキャパシティがあって、静かな昼間に定期的なプロセスをスケジュールするのが理にかなってたけど、今は問題が起きた時のバス番号の可用性がもっと重要になってる。だから、DSTの心配よりもそっちが優先されるんだよね。低トラフィックの時間帯を探すんじゃなくて、ピークトラフィックを避けるのがメイン。俺が改良したバッチ処理システムは、元の設計のCPU時間の7%しか使わないんだけど、クローラーが使うのと同じ固定並列処理のトリックを使ってるから、サイトが落ちることはない。常にkリクエストを飛ばしてて、サーバーの応答が速ければ、もっとリクエストを秒間に出すんだ。もし生産サービスに余裕があれば、そのジョブは10分で終わる。応答が遅いと15分かかる。リトルの法則を逆転させて、サーバーの数を固定して、時間を変えてるんだ。もっとサーバーを立ち上げるのに10分のかなりの時間がかかったのは残念だったな。そうすれば5分にできたかもしれないのに(元々は30分以上かかってたし、35分に近づいてた)。一度、完全にバンブーエージェントに移そうとしたけど、リソースが足りなかった。もしCPUが2倍のエージェントがあれば、サービスをシャットダウンできたのに。バンブーエージェントをアップグレードする方が、そのサービスを運営するよりもコストがかからなかったって気づくまで、俺はドアを出ようとしてた。みんなのビルドも早くなったはずなのに。無駄な経済だね。

あるいは、可能であればサーバーのタイムゾーンをUTCに設定して、夏時間の変更が全く起こらないようにするのも手だね。でも、これがみんなが本当に望んでることなのかな?今、俺は夏時間を考慮しないクラウドスケジューラーでデプロイされた定期プロセスに取り組んでるんだけど(時間入力の横に「夏時間は考慮しません」って書いてある)。みんな、毎年の365日、仕事が始まる4時間前にジョブを実行してほしいって言ってる。日曜日に変更しないと、エンドユーザーが期待する時間にジョブが完了しないことになる。また3月にも変更が必要だ。何か見落としてるのかな?

これを「レーキ踏み」と呼んでるんだけど、同じ場所を行ったり来たりしてる限り、全然気づかないよね。

記事は主にcronスケジューラーを使って、特にトラフィックが少ないから日曜日の午前2時に物事を実行することについて話してる。これらのcronジョブは「いつ実行されても構わないけど、問題を引き起こす可能性は最小限にしたい」って感じ。君のユースケースは全然違う。「この時間にこのジョブを実行したい」ってことだから、君に適用される唯一の教訓は、cronユーティリティがDSTの切り替え時に変な動作をするかもしれないってこと。君のクラウドプロバイダーがそれを基にしてるかどうかはわからないから、全く関係ないかもしれない。

みんな、仕事が始まる4時間前にジョブを実行してほしいって言ってる。こういう繰り返しイベント、特定の場所の人間に関連するものは、「どこでもUTCを使えばいい」ってアドバイスに関する最も一般的な問題だ。でも、実際には全く対立してないんだ。ただ、もう一つの間接的なレイヤーが必要なだけ。例えば、これは早朝の06:30に始まる工場だとしよう。そうすると「4時間前」はDSTの影響を受ける時間帯に入る。「現地時間で02:30に実行」は避けるべきだ。なぜなら、「春に進める」日には02:30が存在しないから。時計は01:59:59から03:00:00に飛ぶ。[0] 同様に、「現地時間で01:30に実行」も避けるべきだ。なぜなら、「秋に戻す」時にそれが2回発生するから。理想的には、繰り返しを特定の場所に関連付けて、その繰り返しがUTC時間で発生する個々のイベントを生成することを考えたい。例えば、工場がサンフランシスコにある場合、繰り返しは「現地時間で02:30に1日1回」と指定されるかもしれない。そうすると、UTC時間での日々のイベントが生成される。夏の間は09:30Z、冬の間は10:30Zになる。また、スケジューラーが「1日1回」の制約を理解できるようにしたい。だから、「現地時間で01:30に1日1回」のタスクは、同じ日に2回発生する01:30現地時間があっても、1つのデイリーイベントだけを生成する。そうすれば、個々のイベントはすべてUTCにあり、システムクロックもそうだから、実際の実行時間に曖昧さはない。繰り返しの複雑さは、より高いレベルで処理される。もしこの問題のさらに難しいバージョンが欲しいなら、サンフランシスコのチームとロンドンのチームが毎週月曜日の午前8時(SF)/午後4時(ロンドン)にZoomミーティングを持つと想像してみて。どちらかの場所が繰り返しを「所有」する必要がある。なぜなら、イギリスはアメリカとは1〜3週間ずれて時間変更を行うから[1]、8時間の時差が単純ではない週ができるんだ。[0]: https://www.timeanddate.com/time/change/usa [1]: https://www.timeanddate.com/time/change/uk

冗長に実行されるcronジョブは、私たちの問題の中で最も小さいものだよ。夏時間の調整日には死亡者やER訪問が急増するんだ。[1] 夏時間は廃止すべきだ。

夏時間は間違いだったし、廃止すべきだ。何の問題も解決せず、ただ問題を生むだけ。しかも、誰かが利益を得るような問題ではなく、みんなにとって単なる時間の無駄。冬時間に固定して、全ての労働時間を一度で夏時間のように調整すればいい。例えば、ビジネスが午前7時に開いて午後10時に閉まるのを、午前6時に開いて午後9時に閉まるようにする。調整期間はあるけど、年に2回すでに調整期間があるから、何も失われない。なぜ労働時間を夏時間に合わせるかって?仕事が終わった時にもっと日光が欲しいから。特に冬の間はね。完全に逆だよ。時計を調整するなら、冬にもっと日光が得られるように調整すべきで、逆にするべきじゃない。仕事に行く時に明るくなってるかどうかなんて気にしない。9時間も屋内にいるのに、自由になった時に日光が欲しいんだ。

じゃあ、時計の変更をやめて、開店と閉店の時間を全部ずらすってこと?それで結局同じ効果になるってことだよね。で、DSTを廃止したいって言ってるけど、コメントの最後では冬にももっとずらしたいって言ってる。君の考えについていくのが難しいし、実際に何がしたいのかよくわからないよ。

一年中標準時間だと、6月の9時にめっちゃ明るいって問題があるよ。小さい子供たちは「もう寝る時間だよ」って言っても「まだ明るいじゃん!」って困っちゃう。DSTを廃止するのには賛成だけど、どっちを選ぶべきかは迷うな。どちらにもトレードオフがあるし。

ちょっと小さいことを言いたくはないけど、「冬時間」なんてないよ。標準時間と夏時間、つまり「デイライトセービングタイム」だけだからね。「冬時間」って言葉を初めて聞いたのは、DSTを永久に続けるか、みんなが「冬時間」を常に保ちたいかを話し合ったときだったよ。そりゃあ、冬の何かをずっと持ち続けたい人なんていないよね。 ;)

それならUTCを使って、コード内でタイムゾーンを使うのをやめればいいんじゃない?いくつかのケースでは簡単じゃないのはわかるけど、UTCには理由があるからね。