マルチサイト運用のWordPressでwp-cron.phpをcronから起動する

2016年8月26日Web-log・ココログ関連,WordPress,パソコン・インターネット

GoDaddyでサーバを借りて、WordPressを動かしています。帯域やファイル容量はほとんど気にしなくて良いのですが、CPUやメモリリソースがシビアです。油断すると、あっという間に制限に引っかかります。そんなわけで、次の記事に従って、CPUやメモリリソースの削減に取り組んでいます。

その項目の一つに、wp-cron.phpをWordPressの中から起動するのではなく、システムのcronを使って起動する方法があります。

シングルサイトのWordPressなら…

シングルサイトについての具体的な方法は、検索するといくらでも見つかります。最初に参考にしたのは、次のウェブページです。ありがとうございます。

基本的な、手順は次の通りです。

  1. wp-config.phpに、define('DISABLE_WP_CRON’, 'true’);を設定する
  2. wgetやcurlを用いてwp-cron.phpを、cronから呼び出す設定をする

マルチサイトのWordPressなら…

シングルサイトならこれで終わりなのですが、マルチサイトだと、もう一工夫必要です。この手順を、全サイトに対しての実行しなければなりません。検索してすぐに見つかるのは、次のところでしょうか? ありがとうございます。

WP-Cliを使って、高度なshellスクリプトでの実現も可能のようです。すごいです。でも、高度すぎて、ついていけませんでした。

日本語で検索して簡単に見つかるのはここまでです。WordPressの仕組みを利用して、もっとスマートにできないものかと、英語で書かれたウェブページも検索してみました。そして見つけたのが、次のウェブページです。この方法を使った改良版のウェブページもありました。Thank you!

結局のところ、マルチサイト運用しているWordPressでwp-cron.phpをcron起動するには、次の3つのポイントがあります。

  1. wp-load.phpを正しく読み込む
  2. 全サイトに対してwp-cron.phpを実行する
  3. このスクリプトをcronで実行する

1. wp-load.phpを正しく読み込む

wp-load.phpを読み込むと、WordPress以外のPHPスクリプトで、WordPressの関数を利用できるようになります。今回、次の二つの関数を使いたいです。これらの関数については、後で説明します。

  • get_sites() または wp_get_sites()
  • wp_remote_get()

wp-load.phpを読み込む時、次のエラーが出て困っていました。

Status: 302 Moved Temporarily
Location: http://oichinote.com/
Content-type: text/html; charset=UTF-8

この原因についてもいろいろ調べました。そして行き着いたのが、改良版のスクリプトに記載されている通り(説明文にも書かれていますが)、$_SERVER['HTTP_HOST’]を正しく設定する事です。今回、cronから直接PHPスクリプトを起動しています。このため、$_SERVER['HTTP_HOST’]が設定されず、ステータス302になってしまい、PHPスクリプトが実行されませんでした。

cronから起動する時に、PHPスクリプトを直接呼ぶのではなく、wgetやcurlで呼びだせば、この設定が無くてもwp-load.phpを読み込めます。ただし、ネットワークリソースを無駄に消費します。これを防ぐためには、次の様に設定します。example.comはご使用のサイト名に変更してください。

$_SERVER['HTTP_HOST'] = 'example.com'; // Your Site

無事に、WordPress関数を実行できる様になりました。

2. 全サイトに対してwp-cron.phpを実行する

全サイトに対してwp-cron.phpを実行するためには、まず、マルチサイトの全サイト情報を取り出す必要があります。

WordPressには、マルチサイトの全サイト情報を取り出す関数があります。get_sites()です。get_sites()はWordPress 4.6で追加になりました。それ以前のWordPressなら、wp_get_sites()を使います。SQL文を書いてWordPressのデータベースを直接触って各サイトを取り出すよりも、この方法の方が安全だと思います。

全サイト情報を取り出した後は、http経由でwp-cron.phpを呼び出します。呼び出すためのURLを作成した後、wp_remote_get()を使って呼び出しています。wp_remote_get()は、GETメソッドでアクセスするための関数です。オリジナルの投稿だと、cURLを使っているのですが、WordPressの関数を使った方が簡単だと思います。

そしてできたのが、次のPHPスクリプト(wp-cron-multisite.php)です。WordPressをインストールしてあるフォルダと同じ場所に置きます。おそらく、WordPress 3.7.0以上なら動作すると思います。WordPress 4.6.0でしかテストしていません。

<?php
// Multisite run wp cron on each site <https://premium.wpmudev.org/forums/topic/multisite-run-wp-cron-on-each-site>
// Getting WordPress cron work in multisite environment – Tigr.net <https://tigr.net/3203/2014/09/13/getting-wordpress-cron-work-in-multisite-environment/>

$_SERVER['HTTP_HOST'] = 'example.com'; // Your Site
require_once(__DIR__ . '/wp-load.php'); // PHP >= 5.3.0

$wp_version = get_bloginfo('version');
$blogs = ($wp_version >= 4.6) ? get_sites() : wp_get_sites(); // WP >= 3.7.0

foreach($blogs as $blog) {
    $command = 'http://' . $blog->domain . ($blog->path ? $blog->path : '/') . 'wp-cron.php?doing_wp_cron';
    wp_remote_get($command); // WP >= 2.7.0
}
?>

3. このスクリプトをcronで実行する

実際のcronの間隔は、次のウェブサイトを参考にして、5分ごとにしています。ありがとうございます。この方は、最初6時間ごとにしていたみたいですが、間隔が長すぎたようで、5分に変更されています。

GoDaddyなら、cPanelのCronジョブで追加します。

Cronジョブ

次の様に操作します。

cronジョブ設定

正しく設定できたら、「現在の cron ジョブ」に次の様に表示されるはずです。

*/5 * * * * cd /home/username/public_html; php -q wp-cron-multisite.php

もちろん、wp-config.phpに、次の設定をするのを忘れないでください。

define(‘DISABLE_WP_CRON’, ‘true’);

これらの設定で、無事にcron起動できるようになりました。予約投稿もできましたので、大丈夫と思います。(でも、なぜか、パプリサイズ投稿が動きませんでした。これは別問題と思います。)

[amazonjs asin="B01DZXAHV0" locale="JP"]

Posted by お市のかた