Ejecutando WP Cron en múltiples sitios de la manera correcta

18

Tengo WordPress Multisite con varios sitios. He definido DISABLE_WP_CRONa trueen mi wp-config.php.

Si configuramos la tarea cron con wget o curl, tenemos una regla de 30 segundos para ejecutar el script PHP. Es muy pequeño enviar toneladas de notificaciones por correo electrónico y hacer otras cosas (tal vez la conexión remota del servidor SMTP es lenta, tal vez es realmente un montón enorme de notificaciones por correo electrónico de bbPress o algo así).

¿Quizás podamos usar algo como esto?

php -q wp-cron.php

Pero solo ejecuta cron en un sitio en Multisitio (cada sitio tiene sus propias tareas cron en diferentes tablas MySQL).

PD: En el foro wpmudev.org encontré una extraña "solución" que también usa Curl.

Otra PS WP CLI tiene wp croncomandos increíbles , pero solo permite ejecutar tareas cron manualmente (sí, podemos usar --urlattr). Por ejemplo:

wp cron event list --url=multisite.com
wp cron event list --url=subdomain.multisite.com
Kolya Korobochkin
fuente
¿Has echado un vistazo al WP-CLIcódigo central?
Kaiser
Si. Excavo en el código fuente en este momento y trato de entender :) El comando para ejecutar todas las tareas (eventos) no existe, tal vez pueda crearlo en el futuro.
Kolya Korobochkin el
¿Tienes wp/ WP-CLI en tu PATH? En caso afirmativo, ¿por qué no activarlo desde un archivo bash que se ejecuta en cron?
Kaiser
¡Suena genial! Pero, ¿cómo ejecutar todas las tareas cron desde wp cli? No veo ningún comando para esto.
Kolya Korobochkin
¿Exactamente como has mostrado al final de tu pregunta?
Kaiser

Respuestas:

13

Creo que la mejor manera es usar WP-CLI, pero necesitarías escribir un script bash para hacer esto. Aquí hay uno que debería hacerlo por usted:

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

Luego, deberá agregar este script a crontab y ejecutarlo tal vez cada minuto si lo desea

DiverseAndRemote.com
fuente
Gracias por tu opinión, pero creo que esta es una solución hacky (sucia). Creo que será mejor escribir un complemento de PHP para wpcli que simplemente ejecute todas las tareas necesarias. Necesito más tiempo para comprender las funciones de WP y el código para hacerlo.
Kolya Korobochkin
44
@ KolyaKorobochkin No estoy de acuerdo. Esto no es hacky en absoluto ya que WP CLI fue hecho para usarse en la línea de comandos y en los scripts de bash.
DiverseAndRemote.com
1
wp cron event run --due-now --url="$SITE_URL" --path="$WP_PATH- Según los rundocumentos, debe utilizar la --due-nowbandera. Esto reduciría las búsquedas y las llamadas a eventos individuales. Ver: wp-cli.org/commands/cron/event/run . De cualquier manera, estoy con @OmarJackman: está utilizando la línea de comandos para usar las herramientas de línea de comandos de WordPress. Accesorios para un ejemplo limpio de Bash. Puede completar esta respuesta mostrando la entrada crontab.
jgraup
Para el beneficio de los futuros lectores, el guión se ve así: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 wp cron event run --due-now --url="$SITE_URL" --path="$WP_PATH"; done
desconcierto
10

Después de agregar la constante en wp-config.php

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

WP-CLI

Y suponiendo que tiene su config.ymlconfiguración correcta, puede omitir la --pathbandera al llamar cron run.


wp cron event run --due-now

[<hook>…] Uno o más ganchos para correr.

[--due-now] Ejecute todos los ganchos que vencen ahora.

[--all] Corre todos los ganchos.


Para ejecutar todas las tareas cron debidas en orden:

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;

Si desea que se ejecuten simultáneamente (ejecutando primero el cron no específico del sitio):

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;

Desearía poner cualquiera de las opciones en un archivo ejecutable

chmod +x run_all_wp_cron_events_due_now.sh

agregar una tarea crontab

crontab -e

y probablemente ejecutar cada minuto

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

Si desea ejecutar un comando personalizado desde cron, es posible que deba especificar las rutas completas para que wp-cli funcione.

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

PHP

La única razón por la que necesitaría cargar WordPress aquí es reunir las URL de la base de datos en lugar de utilizar una lista predefinida. Solo vamos a hacer ping a esas URL y realmente no nos importa cuál sea la respuesta.

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 );
}

Y agregue una sola llamada a su custom-cron.phpen un crontab

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

Una línea más fácil con menos golpe:

wp site list --field=url | xargs -i -n1 wp cron event run --due-now --url="{}"

Puede ejecutarlo manualmente o ponerlo en un script y llamarlo desde cron como en las otras respuestas.

Anastis
fuente
0

Esta es mi solución:

global $multisite_hosts;
$multisite_hosts = Array('xxxx.dev.xxx.oondeo.es','x2.dev.xxx.oondeo.es','x3.dev.xxx.oondeo.es');

function run_cron(){
  global $multisite_hosts;
  $host=array_pop($multisite_hosts);
  if (!$host)
    return;
  register_shutdown_function('shutdown');
  if (!isset($_SERVER['HTTP_HOST'])) {
       $_SERVER['HTTP_HOST'] = $host;  // replace with primary host
  }

  require './wp-cron.php';
}

function shutdown()
{
  run_cron();
}
run_cron();

Llamamos a esto desde crontab, espero que ayude

Amon-Ra
fuente
-5

Creo que debe decirnos qué quiere decir con "ejecutar wp-cron.php de la manera correcta" en primer lugar. Según Wordpress, no tiene sentido que deshabilite wp-cron y quiera que se ejecute ... Desde la perspectiva de Linux, wget-ing o / bin / php-ing wp-cron.php sería correcto, pero parece que su host particular está limitando su número de invocaciones de php por razones de seguridad? - esa parte no está completamente clara en tu descripción.

Otra pregunta: ¿cuántos correos electrónicos son "una tonelada"? Hay buenas razones por las cuales no deberías intentar enviar demasiados correos electrónicos tan rápido.

Puede que tenga que repensar sus objetivos.

(Yo comentaría en lugar de responder, pero no tengo suficiente reputación en wpstack).

Jorge Orpinel
fuente
3
Hay varias formas de ejecutar el cron de WordPress. El mecanismo incorporado se activa por las visitas a la página, y es una práctica común configurarlo DISABLE_WP_CRONpara deshabilitar este método al configurar el método cron más confiable del sistema.
Marcus Downing
La pregunta no es por qué hacerlo / si las razones son significativas, sino cómo llamar correctamente a wp-cron.php en una instalación multisitio. Muy claro para mí;)
Philipp
1
Espero que te des cuenta de que estás comentando una respuesta muy antigua y ya oculta.
Jorge Orpinel