Jan 29

Run Wordpress tasks from real cron job

Category: How-To
Tags: ,,

I had to pull off my sleeves, open WP code and see by myself because all I finally found was this article (well I must admit that it was very helpful):
http://wordpress.org/support/topic/273381

To explain, in short, how Wordpress crons are working, here is a shortened call stack:

  • Web User Request
  • => WP API initialisation
  • ==> wp_cron()  // if authorized to run, the cron array is loaded (from a get_option call)
  • ===> spawn_cron()     // this is called if a job pending execution is found in the cron array.
  • ====> wp_remote_post(’wp-cron.php?doing_wp_cron’)     // the asynchronous call

wp_cron() is the function that initiate the process of executing the jobs if one needs to be executed.  And wp-cron.php is the one that will, at the end, execute those jobs.

wp_cron function code

In order to run the jobs from a real cron, it is simple as scheduling a wget call to wp-cron.php and disabling PHP calls to wp_cron() function.  Damn, if I knew that from beginning…  When you open the wp_cron() function declaration, you will notice that first line checks for a constant definition: DISABLE_WP_CRON.  So you define(’DISABLE_WP_CRON’, true) in your wp-config.php and that’s it.

Well, if you are using Wordpress MU, that’s not totally it. Remember the comments in the stack call above? The cron array is loaded from a function call to get_option.  In Wordpress MU, get_option reads data from wp_xx_options which is per blog database table.  So it has a set of scheduled tasks per blog.  So you need to call wp-cron.php in the context of each blog.  So it’s starting to bug me… I don’t want to do maintenance tasks everytime a blog is created in Wordpress MU!  To prevent this, I created a small php script that I called wp-cron-multi-blog.php that is calling wp-cron.php for each active blogs defined in Wordpress MU.

Here is a wrap-up of the information without the bells and whistles.  To run WP tasks from a real scheduled cron you should do this:

in wp-config.php, add the following line :

define('DISABLE_WP_CRON', true);

for a standard Wordpress installation, configure a crontab that:

  • wget http://www.server.com/wp-cron.php?doing_wp_cron

for a Wordpress MU installation, configure a crontab per blog like:

  • wget http://www.server.com/wp-cron.php?doing_wp_cron
  • wget http://www.server.com/whatever/wp-cron.php?doing_wp_cron
  • wget http://www.server.com/what-a-blogger/wp-cron.php?doing_wp_cron
  • ...

or, a single crontab calling my wp-cron-multi-blog.php (placed in root installation of WP):

  • wget http://www.server.com/wp-cron-multi-blog.php

A final note about wp-cron-multi-blog.php.  If your Wordpress MU installation has a lot of blogs and each of them tends to have many time consuming tasks (ex: cache cleaning), it may be a good idea to edit this script in order to limit the number of blogs to run for at one time.

Hope this helps.

Pascal.

Pages: 1 2

4 comments

4 Comments so far

  1. DS February 9th, 2010 11:17 am

    I implemented this in WPMU 2.9.1.1 with the wp-cron-multi-blog.php script and a /etc/crontab setup and it does not work at all for me. If I manually browse to the script, it reports back as if its working/doing something, but doesn’t appear to actually spawn the cron jobs.

  2. Pascal February 9th, 2010 9:12 pm

    Ok I will double-check it in case I did a copy/paste mistake.

    What are your cron jobs skipped? pre-publishing?

    Pascal.

  3. Helgi Hrafn Halldórsson February 17th, 2010 4:07 am

    Thank you for this post. It helped me alot :P

  4. מרק ק. March 3rd, 2010 10:43 pm

    You can probably make your script more efficient by managing the list of scheduled task, or the blog which has them, in a separate DB table.

    Another enhancement might be to directly call the WP cron task execution API, after calling switch_to_blog for the appropriate blog number.

Leave a comment