Last Updated on September 21, 2023 EDT by Jordan
Table of Contents
- What is the WP-Cron
- First Step, Disable the WordPress WP-Cron From Running on Page Visits
- Choose a Method for Running WordPress Cron
- Additional Options
- Conclusion
- Resources
- Changelog
Content Error or Suggest an Edit
Notice a grammatical error or technical inaccuracy? Let us know; we will give you credit!
What is the WP-Cron
The WordPress WP-Cron is used to run scheduled tasks within WordPress core, as well as plugins such as WooCommerce.
The WordPress WP-Cron will run on each page visit by a visitor, this can result in the WP-Cron running multiple times on busy sites and con under up slowing down
The WordPress cron will run automatically when a visitor visits your site. This can cause an unnecessary load on your server or slow down the single request and result in a slower load time of your site.
A popular option is to disable the automatic WordPress cron, and replace it with a manual cron. Below are two methods to achieve this.
First Step, Disable the WordPress WP-Cron From Running on Page Visits
This is required, and simple edit of your wp-config.php. Locate the following line below, and change it from false to true. You may not have it in your wp-config.php; simply add it above the line “/* That's all, stop editing! Happy publishing. */
“.
define('DISABLE_WP_CRON', 'true');
Choose a Method for Running WordPress Cron
Method #1 – WordPress Cron using wget/curl
Most articles talking about using the Linux crontab to run the WP-Cron will reference using wget or curl. There are a couple of issues with this that I’ve highlighted below.
Issue 1 – Network, DNS and SSL Issues
The issue with wget/curl is that you’re adding networking overhead, potentially going through multiple firewalls, WAF’s like Cloudflare, and Wordfence. You’re also dependent on local DNS resolution and the domain name resolving correctly. DNS can have issues, it’s not invincible. The same is true of SSL, if your SSL expires then, of course, there are bigger issues.
If there is an issue with any of these, your WP-Cron won’t run.
Issue 2 – Long Running Request and Timeouts
Networking has timeouts, and as such if a request is taking too long and reaches the timeout the request is closed or terminated. There are timeouts everywhere, including your WAF and your own webserver. Again with longer running processes, you’ll see issues and potentially a cron that never finishes completely at times which can cause issues for time-sensitive actions on larger sites. Granted the cron will re-run from where it last finished, but if the connection was terminated during a function that doesn’t complete, then the task is incomplete. If the task was a daily task, it would not run again until the next day.
Issue 3 – Potential for a DDoS attack.
This doesn’t really seem to be something anyone talks about. Providing a web endpoint that will cause an increase in resources is an opportunity for a DDoS attack. You can eat up connections, or increase the host’s resources.
The Solution to wget or curl Issues?
There isn’t a solution to the timeouts, you can increase your timeouts on PHP and your webserver but they’re still a limit and not infinite until the request is completed. Increasing timeouts can also potentially leave you susceptible to a DDoS attack, using up all your connections. One thing is sure, don’t use wget, use curl instead, which I’ll explain below.
Look at using wp-cli and run cron events, or you could simply send the request locally to the web server versus out to the internet and back. You can use the –header option in curl to send a request to the local web server at localhost/127.0.0.1 versus using the domain name or DNS of the site. Then block requests to wp-cron.php from anywhere but localhost/127.0.0.1 Here’s an example of block requests to wp-cron.php at Cloudflare or your WAF.
curl -L -k --header "Host: managingwp.io" https://127.0.0.1
It’s important that you use -L, as it will follow redirects. And -k is required as it will not verify the SSL certificate common name and the URL being used, which will mismatch due to the certificate common name being managingwp.io and the URL being https://127.0.0.1
The Benefits of wget or curl Method?
There is one benefit to using wget/curl, you’ll be able to utilize opcode caching to speed up these requests. Granted on smaller sites the speed up might not be much, on larger sites it might save you 30 seconds of 100% CPU usage (PHP will use as much CPU as possible).
You do have to make sure that you configure your OPCode cache settings correctly. You’ll need to make sure all files are cached, and that requires quite a bit of memory, which might not be possible in some instances.
Method #2 – WordPress Cron using WP-CLI (Preferred Method)
This is the preferred method since it will work if there are DNS and other network issues.
*/5 * * * * /usr/local/bin/wp --path=/var/www/managingwp.io/htdocs cron event run --due-now > /dev/null 2>&1
Method #3 – Execute cron.php using PHP CLI
Another method is to use PHP via the CLI and execute cron.php as shown below
*/5 * * * * /usr/local/lsws/lsphp74/bin/lsphp /home/managingwp.io/public_html/cron.php > /dev/null
There may be reasons for this, but I don’t personally utilize this method.
Additional Options
Logging WordPress Cron
If you want to log to a file, you can add the following; just make sure the user running the cron has access to the log file.
*/5 * * * * /usr/local/bin/wp --path=/var/www/managingwp.io/htdocs cron event run --due-now >> /var/log/wp-cli-cron.log 2>&1
Logging Cron Run Times
If you have a heavily trafficked site, you might need to log the run times of your WordPress cron. You can do so with the following code.
*/5 * * * * time /usr/local/bin/wp --path=/var/www/managingwp.io/htdocs cron event run --due-now >> /var/log/wp-cli-cron.log 2>&1
The above code will time the run of your WordPress cron and each task, and provide the following output.
0.65s user 0.14s system 93% cpu 0.850 total
Monitoring your WP-Cron
You can monitor your WP-Cron using something called a heartbeat monitor, which is something that comes with certain monitoring platforms.
Better Uptime Heartbeat Monitoring
If you have Better Uptime (Affiliate Link) you can monitor your cronjob run using the following command.
*/5 * * * * /usr/local/bin/wp --path=/var/www/managingwp.io/htdocs cron event run --due-now && curl https://betteruptime.com/api/v1/heartbeat/v25v234v4634b636v3 > /dev/null
They also provide an example using a script which is actually better for catching errors.
Cronitor Monitoring
Another popular cron monitoring service is Cronitor which will monitor and alert you if your cronjob takes too long to run, fails to run and etc.
Effectively giving you a total run time and CPU usage utilized. This can help for troubleshooting.
WordPress Cron and Linux Cron Shell Shim
I’ve created this script that you can use as a shim between the Linux cron and wp-cli and do the following.
- Utilizes wp-cli cron command to run all cron events.
- Automatically detects webroot (htdocs/public_html) if one level below WordPress Root.
- Checks if WordPress root exists and is a WordPress installation.
- Logging to a file or syslog with a tag and domain name of the WordPress instance using wp-cli options
- Log includes output and errors, date and time, how long the cron ran for and the CPU time.
- Can specify a heartbeat URL for monitoring (BetterUptime/Uptimerobot)
- Post command that can be run afterwards which can be another script or curl to post to a webhook.
Monitoring WordPress Cron using a Must-Use Plugin
The following article provides instructions on how to use a must-use plugin and Betteruptime's Heartbeat feature.
Conclusion
As mentioned above using wp-cli to run your WordPress cron is the preferred method as it will bypass DNS, SSL and timeouts from PHP and your webserver.
Resources
Changelog
- 04-21-2023 - Added link to Github repository containing cron-shim.sh
- 04-13-2023 - Corrected some typo's and incorrect code. Added Resources section. Added cron-shim script.
- 08-25-2022 - Added Cronitor and Logging Cron Run Times sections.
- 09-21-2022 - Taken out of draft.
Last Updated on September 21, 2023 EDT by Jordan