I have WordPress Multisite with several sites. I set up DISABLE_WP_CRON to true in my wp-config.php.

If we set up cron task with wget or curl we have 30 sec rule to execute PHP script. It's so small to send tons of email notifications and do other stuff (maybe remote SMTP server connection is slow, maybe it's really huge bunch of email notifications from bbPress or anything).

Maybe we can use something like this?

php -q wp-cron.php

But it's only run cron to one site in Multisite (each site have their own cron tasks in different MySQL tables).

P. S. On wpmudev.org forum I found strange "solution" which also use Curl.

Another P. S. WP CLI have awesome wp cron commands but it's only allow run cron tasks manually (yep, we can use --url attr). For example:

wp cron event list --url=multisite.com
wp cron event list --url=subdomain.multisite.com
  • Have you taken a look at WP-CLI core code? – kaiser Nov 3 '14 at 1:36
  • Yes. I dig into the source code right now and trying to understand :) Command to run all tasks (events) not exists, maybe I can create it in future. – Kolya Korobochkin Nov 4 '14 at 13:27
  • Do you have wp/WP-CLI in your PATH? If yes, why not trigger that from a bash file running in cron? – kaiser Nov 4 '14 at 13:38
  • Sounds great! But how to run all cron tasks from wp cli? I don't see any commands for this. – Kolya Korobochkin Nov 15 '14 at 14:45
  • Exactly as you have shown at the end of your question? – kaiser Nov 16 '14 at 12:38

I think the best way is to use WP-CLI but you'd need to write a bash script to do this. Here is one that should do it for you:

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}')
    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}')
        wp cron event run "$EVENT_HOOK" --url="$SITE_URL" --path="$WP_PATH"

You'd then need to add this script to crontab and run it maybe every minute if you like

  • Hm thank you for your opinion but I think this is hacky (dirty) solution. I think will be better write some PHP addon for wpcli which just run all needed tasks. I need more time to understand WP functions and code to do it. – Kolya Korobochkin Jan 31 '15 at 14:15
  • 7
    @KolyaKorobochkin I disagree. This isn't hacky at all since WP CLI was made to be used on the command line and in bash scripts. – DiverseAndRemote.com Dec 3 '15 at 18:15
  • 1
    wp cron event run --due-now --url="$SITE_URL" --path="$WP_PATH - According to the run docs, you should utilize the --due-now flag. This would reduce the lookups and individual event calls. See: wp-cli.org/commands/cron/event/run. Either way, I'm with @OmarJackman - he's utilizing the command line to use WordPress command line tools. Props for a clean Bash example. You could round out this answer by showing the crontab entry. – jgraup Sep 14 '16 at 16:18
  • 1
    For the benefit of future readers, the script then looks like: 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 – puzzlement Apr 16 '17 at 0:44

After you've added the constant in wp-config.php

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


And assuming you have your config.yml setup correctly, you can ommit the --path flag when calling cron run.

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.

To run all due cron tasks in order:

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;

If you want them to run concurrently (running the non-site-specific cron first):

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;

You would want to put either option in an executable file

chmod +x run_all_wp_cron_events_due_now.sh

add a crontab task

crontab -e

and probably execute each minute

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

If you want to run a custom command from cron, you might need to specify the full paths for wp-cli to work.

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


The only reason you would need to load up WordPress here is to gather the URLs from the database rather than using a pre-defined list. We're only going to ping those URLs and we don't really care what the response is.



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

And add a single call to your custom-cron.php in a crontab

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

Easier one-liner with less bash:

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

You can either run it manually or put it in a script and call it from cron as in the other answers.

  • Exactly what I was looking for - works just as advertised, thanks! – kero Oct 15 '20 at 11:19
  • This is a much smarter use of the available tools in WP CLI than the answers that are going through a lot of effort to parts out the results of the CSV output. Works great! – squarecandy Apr 17 at 3:45

This is my solution:

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;
  if (!$host)
  if (!isset($_SERVER['HTTP_HOST'])) {
       $_SERVER['HTTP_HOST'] = $host;  // replace with primary host

  require './wp-cron.php';

function shutdown()

We call this from crontab, hope it helps


I think you need to tell us what you mean by "run wp-cron.php the right way" first and foremost. According to Wordpress, it doesn't make sense that you disable wp-cron and yet want it to run... From the Linux perspective, wget-ing or /bin/php-ing wp-cron.php would be correct, but it seems your particular host is limiting your number of php invocations for security reasons? -- that part isn't completely clear from your description.

Another question: how many emails are "a ton"? There are great reasons why you shouldn't try to send too many emails that quickly.

You may have to re-think your objectives.

(I would comment instead of replying but I don't have enough reputation on wpstack.)

  • 5
    There are multiple ways of running the WordPress cron. The built-in mechanism is triggered by page views, and it's common practice to set DISABLE_WP_CRON to disable this method when setting up the more reliable system cron method instead. – Marcus Downing Jul 11 '16 at 14:28
  • The question is not why to do it/if the reasons are meaningful but how to correctly call wp-cron.php on a multisite installation. Quite clear for me ;) – Philipp Oct 26 '17 at 20:26
  • 2
    I hope you realize you're commenting on a very old and already hidden answer. – Jorge Orpinel Oct 27 '17 at 21:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.