Every once in a while your plugin will require a time-based running schedule, for example you have a plugin that renews all Let’s encrypt certificates in a WordPress MU Network, however if you require reliability, you will realize that the built in wp-cron file is completely useless.
Why WP-Cron sucks
WP-cron is intended to schedule and run things like check for plugin and theme updates, publish scheduled posts and run plugin functions. The biggest downside of WP-cron is that it is triggered when a user visits the website…
- Problem – For small sites with low traffic that means that the code you hooked there might not actually trigger, making it very unreliable. For big sites with a lot of traffic the problem is different many visitors mean that a lot of cron processes will be started, piling on the CPU time.
- Problem – WP-Cron runs over HTTP request, which means that the unlucky user that triggers the cron might see some delays in the website(even worse if it is a Google bot as they do not like to wait).
- Problem – Memory and execution time. You cannot and must not run memory intensive and long running scripts through wp-cron. It is not designed for this and please, for the love of all that is sacred stop adding crazy max_execution_time and memory_limit values for the sake of some badly written code. It is unbecoming! 🙂
How to fix it
There are of course a few solutions to this problem one of which I’ll mention just to point out its utter uselessness. All solutions, however, require the following addition to wp-config.php
// wp-config.php - Right above - That's all, stop editing! Happy blogging. define( 'DISABLE_WP_CRON', true );
First solution – Using Linux cron and wget
I see a lot of people setting up the following cron job:
*/10 * * * * www-data wget https://yoursite.net/wp-cron.php > /dev/null 2>&1
Doing that you start right, by using Linux cron and remove the unreliability factor but still keep the HTTP request downsides.
Second solution – Stick to Linux cron but instead run wp-cron through PHP-CLI
Similarly to the previous one you set the following cron job:
*/10 * * * * www-data php /path/to/wp-cron.php > /dev/null 2>&1
Running the scheduled task in this way you get both reliability and stability, you can now run long running and memory intensive tasks.
Third solution – Using Linux cron and WP-Cli to schedule/run your actions
I’m using this for some custom projects involving WPMU networks and big batch processes and it works flawlessly. For this solution you will obviously need WP-Cli installed, which is as simple as running the following commands:
$ curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar $ chmod +x wp-cli.phar $ sudo mv wp-cli.phar /usr/local/bin/wp
Now the reason(one of many) this tool is useful is that you can schedule and run you actions with it. Lets say you have the action “renew_certificates” defined and want to run it twice a day.
0 6,18 * * * www-data /usr/local/bin/wp cron event run 'renew_certificates' --path=/path/to/wordpress/ > /dev/null 2>&1
and voila your code will run at 6 and 18 server time, you can also specify flags
–due-now – Run all hooks due right now.
–all – Run all hooks.
Great post.
If you’re on a shared host that cron job service is crap, you can be found a list of free online cron jobs services at: http://www.cronjobservices.com.