Executarea corectă a WP-Cron pe rețele Multisite?
Am o instanță WordPress Multisite cu mai multe site-uri. Am setat DISABLE_WP_CRON
la true
în wp-config.php
.
Dacă configurăm un task cron cu wget sau curl, avem o limită de 30 de secunde pentru execuția scriptului PHP. Este prea puțin pentru trimiterea multor notificări prin email și alte operații (poate conexiunea la serverul SMTP este lentă, poate sunt foarte multe notificări de la bbPress sau altele).
Poate putem folosi ceva de genul acesta?
php -q wp-cron.php
Dar acest lucru rulează cron doar pentru un singur site în Multisite (fiecare site are propriile task-uri cron în tabele MySQL diferite).
P.S. Pe forumul wpmudev.org am găsit o "soluție" ciudată care folosește tot Curl.
Alt P.S. WP CLI are comenzi excelente wp cron
dar permit rularea task-urilor cron doar manual (da, putem folosi atributul --url
). De exemplu:
wp cron event list --url=multisite.com
wp cron event list --url=subdomain.multisite.com
După ce ai adăugat constanta în wp-config.php
defined('DISABLE_WP_CRON') or define('DISABLE_WP_CRON', true);
WP-CLI
Și presupunând că ai configurat corect config.yml
, poți omite flag-ul --path
când apelezi cron run
.
wp cron event run --due-now
[<hook>…]
Unul sau mai multe hook-uri de rulat.
[--due-now]
Rulește toate hook-urile datorite acum.
[--all]
Rulește toate hook-urile.
Pentru a rula toate sarcinile cron datorite în ordine:
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;
Dacă vrei să ruleze concurent (rulând mai întâi cron-ul nespecific site-ului):
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;
Ai putea să pici oricare dintre opțiuni într-un fișier executabil
chmod +x run_all_wp_cron_events_due_now.sh
adaugă o sarcină crontab
crontab -e
și probabil să execute în fiecare minut
* * * * * run_all_wp_cron_events_due_now.sh > /dev/null
Dacă vrei să rulezi o comandă personalizată din cron, poate fi necesar să specifici căile complete pentru ca wp-cli să funcționeze.
* * * * * cd /home/username/public_html; /usr/local/bin/php /home/username/wp-cli.phar your-custom-cron-commands run >/dev/null 2>&1
PHP
Singurul motiv pentru care ai avea nevoie să încarci WordPress aici este să obții URL-urile din baza de date în loc să folosești o listă predefinită. Vom doar să accesăm acele URL-uri și nu ne interesează cu adevărat care este răspunsul.
custom-cron.php
<?php
// Încarcă WP
require_once( dirname( __FILE__ ) . '/wp-load.php' );
// Verifică Versiunea
global $wp_version;
$gt_4_6 = version_compare( $wp_version, '4.6.0', '>=' );
// Obține Bloguri
$args = array( 'archived' => 0, 'deleted' => 0, 'public' => 1 );
$blogs = $gt_4_6 ? get_sites( $args ) : @wp_get_sites( $args ); // >= 4.6
// Rulează Cron pe fiecare blog
echo "Rulează Cron-uri: " . 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 );
}
Și adaugă un singur apel către custom-cron.php
în crontab
* * * * * wget -q -O - http://your-site.com/custom-cron.php?doing_wp_cron

Cred că cea mai bună metodă este să folosești WP-CLI, dar va trebui să scrii un script bash pentru asta. Iată unul care ar trebui să funcționeze pentru tine:
WP_PATH="/calea/catre/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
Apoi va trebui să adaugi acest script în crontab și să-l rulezi poate la fiecare minut, dacă dorești.

Hmm, mulțumesc pentru opinie, dar cred că aceasta este o soluție hacky (murdară). Cred că ar fi mai bine să scriu un addon PHP pentru wpcli care să execute toate sarcinile necesare. Am nevoie de mai mult timp pentru a înțelege funcțiile WP și codul pentru a face asta.

