Cronジョブ失敗アラート:定期ジョブが止まったら電話を鳴らす

Cronジョブは静かに失敗します。失敗や実行漏れを検知し、数秒以内にプッシュ通知や電話アラートを受け取る3つの確実なパターンを解説します。

目次

Cronジョブの失敗が危険なのは、何も起きないからです。エラーページもクラッシュもユーザーからの苦情もなく、あるのは3週間前に静かに止まっていたバックアップ、送信されなかったレポート、ディスクが満杯になるまで放置されたクリーンアップスクリプトだけ。気づいたときには本番環境が倒れています。

Cron自体にはアラート機能がありません。ジョブがエラーで終了しても、cronは何もしません。予定時刻にサーバーがダウンしていればジョブはそもそも実行されず、実行されなかったことを示す痕跡すら残りません。この後者のケースこそ、多くの監視構成が見逃すポイントです。

この記事では、両方の障害を検知する3つのパターンと、Echobell でアラートを実際の電話呼び出しにエスカレーションして絶対に見逃さないようにする方法を紹介します。

パターン1:終了コードフックで失敗を通知

最もシンプルな方法は、ジョブが非ゼロで終了したときにwebhookを発火させることです。

まずEchobellでチャンネルを作成し、そのwebhook URLをコピーします。次にcronコマンドをラップします:

0 3 * * * /opt/scripts/backup.sh || curl -s "https://hook.echobell.one/t/<channel-token>?title=Backup+failed&host=$(hostname)"

backup.sh が成功すれば何も起きません。失敗すれば、Echobellが数秒以内にスマートフォンへアラートを届けます。クエリパラメータはテンプレート変数になるため、どのホストのどのジョブが失敗したかを通知に正確に含められます。

長いスクリプトなら、trapでより詳しいコンテキストを送れます:

#!/usr/bin/env bash
set -euo pipefail

notify_failure() {
  curl -s -X POST "https://hook.echobell.one/t/<channel-token>" \
    -H "Content-Type: application/json" \
    -d "{\"job\":\"nightly-backup\",\"host\":\"$(hostname)\",\"line\":\"$1\"}"
}
trap 'notify_failure $LINENO' ERR

# ... ジョブのロジック ...

この方法の限界は、スクリプトが実際に実行されて失敗した場合にしか機能しないことです。サーバーがダウンしていたり、cronの設定が間違っていたり、デバッグ中に誰かがその行をコメントアウトしていたら、アラートは永遠に発火しません。だからこそパターン2が必要です。

パターン2:実行漏れを捕まえるデッドマンスイッチ

デッドマンスイッチはロジックを逆転させます。ジョブは成功時にモニターへpingを送り、モニターはpingが予定どおり届かなかったときにアラートを出します。エラー、ハング、サーバーダウン、crontabエントリの削除——あらゆる障害モードをカバーできます。

セルフホスト可能な2つの人気ツールがEchobellとうまく連携します:

  • Healthchecks.io はまさにこの用途のためのツールです。cronスケジュールと猶予期間を設定したチェックを作成し、cron行の末尾に && curl -s https://hc-ping.com/YOUR_UUID を追加します。pingが遅れるとHealthchecksがwebhookを送信するので、それをEchobellチャンネルに向ければ、バックアップの実行漏れが鳴り響く電話に変わります。
  • Uptime Kuma には同じ仕組みの「Push」モニタータイプがあります。ジョブがpush URLを呼び出し、ハートビートが途絶えるとUptime Kumaが通知連携を通じてアラートを出します。

どちらの場合も流れは同じです:cronジョブ → 成功ping → モニターが沈黙を検知 → EchobellへWebhook → プッシュ通知または電話。

パターン3:データを出力するジョブには時間窓チェック

ジョブによっては、終了コードより出力を検証したほうが確実です。夜間ETLが午前4時までに行を挿入するはずなら、小さな検証ジョブで行数をチェックし、数字がおかしいときにEchobellのwebhookを呼び出します。

ここでEchobellの条件機能が役立ちます。毎回の実行後にステータスwebhookを送り、通知するかどうかはチャンネル側で判断させるのです。status != "ok" のような条件なら成功時は静かなままですし、組み込みのUTC時刻変数を使えば、ジョブが完了しているべき時間帯だけにアラートを絞れます。

アラートを絶対に見逃さないために

検知は問題の半分にすぎません。午前3時にロック画面へ静かに表示されるバックアップ失敗のバナーは、アラートがないのと実質同じです。

Echobellではチャンネルごとに緊急度を選べます:

  • 通常 —— 標準のプッシュ通知。情報系のジョブに
  • 時間指定(Time-Sensitive) —— iOSの集中モードを突破。早めに確認すべきジョブに
  • 着信 —— 気づくまで本物の電話のように鳴り続ける

サイレント失敗が実害につながるジョブ——データベースバックアップ、請求バッチ、証明書更新——にはチャンネルを着信に設定しましょう。「午前3時に気づく」と「午前9時に気づく」の差こそが、電話アラートの価値です。

複数人でジョブを管理しているなら、チャンネルの購読リンクをチームに共有してください。購読者全員が同じ瞬間に同じアラートを受け取ります。

どのパターンを使うべきか

  • 終了コードフック:5分で設定でき、明示的な失敗を捕捉。まずはここから。
  • デッドマンスイッチ:実行漏れやハングも捕捉。本当に止まっては困るジョブすべてに。
  • 時間窓データチェック:「正常終了したのに出力がおかしい」が起こりうるパイプラインに。

3つは組み合わせられます。終了コードフックは失敗の事実と理由を教えてくれ、デッドマンスイッチは自己申告できなかった障害も確実に知らせてくれます。

最初のcronアラートは数分で設定できます。Echobellをダウンロードしてチャンネルを作成し、crontabに curl を1行追加するだけ。次に定期ジョブが午前3時に止まったとき、あなたの電話は鳴ります——そして来四半期に復元することになるバックアップは、ちゃんと存在しているはずです。

関連記事