2026年8月27日

2026年8月27日

Healthchecks.ioでスケジュール監視する方法|cron・バックアップの実行漏れを検知する

Healthchecks.io は、cron やバックアップのような定期ジョブが「予定どおり終わったか」を見張るサービスです。ジョブの最後に専用URLへアクセス(ping)させておき、決めた時間内に ping が来なければ通知が飛ぶ仕組みなので、エラーすら出さずに止まったジョブにも気づけます。この記事では、チェックの作り方、crontab への組み込み、失敗とログの送り方、WordPress の WP-Cron を監視する方法までを順に説明します。

Healthchecks.io の仕組み:「来るはずの連絡が来ない」を検知する

一般的な外形監視(Uptime Kuma など)は、監視側からサイトへアクセスして応答を確かめます。これに対して Healthchecks.io は向きが逆で、監視される側のジョブが自分から ping を送ります。いわゆる「デッドマンスイッチ」型の監視です。

この方式が役立つのは、次のような止まり方です。

  • サーバーの再起動後に cron デーモンが動いていなかった
  • crontab を編集したときに行を消してしまった
  • バックアップスクリプトが途中で固まり、終わらないまま残っている
  • WordPress の WP-Cron が、アクセスの少ない時間帯に動いていなかった

どれもエラーログが残りにくく、「何も起きていない」ことが問題なので、外から監視するだけでは見つけられません。ping が来ないこと自体を異常とみなす Healthchecks.io なら検知できます。

各チェックには、主に次の2つの時間を設定します。

  • 期間(Period):ping が届く間隔。毎日1回なら1日
  • 猶予(Grace):期間を過ぎてから「遅れ」を許す時間。ジョブの所要時間がぶれる場合は長めにする

間隔の代わりに cron 式とタイムゾーンでスケジュールを指定することもできます。「毎日3時に実行」のように時刻が決まっているジョブは、cron 式のほうが実態に合います。

手順1:チェックを作成する

Healthchecks.io にはホスティング版(healthchecks.io)があり、オープンソースなので自分のサーバーで動かすこともできます。まずはホスティング版で試し、要件に応じて自前運用を検討するのが手軽です。無料で使える範囲や上限は変更されることがあるため、料金ページで最新の条件を確認してください(2026年10月現在)。

ダッシュボードでチェックを追加すると、https://hc-ping.com/ で始まる固有の ping URL が発行されます。このとき決めておくことは3つです。

  1. 名前:「backup-db-daily」のように、通知を見ただけで何のジョブか分かる名前にする
  2. スケジュール:cron 式を使う場合は、サーバーの crontab と同じ式・同じタイムゾーンにそろえる
  3. 猶予:普段の所要時間の最大値に余裕を足した長さにする

画面の項目名はバージョンによって変わることがあるため、ここでは役割で説明しています。

ping URL は、知っている人なら誰でも「成功」を送れてしまう値です。公開リポジトリに含めない、スクリーンショットに写さないなど、パスワードに近い扱いをしてください。

手順2:crontab に ping を組み込む

もっとも単純な形は、ジョブが成功したときだけ ping を送る書き方です。

# 毎日3:00にDBバックアップ。成功したときだけpingを送る
0 3 * * * /usr/local/bin/backup-db.sh && curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/your-uuid

&& でつないでいるので、スクリプトが0以外の終了コードで終わると ping は送られず、猶予を過ぎた時点で通知されます。curl のオプションにはそれぞれ理由があります。

  • -f:HTTPエラーのときに失敗として扱う
  • -sS:進捗表示を消しつつ、エラーだけは表示する
  • -m 10:最大10秒で打ち切る。ネットワーク障害で curl が固まるのを防ぐ
  • --retry 5:一時的な通信エラーなら再試行する
  • -o /dev/null:応答本文を捨て、cron のメールを汚さない

手順3:失敗・開始・ログも送る

成功の ping だけだと、失敗した場合は猶予が過ぎるまで通知が来ません。Healthchecks.io の ping URL は末尾を変えることで次の意味を持たせられます。

  • /start:開始の合図。所要時間の計測や、終わらないジョブの検知に使う
  • /fail:失敗をすぐに知らせる
  • /0〜/255:終了コードをそのまま送る。0は成功、それ以外は失敗として扱われる

終了コードを送る形にすると、成功・失敗の両方を1行で扱えます。

0 3 * * * /usr/local/bin/backup-db.sh; curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/your-uuid/$?

ここでは && ではなく ; を使い、直前のコマンドの終了コード $? を URL に入れています。crontab 内で % は改行扱いになる点に注意してください。日付などで % を使うなら、処理をスクリプトにまとめるほうが安全です。

失敗の理由まで通知で見たい場合は、ラッパースクリプトで出力の末尾を POST します。Healthchecks.io は ping の本文を一定量(ドキュメント上は先頭100kBまで)保存します。

