Troubleshooting WordPress wp_cron execution failures on Rocky Linux 9: Setting up native systemd-timer cron schedules
Diagnosing wp_cron Failures
WordPress’s built-in scheduler, wp_cron, is a critical component for tasks like publishing scheduled posts, checking for updates, and running various plugin/theme hooks. When wp_cron fails to execute reliably, it can lead to a cascade of operational issues. Common symptoms include scheduled posts not publishing, plugin notifications not appearing, and general site sluggishness due to deferred background tasks. The primary culprit is often the reliance on visitor traffic to trigger wp_cron. If a site has low traffic, or if the DISABLE_WP_CRON constant is set in wp-config.php (a common practice to prevent accidental execution during page loads), the scheduled events may never fire.
On a modern Linux distribution like Rocky Linux 9, the robust systemd suite provides a more reliable and deterministic way to schedule tasks. By disabling the default WordPress cron behavior and implementing native systemd timers, we can ensure that scheduled events run at precise intervals, independent of website traffic.
Disabling WordPress’s Default wp_cron
The first step is to prevent WordPress from attempting to run its cron jobs via HTTP requests. This is achieved by defining a constant in your wp-config.php file. It’s crucial to place this definition before the line that reads /* That's all, stop editing! Happy publishing. */.
Edit your wp-config.php file, typically located in the root directory of your WordPress installation:
define('DISABLE_WP_CRON', true);
With this line in place, WordPress will no longer attempt to trigger wp_cron on every page load. This is a necessary prerequisite for setting up an external scheduler.
Setting Up a Systemd Timer for wp_cron
We will create two systemd unit files: a .service file to define how to execute the WordPress cron script, and a .timer file to specify when and how often the service should run.
1. Creating the Systemd Service File
This service file will instruct systemd to execute the wp-cron.php script using the PHP interpreter. We’ll use wget or curl to simulate an HTTP request to the cron script, which is how WordPress expects it to be invoked when DISABLE_WP_CRON is true.
Create a new file named wp-cron-scheduler.service in the /etc/systemd/system/ directory. Replace your-domain.com with your actual website’s domain and adjust the User and Group to match your web server’s user (e.g., apache or nginx).
[Unit] Description=WordPress wp-cron.php scheduler for your-domain.com Wants=network-online.target After=network-online.target [Service] Type=oneshot User=apache Group=apache ExecStart=/usr/bin/wget -q -O - 'http://your-domain.com/wp-cron.php?doing_wp_cron=1' > /dev/null 2>&1 # Alternatively, using curl: # ExecStart=/usr/bin/curl --silent --compress 'http://your-domain.com/wp-cron.php?doing_wp_cron=1' > /dev/null 2>&1 [Install] WantedBy=multi-user.target
Explanation:
[Unit]: Defines metadata about the service.Wants=network-online.targetandAfter=network-online.targetensure the network is available before attempting to run the cron job.[Service]: Configures the service execution.Type=oneshot: Indicates that the service performs a single task and then exits.UserandGroup: Specifies the user and group under which the command will run. This should match your web server’s user to avoid permission issues.ExecStart: The command to execute. We usewget(orcurl) to fetchwp-cron.php. The?doing_wp_cron=1parameter is a standard way to signal to WordPress that this is a cron request. Redirecting output to/dev/nullkeeps the logs clean.
[Install]: Defines how the service should be enabled.WantedBy=multi-user.targetmeans it will be started when the system reaches the multi-user runlevel.
2. Creating the Systemd Timer File
This timer file will define the schedule for our service. Create a file named wp-cron-scheduler.timer in the same directory (/etc/systemd/system/). The timer file’s name must match the service file’s name (excluding the .service extension).
[Unit] Description=Run WordPress wp-cron.php scheduler every 15 minutes [Timer] OnCalendar=*:0/15 Persistent=true Unit=wp-cron-scheduler.service [Install] WantedBy=timers.target
Explanation:
[Unit]: A description of the timer.[Timer]: Configures the timer.OnCalendar=*:0/15: This is the core of the scheduling. It means “run every 15 minutes”. The format is flexible; for example,hourly,daily, or more complex calendar events can be specified.*:0/15translates to “every hour, at minute 0, 15, 30, 45”.Persistent=true: If the system was down when a timer was supposed to run, this option ensures that the job will run once as soon as possible after the system boots up.Unit=wp-cron-scheduler.service: Specifies which service unit this timer should activate.
[Install]: Defines how the timer should be enabled.WantedBy=timers.targetensures it’s started when the system’s timer management is ready.
Enabling and Managing the Systemd Timer
After creating the two unit files, we need to reload the systemd daemon to recognize them, enable the timer to start on boot, and then start the timer immediately.
Run the following commands as root:
sudo systemctl daemon-reload sudo systemctl enable wp-cron-scheduler.timer sudo systemctl start wp-cron-scheduler.timer
You can check the status of your timer and its next scheduled run with:
sudo systemctl status wp-cron-scheduler.timer
This will show you if the timer is active, when it last ran, and when it’s scheduled to run next. To see the output or any errors from the actual cron execution (the .service file), you can check the journal:
sudo journalctl -u wp-cron-scheduler.service
If you encounter issues, double-check the User and Group in the .service file, ensure the path to wget or curl is correct, and verify that http://your-domain.com/wp-cron.php is accessible from the server itself (e.g., using curl http://localhost/wp-cron.php).
Verifying wp_cron Execution
To confirm that your systemd timer is working correctly and that WordPress is processing events, you can:
- Schedule a Post: Create a new post and schedule it to publish a few minutes in the future. Verify that it publishes automatically at the scheduled time.
- Check Plugin/Theme Hooks: Some plugins or themes might have specific cron-related actions. Monitor their expected behavior.
- Inspect Logs: Regularly check the
systemdjournal for thewp-cron-scheduler.serviceand look for any errors. - WordPress Site Health: The WordPress Site Health tool (Tools > Site Health) often reports on scheduled events and can indicate if cron jobs are being missed.
By implementing this systemd timer-based approach, you move away from the unreliable, traffic-dependent wp_cron mechanism and establish a robust, predictable scheduling system for your WordPress site on Rocky Linux 9.
Leave a Reply
You must be logged in to post a comment.