綺麗に死ぬITエンジニア

意外と知らない、WordPressの正しいcronの設定方法

2015-12-08

WordPressのジョブの定期実行(一定時間ごとの処理)の仕組みは、デフォルトではwp-cron(擬似cron)と呼ばれる方法を利用しています。これは、Webアクセスをトリガーとし、現在実行すべき処理がないかどうかをその都度確認するものです。

しかし、これではジョブの定期実行により呼ばれる"予約投稿"が、時間を過ぎても次のWebアクセスが来るまで投稿されません。これは、記事投稿時に自動でメール配信やSNS配信をしている場合には、告知の遅延の元となってしまいます。また、アクセスの多いサイトであればオーバーヘッドも気になります。

そこで、リアルタイムに処理する必要がある場合には、wp-cronからサーバー側の通常のcronに移行するのが普通ですが、Webで検索すると各サイトで設定方法が異なり、一部無駄が多い設定になっている場合があるので、ここで私自身が思う最適な設定方法について、ご紹介したいと思います。

wp-cronの無効化

サーバーサイドのcronに移行しますので、Webアクセスごとに動くwp-cronを無効化します。

WordPressのインストールディレクトリーの直下にあるwp-config.phpの、データベース設定の下の辺りに、下記の記述を追加します。

define('DISABLE_WP_CRON', 'true');

サーバー側のcronの有効化

下記のように、/etc/crontabを編集し、WordPressのcronが定期的に実行されるようにします。

$ vi /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
* * * * * nginx /usr/bin/php -q /var/www/html/wp-cron.php >/dev/null 2>&1

最終行が、追加すべき設定項目です。

上記の[nginx]の部分は、利用しているWebサーバーのユーザーを指定してください。Webサーバーがnginxならnginx、Apache HTTP Serverならapache、Debian系のLinuxを利用している場合はwww-dataなどのユーザー名を指定します。

上記の[/usr/bin/php]の部分は、PHPコマンドの絶対パスを指定してください。通常はこのままで問題ないと思いますが、ソースからコンパイルした場合などは変更する必要があるかもしれません。

上記の[/var/www/html/wp-cron.php]の部分は、WordPressがインストールされたディレクトリのwp-cron.phpファイルの絶対パスを指定してください。これは環境によって大きく異なる可能性があります。

良くない記述例

$ whoami   # 現在のユーザーを表示するコマンド
root
$ crontab -e
* * * * * /usr/bin/php -q /var/www/html/wp-cron.php >/dev/null 2>&1

rootユーザーで実行してはいけません。

cronで実行したPHPファイル内で、アップロードするメディア用のディレクトリーを作成することがありますが、rootで実行するとrootユーザーが所有者となってしまうため、メディアファイルがアップロードできなくなるなどの弊害が出る可能性があります。他にも、サードパーティのプラグインなどで不具合が生じる可能性があります。素直にWebサーバーのユーザーで実行しましょう。

$ vi /etc/crontab

* * * * * root /usr/bin/curl https://s8a.jp/wp-cron.php >/dev/null 2>&1

HTTP / HTTPS経由で実行することは、望ましくありません。

Webサーバー経由でアクセスすると、その分サーバーにオーバーヘッドが生じます。Webサーバーは、通信時に全体のコンテンツの長さを計算してレスポンスヘッダーに記載したり、圧縮処理を実行したり、名前解決などでネットワークを経由したり、キャッシュサーバーを利用している場合はトラフィック自体がネットワーク上を流れてしまったりするなど、様々な点でコマンドでの実行と比べ動作が遅くなる可能性を孕んでいます。また、Webサーバーが起動していないと動作せず、エラーを吐きます。

なお、この方法の場合は処理自体がWebサーバーを経由する(WebサーバーのユーザーがPHPファイルを読み込む)ため、rootユーザーで実行しても大丈夫です。どうしてもrootユーザーで実行したい場合は、せめて以下のように記述しましょう。

$ vi /etc/crontab

\* * * * * root /usr/bin/curl https://127.0.0.1/wp-cron.php >/dev/null 2>&1

名前ベースのバーチャルホストを利用している場合は、これでは動かなくなってしまうので、もうこのオーバーヘッドは諦めましょう。レンタルサーバーなどの場合は、ほぼ名前ベースのバーチャルホストだと思いますので、次回契約更新時にはVPSなどの自由度の高いプランを検討しましょう。ですが、動作上、直ちに問題が生じるほどのものではないので、パフォーマンスに問題がなければスルーでOKです。

まとめ

cronって「クロン」って呼んでる人がいたり、「クーロン」って呼んでる人がいたり、「クローン」って呼んでる人がいたり、安定しないですよね。結局どれが正しいんでしょうかね。でも、スペル的に「クーロン」だけは、絶対認めたくない。

あ、皆さん楽しいWordPressライフを送りましょう! それでは!

筆者について

フリーランスエンジニアとして活動している、「もりやませーた」です。

筆者のTwitterはこちら。記事に関するご意見等はTwitterの方へお寄せください。

その他業務に関するお問い合わせは、こちらのページをご覧ください。

WordPress