問題描述

我有幾個站點的 WordPress 多站點。我在 wp-config.php 中將 DISABLE_WP_CRON 設定為 true

如果我們使用 wget 或 curl 設定 cron 任務,我們有 30 秒的規則來執行 PHP 指令碼。傳送大量電子郵件通知並執行其他操作 (可能是遠端 SMTP 伺服器連線速度很慢,或許這是一大堆來自 bbPress 或任何東西的電子郵件通知) 這麼小。

也許我們可以使用這樣的東西?

php -q wp-cron.php

但是,它只能執行在多站點中的一個站點 (每個站點在不同的 MySQL 表中都有自己的 cron 任務) 。

P. S. On wpmudev.org forum 我發現奇怪的”solution” 也使用 curl 。

另一個 P. S. WP CLI 具有令人敬畏的 wp cron 命令,但它只允許手動執行 cron 任務 (是的,我們可以使用--url attr) 。例如:

wp cron event list --url=multisite.com
wp cron event list --url=subdomain.multisite.com

最佳解決方案

我認為最好的方法是使用 WP-CLI,但是您需要編寫一個 bash 指令碼來執行此操作。這是一個應該為你做的事情:

WP_PATH="/path/to/wp"
for SITE_URL in = $(wp site list --fields=domain,path,archived,deleted --format=csv --path="$WP_PATH" | grep ",0,0$" | awk -F ',' '{print $1 $2}')
do
    for EVENT_HOOK in $(wp cron event list --format=csv --fields=hook,next_run_relative --url="$SITE_URL" --path="$WP_PATH" | grep "now"$ | awk -F ',' '{print $1}')
    do
        wp cron event run "$EVENT_HOOK" --url="$SITE_URL" --path="$WP_PATH"
    done
done

然後,您需要將此指令碼新增到 crontab 中,如果您願意,可以每分鐘執行一次

次佳解決方案

wp-config.php 中新增常量後

defined('DISABLE_WP_CRON') or define('DISABLE_WP_CRON', true);

WP-CLI

並且假設您的 config.yml 設定正確,您可以在呼叫 cron run 時忽略--path 標誌。


wp cron event run --due-now

[<hook>…] One or more hooks to run.

[--due-now] Run all hooks due right now.

[--all] Run all hooks.


run all due cron tasks 為依據:

function run_crons_due_now_in_order { for SITE_URL in $(wp site list --fields=url --format=csv | tail -n +2 | sort); do wp cron event run --due-now --url="$SITE_URL" && echo -e "t+ Finished crons for $SITE_URL"; done; echo "Done"; }; run_crons_due_now_in_order;

如果要讓它們同時執行 (首先執行 non-site-specific cron):

function run_all_crons_due_now { for SITE_URL in $(wp site list --fields=url --format=csv | tail -n +2 | sort); do wp cron event run --due-now --url="$SITE_URL" && echo -e "t+ Finished crons for $SITE_URL" & done; wait $(jobs -p); echo "Done"; }; run_all_crons_due_now;

您可以將任一選項放在可執行檔案中

chmod +x run_all_wp_cron_events_due_now.sh

新增一個 crontab 任務

crontab -e

並可能每分鐘執行一次

* * * * * run_all_wp_cron_events_due_now.sh > /dev/null

如果要從 cron 執行 custom command,則可能需要指定 wp-cli 的完整路徑才能正常工作。

* * * * * cd /home/username/public_html; /usr/local/bin/php /home/username/wp-cli.phar your-custom-cron-commands run >/dev/null 2>&1

PHP

您在這裡需要載入 WordPress 的唯一原因是從資料庫中收集 URL,而不是使用 pre-defined 列表。我們只打算 ping 這些 URL,我們並不關心響應是什麼。

custom-cron.php

<?php

// Load WP
require_once( dirname( __FILE__ ) . '/wp-load.php' );

// Check Version
global $wp_version;
$gt_4_6 = version_compare( $wp_version, '4.6.0', '>=' );

// Get Blogs
$args  = array( 'archived' => 0, 'deleted' => 0, 'public' => 1 );
$blogs = $gt_4_6 ? get_sites( $args ) : @wp_get_sites( $args ); // >= 4.6

// Run Cron on each blog
echo "Running Crons: " . PHP_EOL;
$agent = 'WordPress/' . $wp_version . '; ' . home_url();
$time  = time();

foreach ( $blogs as $blog ) {
    $domain  = $gt_4_6 ? $blog->domain : $blog['domain'];
    $path    = $gt_4_6 ? $blog->path : $blog['path'];
    $command = "http://" . $domain . ( $path ? $path : '/' ) . 'wp-cron.php?doing_wp_cron=' . $time . '&ver=' . $wp_version;

    $ch = curl_init( $command );
    $rc = curl_setopt( $ch, CURLOPT_RETURNTRANSFER, false );
    $rc = curl_exec( $ch );
    curl_close( $ch );

    print_r( $rc );
    print_r( "t✔ " . $command . PHP_EOL );
}

並在 crontab 中新增一個單獨的 custom-cron.php 呼叫

* * * * * wget -q -O - http://your-site.com/custom-cron.php?doing_wp_cron

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。