The wp-cron.php
script for WordPress handles various scheduled events (such as checking for updates, publishing scheduled posts and more). By default this will be executed at each page load (to check if anything needs to be done). A common recommendation is to disable this and instead run it as a cron job.
We deal with a lot of high-traffic and demanding sites at Kinsta. Because of this, we’ve seen a lot of performance issues with the WordPress built-in Cron handler: WP-Cron. First off, it’s important to understand that WP-Cron is not a real cron job, it’s simply what WordPress has created to mimic what a system cron does.
https://kinsta.com/knowledgebase/disable-wp-cron/
wp-cron.php is the WordPress task scheduler, that takes care of things like checking for updates and publishing scheduled posts.
https://my.kualo.com/knowledgebase/65_wordpress/1295_why-and-how-to-disable-the-wordpress-wp-cron.php-and-set-it-as-a-real-cron-job-within-cpanel.html
It runs on every single page load.
If your website has not been visited in a while, it will have a lot of missed tasks to catch up which can greatly increase the loading time and could cause additional resource usage issues.
Rather than running this on a cron, I prefer to use a systemd timer.
Configuration Files
A timer and service unit need to be added to systemd. I prefer to run these as a user service so the service and timer files need to be located in ~/.config/systemd/user
. That folder will most likely not exist, so first create it:
mkdir -p ~/.config/systemd/user
Service File
Create the service next; the service is what will be executed by the timer. I name this service wp-cron
so it should be located in the file ~/.config/systemd/user/wp-cron.service
. The content of the service file:
[Unit] Description=Run WordPress cron After=network.target [Service] Type=simple WorkingDirectory=/home/mywebsite/public_html ExecStart=/usr/bin/php /home/mywebsite/public_html/wp-cron.php [Install] WantedBy=default.target
The WorkingDirectory
and ExecStart
lines will need to be adjusted for your specific environment.
Timer File
The timer which calls the service needs to be created. This should be located in the file ~/.config/systemd/user/wp-cron.timer
:
[Unit] Description=Run WordPress cron After=network.target [Timer] Persistent=false OnCalendar=minutely Unit=wp-cron.service [Install] WantedBy=timers.target
With the above OnCalendar
setting the WordPress cron will be executed every minute.
Enabling Timer
The timer now needs to be enabled and started:
systemctl --user enable wp-cron.timer systemctl --user start wp-cron.timer
To verify the timer is enabled and to see the next run time use the status command:
systemctl --user status wp-cron.timer
To verify the service actually ran, use the status command for the service:
systemctl --user status wp-cron.service
Once you have confirmed it is working, the WordPress configuration file (wp-config.php) needs to be adjusted to disable the cron. Edit the file and set the DISABLE_WP_CRON flag:
// Disable the WordPress cron // This is instead being executed as a systemd timer/service define('DISABLE_WP_CRON', true);
Common Problems
These are fixes for common problems.
Service not being executed if user is not logged in
By default (at least for Debian) users cannot have lingering processes. If the user is not logged in no user services/timers will run. To fix this use loginctl:
sudo loginctl enable-linger mywebsite