Yikes! This post is over a year old!
If you think it deserves a rewrite please get in touch or leave a comment.
— Thanks, Ash.
What is WP-Cron?
The default configuration of the WordPress Cron system takes care of automated tasks, checking for updates, and publishing scheduled posts but it can’t always be relied upon to be on-time.
WordPress Core, Plugins and Themes can all register ‘events’ via the use of wp_schedule_eve
and scheduled events can be one-off or set to recur. nt
()
The way WordPress handles triggering these events is by relying on traffic to the website. Every time a user visits the website, WordPress will check to determine if there are any events due to be triggered. If any events are due (or in some cases, overdue), WordPress will attempt to execute them.
The downside to this default behavior is that if you experience a lull in traffic there’s no guarantee that your scheduled events will be executed on time.
This can present issues for site owners that are expecting certain events to execute at certain times. A good example that we commonly see at Mixd is things like press releases needing to be published at specific times.
To ensure your WP-Cron events trigger exactly when you need them to, you can make use tools like curl
to consistently send requests to your website forcing WordPress to execute it’s scheduled events in a much more predictable way.
The following steps should make it simplistic enough to convert your WordPress cron into a system cron on a Ubuntu web server.
Creating a crontab
On Ubuntu, cron tasks can be assigned to a particular user. For convenience we can ask the user that our web server runs as to take of this for us.
If you’re running a typical LAMP server, Apache usually runs as www-data
but you can find out which user Apache is running as by executing:
cat /etc/apache2/envvars | grep 'APACHE_RUN_USER'
Once you know which user you want to delegate the cron task to, you can set up a ‘crontab’ . To open the crontab for editing, for the www-data
user, run:
sudo crontab -e -u www-data
The -e flag means ‘edit’.
The -u flag determines which User’s crontab you want to operate on.
The crontab should now be open in your systems’ default command line text editor. For most cases, this’ll be nano
.
If this is the first time you’re adding a task to the system cron, the file will be empty.
Take this as a top tip. Include a MAILTO
as the first line in the file. This will make sure that you can get an email if there’s a problem with any future cron tasks. Simply substitute <your email here>
with your email address.
# Send the output of cron tasks to:
MAILTO=<your email here>
Once that’s in, you should work out how frequently you want to execute your cron task.
This is represented in the following format:m
(minute) h
(hour) dom
(day of month) mon
(month) dow
(day of week) command.
ProTip: use something like crontab.guru to calculate your format.
For WordPress; it’s worthwhile simply making it run every minute of every day. The format for this is:
# Run the following command once a minute
* * * * *
Now you know your format, you want to add your cron task.
Here’s one I made earlier. Simply swap out the domain name.
# Run the following command once a minute
* * * * * /usr/bin/curl -sSf ashdavies.online/wordpress/wp-cron.php > /dev/null
In my case, I’ve opted to use curl
. There’s a handful of command line flags that I’m using to reduce the output of the command. I only really want to be notified if there is a problem requesting the wp-cron.php
file.
Here are the flags: -s
= Silent or quiet mode, -S
= Show error on failure, -f
= Silent server errors
Once you’re happy with the task, press ctrl+x
& Y
to Save and Exit the crontab. As soon as the crontab has been saved it will take effect. To check if it is working you can watch the Apache access.log for the website you have just configured it for.
Note: You should probably wait at least the minimum amount of time you have defined in your system cron task to make sure it is running consistently.
For my above example, I will wait at least 2 minutes to ensure I can see the request in the log file.
tail /var/log/apache2/access.log | grep cron
"GET /wordpress/wp-cron.php HTTP/1.1" 200 "curl/7.58.0"
Once you can see the request in the access log consistently, then the System Cron is now enabled.
For WordPress, the last step is to edit the wp-config.php
file on the same server to disable the default WP-Cron scheduler.
Open up your wp-config.php
for editing and add:
define('DISABLE_WP_CRON', true);
Once this has been added, press ctrl+x
& y
to save your changes.
That’s it! The website is no longer using the built-in scheduler and is now reliant upon the system cron.