THE GOAL
Create a system cron for WordPress, that is accessible and can be easily tweaked to provide more details. Here some basic information about crons and the tools I am going to use …
WordPress CRON
In WordPress, the term “cron” refers to the system used for scheduling tasks to be executed at predefined intervals. The WordPress cron system allows various actions to be scheduled, such as publishing scheduled posts, checking for updates, sending email notifications, and running other scheduled tasks.
WordPress includes its own pseudo-cron system, which relies on visitors accessing your site. When a visitor loads a page on your WordPress site, WordPress checks if there are any scheduled tasks that need to be executed. If there are, it runs those tasks. This system works well for most sites, but it has limitations, particularly for low-traffic sites or sites that need precise scheduling.
To overcome these limitations, WordPress also provides the option to use a real cron system. With a real cron system, tasks are scheduled and executed independently of visitor traffic. This can be more reliable and precise than relying on visitors to trigger cron tasks.
To set up a real cron system for WordPress, you typically need to configure your server’s cron job scheduler to trigger the wp-cron.php file at regular intervals. This file handles the execution of scheduled WordPress tasks.
List scheduled WordPress events
WP Crontrol is a solid UI, to list and see whats happening in the background.
- View all cron events along with their arguments, recurrence, callback functions, and when they are next due.
- Edit, delete, pause, resume, and immediately run cron events.
- Add new cron events.
- Bulk delete cron events.
- Add and remove custom cron schedules.
- Export and download cron event lists as a CSV file.
WP-CLI
WP-CLI (WordPress Command Line Interface) is a powerful command-line tool that allows developers and administrators to interact with WordPress websites directly through the command line, without needing to use a web browser.
It provides a wide range of commands for managing various aspects of a WordPress site, such as executing crons / scheduled tasks, installing plugins, updating themes, managing users, and much more.
Most WordPress hosts have it preinstalled. Installation
Test CRON
1 2 3 4 5 |
# Test WP Cron spawning system $ wp cron test Success: WP-Cron spawning is working as expected. |
Run CRON
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Schedule a new cron event $ wp cron event schedule cron_test Success: Scheduled event with hook 'cron_test' for 2024-01-31 10:19:16 GMT. # Run all cron events due right now $ wp cron event run --due-now Success: Executed a total of 2 cron events. # Delete all scheduled cron events for the given hook $ wp cron event delete cron_test Success: Deleted 2 instances of the cron event 'cron_test'. # List scheduled cron events in JSON $ wp cron event list --fields=hook,next_run --format=json [{"hook":"wp_version_check","next_run":"2024-01-31 10:15:13"},{"hook":"wp_update_plugins","next_run":"2016-05-31 10:15:13"},{"hook":"wp_update_themes","next_run":"2016-05-31 10:15:14"}] |
ntfy.sh
ntfy (pronounced notify) is a simple HTTP-based pub-sub notification service. It allows you to send notifications to your phone or desktop via scripts from any computer, and/or using a REST API.
You can host your own docker instance or use the hosted solution.
The documentation is detailed and offers many ways to tweak the resulting notification.
Server CRON / THE OLD WAY
1 2 3 4 |
/** Disable virtual cron in wp-config.php */ define('DISABLE_WP_CRON', true); |
1 2 3 |
0 13 * * * wget -q -O - https://domain.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1 |
Server – CRON / THE NEW COMBINED WAY
I am not showing you how to create a system cron, that can vary depending on your hosting provider. Some of you will just setup / modify the crontab themselves. So here an example of how I use it these days …
1 2 3 |
*/30 * * * * OUTPUT=$(/bin/bash -c "/path/to/wp-cli/wp --path=/path/to/wp/install/ cron event run --url=https://your-website.com/if/multisite/ --due-now" 2>&1) && curl -u %ntfy_token% -H "Filename:your_cron_output.txt" -H "Title:Your Cron" -d "$OUTPUT" "https://ntfy.server.com/topic" |
Lets dissect this :)
Execution Timeframe – Minute / Hour / Day (month) / Month / Day (week)
See example usage on crontab.guru.
1 2 3 |
*/30 * * * * |
Capture the output
Im using a variable to capture the output, allowing me to pass it to ntfy.
1 2 3 |
OUTPUT=$() |
The command part 1
Use bash to launch wp-cli, passing in required parameters to make sure the right website is targeted.
I am using –due-now to only launch those schedules that are actually pending. >/dev/null 2>&1 prevents any emails to be send for this cron job, it redirects the error stream into the output stream. Always helpful to remove it for the first testdrive.
>/dev/null: redirects standard output (stdout) to /dev/null
2>&1: redirects standard error (2) to standard output (1), which then discards it as well since standard output has already been redirected :)
1 2 3 |
/bin/bash -c "/path/to/wp-cli/wp --path=/path/to/wp/install/ cron event run --url=https://your-website.com/if/multisite/ --due-now" >/dev/null 2>&1 |
The command part 2
This part sends the output to a ntfy instance / topic.
1 2 3 4 5 6 7 |
curl -u %ntfy_token% -H "Filename:your_cron_output.txt" -H "Title:Your Cron" -d "$OUTPUT" "https://ntfy.server.com/topic" |
- -u %token% login / auth with your token
- -H “Filename: …” this will move the body text into an attachment file. You can remove this and all output will be part of the body text. ntfy has a body message length limit and will shift to an attachment when reached.
- -H “Title: …” Title for the message
- -d “$Output” Set the body message to the output we captured, using the set variable
- Finally the url to post to, the ntfy instance and topic.
You can set many other things as well, like tags, images …. Check the documentation about publishing for more options. You can even redirect to an email account ;)
Detecting WP-CLI execution programmatically
1 2 3 4 5 |
if ( defined( 'WP_CLI' ) && WP_CLI ) { // Do WP-CLI specific things. } |
Detecting WP-CRON execution programmatically
1 2 3 4 5 6 |
if ( defined( 'DOING_CRON' ) ) { // Do something } |
Enjoy coding …
Alex