#!/bin/bash
# /usr/local/bin/hc-wrap.sh  使い方: hc-wrap.sh <ping-url> <コマンド...>
set -u
PING_URL="$1"; shift
RID=$(cat /proc/sys/kernel/random/uuid)

curl -fsS -m 10 --retry 5 -o /dev/null "${PING_URL}/start?rid=${RID}"

OUTPUT=$("$@" 2>&1)
STATUS=$?

# 出力の末尾10KBだけを送る
printf '%s' "$OUTPUT" | tail -c 10000 | \
  curl -fsS -m 10 --retry 5 -o /dev/null --data-binary @- "${PING_URL}/${STATUS}?rid=${RID}"

exit "$STATUS"

rid は開始と終了の ping をひも付ける識別子で、同じジョブが重なって動いたときでも所要時間を正しく計算するために使います。送る出力にパスワードやトークンが含まれていないかは事前に確認してください。ログは第三者のサービスに保存されます。

手順4:WordPress の WP-Cron を監視する

WP-Cron は、サイトにアクセスがあったときに予定のタスクを実行する仕組みです。アクセスが少ないサイトやキャッシュで PHP が動かないページばかりのサイトでは、予約投稿や定期処理が遅れることがあります。安定させる定番の方法は、wp-config.php で DISABLE_WP_CRON を true にし、サーバーの cron から WP-CLI で実行することです。その実行を Healthchecks.io で見張ります。

# Webサーバーの実行ユーザー(例: www-data)のcrontabに書く
*/5 * * * * /usr/local/bin/wp cron event run --due-now --path=/var/www/html --quiet; curl -fsS -m 10 --retry 3 -o /dev/null https://hc-ping.com/your-uuid/$?

つまずきやすいのは次の3点です。

  • cron の PATH は短いため、wp はフルパスで書く
  • root の crontab で動かすと、作られたファイルの所有者が root になり、後でアップロードや更新が失敗することがある
  • 5分ごとに ping するなら期間は5分、猶予は数分程度にし、送信頻度を上げすぎない(ドキュメントは1分に5回を超える ping を避けるよう案内しています)

特定のプラグインの定期処理が本当に走ったかを知りたい場合は、そのフックに後から ping を足す方法もあります。mu-plugin に置けば、テーマ変更の影響を受けません。

<?php
// wp-content/mu-plugins/hc-ping.php
// wp-config.php で define( 'MY_HC_PING_URL', 'https://hc-ping.com/your-uuid' ); を設定しておく
add_action( 'my_plugin_daily_event', function () {
    if ( ! defined( 'MY_HC_PING_URL' ) ) {
        return;
    }
    wp_remote_get( MY_HC_PING_URL, array( 'timeout' => 10 ) );
}, 99 );

my_plugin_daily_event は例なので、実際のフック名は WP-Crontrol などのプラグインや wp cron event list で確認してください。優先度を99にしているのは、本来の処理より後に ping を送るためです。本来の処理が致命的エラーで止まれば ping は送られず、遅れとして通知されます。導入はステージング環境で試し、本番に入れる前にバックアップを取ってください。

通知先を設定する

チェックが「遅れ」や「失敗」になったときの通知先は、メールのほか Slack、Discord、Webhook、PagerDuty や Opsgenie などの連携が用意されています。対応サービスは追加・終了があるため、連携一覧の画面で確認してください。

運用では次の点を意識すると、通知を見落としにくくなります。

  • 通知先は2系統にする(例:メールとチャット)。片方が止まっても気づける
  • 連携を設定したら、テスト通知を送って届くことを確かめる
  • 重要度で分ける。バックアップ失敗はオンコール担当へ、レポート生成の遅れはチャットだけ、のようにプロジェクトや連携を分ける

よくあるつまずき

  • 毎日決まった時間に誤報が出る:cron 式のタイムゾーンがサーバーとずれている可能性が高いです。チェック側のタイムゾーン設定を確認します。
  • ジョブが長引くと遅れ扱いになる:猶予が短すぎます。/start を送るようにすると、所要時間の実績がダッシュボードに残るので、それを見て猶予を決められます。
  • ping は届いているのに処理は失敗していた:スクリプトが失敗しても終了コード0で終わっていないか確認します。bash なら set -e やパイプの set -o pipefail を検討します。
  • サーバーごと止まった:この場合も ping が来ないので通知されます。ただし原因の切り分けには、外形監視やサーバー監視も併用するのが現実的です。

まとめ

  • Healthchecks.io は、ジョブ側から ping を送り、来なければ通知するデッドマンスイッチ型の監視
  • 期間と猶予、または cron 式とタイムゾーンをジョブの実態に合わせて設定する
  • curl -fsS -m 10 --retry 5 で ping し、終了コード・/start・ログ送信で失敗の理由まで追えるようにする
  • WordPress は DISABLE_WP_CRON とサーバー cron の組み合わせにし、その実行を監視する
  • ping URL は秘密情報として扱い、通知先は2系統にしてテストしておく

お気軽にご相談ください

お見積りへ お問い合わせへ
▲