コンテンツへスキップ

crontab構文の基礎とWP-Cronとの違い

*/5 * * * * って結局どういう意味?」——サーバーの定期実行を設定しようとして、この5つのアスタリスクの並びで手が止まった経験がある人は多いはずである。WordPressを運用していると、WP-CLIでWP-Cronの中身を覗く機会はあっても、OS本体のcrontab構文そのものにきちんと触れる機会は意外と少ない。WP-Cronを本物のcronに切り替える設定を組むにも、まずcrontabの構文を理解しておく必要がある。

補足: crontabはUnix系OS(Linux/macOS等)に標準で組み込まれた定期実行の仕組み。「cron table」の略で、いつ・何を実行するかを1行ずつ記述する設定ファイルとその管理コマンドを指す。

5つのフィールドの意味

crontabの1行は、次の5つの時刻フィールドと実行するコマンドで構成される。

分 時 日 月 曜日 コマンド
*  *  *  *  *    command
フィールド 範囲 意味
0-59 何分に実行するか
0-23 何時に実行するか(24時間表記)
1-31 何日に実行するか
1-12 何月に実行するか
曜日 0-7(0と7は日曜) 何曜日に実行するか

* はそのフィールドを「毎回」として扱うワイルドカードである。すべてが * の行は「毎分実行」を意味する。

よく使う記法パターン

実務でよく使うのは、この5フィールドの組み合わせパターンをいくつか覚えておくことである。

# 毎分実行
* * * * * command

# 5分おきに実行
*/5 * * * * command

# 毎日午前3時に実行
0 3 * * * command

# 平日(月〜金)の午前9時に実行
0 9 * * 1-5 command

# 毎月1日の午前0時に実行
0 0 1 * * command

*/5 のようなスラッシュ記法は「ステップ値」と呼ばれ、「0から始めて5刻みで」を意味する。1-5 のようなハイフン記法は範囲指定で、月曜(1)から金曜(5)までをまとめて表す。カンマで 1,3,5 のように複数値を並べることもできる。この3種類(ステップ・範囲・カンマ)を組み合わせられれば、たいていのスケジュールは表現できる。

一部のcron実装では @daily0 0 * * * と同義)や @hourly0 * * * * と同義)のような特殊文字列も使える。可読性は上がるが、実装によってサポート状況が違うため、5フィールド記法を基本形として覚えておくほうが移植性が高い。

crontab -e で編集する

自分のユーザー権限で動くcronジョブは crontab -e で編集する。

# 現在のユーザーのcrontabを編集
crontab -e

# 現在のユーザーのcrontabを一覧表示
crontab -l

# 現在のユーザーのcrontabを削除
crontab -r

crontab -e はデフォルトのテキストエディタ(EDITOR 環境変数で指定されたもの)を開く。保存すると即座に反映され、明示的な再起動やリロード操作は不要になる。編集内容を誤って全消去してしまう事故を避けるため、crontab -r は実行前に crontab -l で内容を確認する癖をつけておきたい。

PATH環境変数の罠

crontabから実行されるジョブは、通常のログインシェルとは異なる最小限のPATH環境変数で動く。ログインシェルで動作確認したコマンドが、crontab経由だと「command not found」で失敗する典型的な原因がこれである。

# ログインシェルではPATHにあるコマンドとして動くが、
# crontab環境では見つからない可能性がある
0 3 * * * wp cron event run --due-now

# 対策: フルパスで指定する、または明示的にPATHを設定する
0 3 * * * /usr/local/bin/wp cron event run --due-now --path=/var/www/html

# もしくはcrontabファイルの先頭でPATHを明示する
PATH=/usr/local/bin:/usr/bin:/bin
0 3 * * * wp cron event run --due-now --path=/var/www/html

which wp 等でコマンドの絶対パスを事前に確認し、crontab側にはフルパスを書いておくのが最も確実な対処になる。

WP-Cronとの根本的な違い

ここまで見てきたOSのcrontabと、WordPress組み込みのWP-Cronは、名前は似ているが動作原理が根本的に異なる。

観点 OSのcrontab WP-Cron
実行のトリガー OS標準のcronデーモンが時刻を監視 ページアクセスのたびにWordPressが「期限切れタスクがないか」を確認
アクセスがない時間帯 予定通りに実行される 実行されない(次のアクセスまで持ち越し)
実行主体 OSプロセス(Webサーバーとは独立) PHPプロセス(リクエスト処理の一部として実行)
設定ファイル crontab -e で編集 wp_options テーブルに保存されたスケジュール

WP-Cronが「ページアクセス頼みの疑似cron」である理由は、まさにこの表の1行目に集約される。トラフィックの少ない深夜のサイトで予約投稿が時刻通りに公開されない、といった現象は、この設計上の制約から生まれている。

本物のcrontabに置き換える

wp-config.phpdefine('DISABLE_WP_CRON', true); を追加してWP-Cronの自動発火を止めた上で、OSのcrontabから定期的にWP-CLIを呼び出す構成にすると、アクセス数に依存しない確実な時刻実行に切り替えられる。

# 5分おきにWP-Cronの遅延タスクをまとめて処理する
*/5 * * * * /usr/local/bin/wp cron event run --due-now --path=/var/www/html/wordpress > /dev/null 2>&1

> /dev/null 2>&1 は標準出力・標準エラー出力を破棄する記法で、cronは実行結果をメールで送ろうとする既定動作を持つため、これを付けないとメール送信が失敗し続ける環境がある(メールサーバーが設定されていない場合など)。ログを残したい場合は /dev/null の代わりにログファイルのパスを指定すればよい。

まとめ

やりたいこと 記法・コマンド
5分おきに実行 */5 * * * *
平日の午前9時に実行 0 9 * * 1-5
自分のcrontabを編集 crontab -e
自分のcrontabを確認 crontab -l
PATH問題を避ける コマンドをフルパスで指定
出力を破棄する 行末に > /dev/null 2>&1

crontabの5フィールド構文自体はシンプルだが、「PATHが最小限になる」「実行結果がメールで飛ぼうとする」といった、対話シェルとの差分に足をすくわれることが多い。WP-CLIでWP-Cronの中身を確認するコマンドと組み合わせれば、WordPressの予定タスクをOS標準の確実なスケジューラで動かす構成が組める。