@KolyaKorobochkin Nu sunt de acord. Aceasta nu este deloc o soluție hacky, deoarece WP CLI a fost creat să fie utilizat în linia de comandă și în scripturile bash.

wp cron event run --due-now --url="$SITE_URL" --path="$WP_PATH
- Conform documentației run
, ar trebui să utilizați flag-ul --due-now
. Acest lucru ar reduce căutările și apelurile individuale la evenimente. Vezi: http://wp-cli.org/commands/cron/event/run/. Oricum, sunt de acord cu @OmarJackman - el utilizează linia de comandă pentru a folosi instrumentele WordPress din linia de comandă. Felicitări pentru un exemplu curat de Bash. Ați putea completa acest răspuns afișând intrarea în crontab.

Pentru beneficiul cititorilor viitori, scriptul arată astfel: 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

Varianta mai simplă într-o singură linie, cu mai puțin cod bash:
wp site list --field=url | xargs -i -n1 wp cron event run --due-now --url="{}"
Puteți să o rulați manual sau să o puneți într-un script și să o apelați din cron, așa cum este descris în celelalte răspunsuri.

Aceasta este o utilizare mult mai inteligentă a instrumentelor disponibile în WP CLI decât răspunsurile care depun mult efort pentru a analiza rezultatele ieșirii CSV. Funcționează perfect!

Acesta este cel mai inteligent răspuns. Și poți adăuga această comandă direct în crontab.

Foarte ingenios! Folosim acest lucru în SlickStack pentru Multisite acum, când utilizatorii selectează metoda wpcli
pentru a-și gestiona WP-Cron: https://github.com/littlebizzy/slickstack/blob/master/crons/01-cron-minutely.txt

Aceasta este soluția mea:
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; // înlocuiește cu gazda principală
}
require './wp-cron.php';
}
function shutdown()
{
run_cron();
}
run_cron();
Apelăm acest script din crontab, sper că te ajută

Puteți găsi un ghid complet aici despre cum să configurați corect job-ul cron pentru un sistem WordPress Multisite, astfel încât să ruleze pe toate sub-site-urile și să execute job-urile cron. https://support.shorturl.gg/business-marketing-and-seo-forums/topic/you-are-using-wp-cron-incorrectly-in-wordpress-multisite/
Folosirea job-ului cron standard pentru site-urile WordPress standalone nu funcționează bine, deoarece job-ul cron WP standard va rula doar pentru site-ul principal și, ca urmare, niciun job cron nu va rula pe sub-site-uri.

Deși acest link poate răspunde la întrebare, este mai bine să incluzi părțile esențiale ale răspunsului aici și să furnizezi linkul pentru referință. Răspunsurile care conțin doar linkuri pot deveni invalide dacă pagina la care se face referință se schimbă. - Din Review

Cred că mai întâi trebuie să ne explici ce înțelegi prin "a rula wp-cron.php corect". Conform WordPress, nu are sens să dezactivezi wp-cron și totodată să vrei să ruleze... Din perspectiva Linux, ar fi corect să folosești wget sau /bin/php pentru wp-cron.php, dar se pare că gazda ta limitează numărul de invocări PHP din motive de securitate? - partea asta nu e clară din descrierea ta.
Altă întrebare: câte email-uri înseamnă "o tonă"? Există motive întemeiate pentru care nu ar trebui să încerci să trimiți prea multe email-uri atât de rapid.
Poate va trebui să reiei obiectivele tale.
(Aș comenta în loc să răspund, dar nu am suficientă reputație pe wpstack.)

Există mai multe modalități de a rula cron-ul WordPress. Mecanismul încorporat este declanșat de vizualizările paginilor, iar o practică comună este să setați DISABLE_WP_CRON
pentru a dezactiva această metodă atunci când configurați în schimb metoda mai fiabilă a cron-ului de sistem.

Întrebarea nu este de ce să o faceți/dacă motivele sunt semnificative, ci cum să apelați corect wp-cron.php pe o instalare multisite. Destul de clar pentru mine ;)
