Blog

How to develop your own WordPress CRON job properly and ensure it actually runs

Hello! In this post we will be walking through how to interact with the WordPress Cron system. We will delve into how to establish your scheduled jobs properly using the built-in WordPress cron system, with no other external interactions such as the OS cronjob system. This will be useful for WordPress plugin developers as in order to develop a plugin that utilizes reliable scheduled tasks, you need to accommodate many different types of web hosting environments.

What is CRON?

In linux, this would be a command line utility that allows the end user to schedule jobs to run at specific days and times on a repeating basis. You can write your own script and have the operating system run it on a nightly basis. Systems Administrators use this often for things like backups, integrity checks and a wide array of use cases.

What is WordPress CRON?

Taking the same concept described above, WordPress has implemented their own cron system. This system allows plugin developers, theme developers and regular end users to utilize the scheduled task system built into WordPress in order to run whatever jobs you see fit. If you aren’t a developer you may utilize a 3rd party plugin to be able to interact with the WordPress cron system and create/manage the jobs.

Having a scheduling system to perform time based tasks is important for so many reasons. It could be just for data pruning, or maintenance or so many things. The main difference with the built-in WordPress cron system and other cron implementations is that the WordPress system is dependent on a page load in order to trigger and initiate a task. So if you schedule your task to run at midnight but nobody visits your site until 12:15AM, that is when the task will run.

How to create your own custom cron schedule

First of all its important to highlight that there are many ways to create and submit a cron job to the WordPress cron scheduling system. Before you do that we need to understand that we need a mechanism to ensure we only have one submission per job. No matter where the mechanism to create the job will live, we need to check if a job exists before submission :

	if ( ! wp_next_scheduled( 'shift8_single_action' ) ) {
		wp_schedule_event( time(), 'hourly', 'shift8_single_action' );
	}

Whats happening in the above snippet? Well we are basically wrapping the WordPress wp_schedule_event function in a condition that ensures the job doesnt already exist. If no such job exists, it will create one.

How to ensure your WordPress cron job actually runs

Now that we figured out how to actually create a cron job in WordPress with a proper condition that ensures only one job is created, we want to start building the logic and code to actually run the function that the cron job will trigger.

Before we get to that I would recommend reading more about the WordPress hook firing sequence. Why this is important is because we want to create a function within the init sequence. If you choose another sequence to fire off all this logic (as you will understand better once you read the code snippet below), then you need to make sure that any dependent functions or hooks that you might use in your actual function will be available during that hook, within the sequence.

Luckily the “init” sequence, most of WordPress is loaded including authentication and 3rd party plugins.

add_action( 'init', function () {
	if ( ! wp_next_scheduled( 'shift8_single_action' ) ) {
		wp_schedule_event( time(), 'hourly', 'shift8_single_action' );
	}

	add_action( 'shift8_single_action', 'shift8_custom_cron_function' );

	function shift8_custom_cron_function() {
		// Whatever custom code you want executed in the cron job
	}
} );

What are we doing with the above code snippet? Well we are expanding on the snippet earlier in this post. We are wrapping the entire cron job block into an init function to ensure everything runs correctly. We found that , depending on what you are doing in the function you are trying to schedule, sometimes the cron task wouldn’t run succesfully.

Now within the init hook you can see we are scheduling an event that references an action that in turn triggers a custom function. In that function (shift8_custom_cron_function) is where you put whatever you need your scheduled job to do.

How to create custom WordPress cron schedule intervals

What if the standard scheduling intervals (hourly, twice daily, daily, weekly) that WordPress provides is not sufficient? Easy! You can create your own schedule interval with whatever schedule you want :

// Custom cron intervals
add_filter( 'cron_schedules', 'shift8_add_cron_interval' );
function shift8_add_cron_interval( $schedules ) { 
    $schedules['ten_minutes'] = array(
        'interval' => 600,
        'display'  => esc_html__( 'Every Ten Minutes' ), 
    );
    $schedules['ten_seconds'] = array(
        'interval' => 10,
        'display'  => esc_html__( 'Every Ten Seconds' ), 
    );
    return $schedules;
}

You can see in the snippet above that the interval is per-second so whatever time you want in seconds would work. Remember again that cron tasks (unless your web host is triggering cron manually) are triggered when someone visits your site. So if you are expecting a task to run hourly, it might run at 1.5 hours if the next visitor doesnt hit the site until then.

How to confirm your WordPress cron job is actually scheduled

You can utilize WP-CLI to quickly confirm that your cron job is actually scheduled within the WordPress cron system. If your code in your theme’s functions.php file looks similar to whats demonstrated above in this post, then you can trigger the cron job creation by visiting your site. Subsequent to that, you can utilize WP-CLI to confirm that the task is indeed created :

wp cron event list

Then in the list that is output from the command above, check for the name of your cron job (in our case it would be “shift8_single_action”).

How to debug your WordPress cron jobs and ensure they are actually running

Debugging whether a cron task runs is sometimes tricky because there is no formalized output that can be easily debugged. There are a few methods that I would suggest that you could use to debug your cron job function to ensure it is actually running or to determine if there are problems.

One such method would be to utilizing error log output. This would leverage the existing OS configured error log for the cron job. In our case it would be within the nginx vhost site error_log file that is configured. You could also simply send debug output to a text file to determine that things are actually running.

Common problems with WordPress cron jobs not running

The first thing that you should check is if the cron job will run if you trigger it with WP-CLI directly :

wp cron event run shift8_single_action

Next, depending on what your function is doing, you need to confirm that you have the correct user permissions to do what your doing. For example one such scheduled job we created purged an uploads folder and any sub folders under the parent folder. Since the user running your cron task would be the same user that the web servies is running under, you need to ensure that that user/group has the correct permissions on the folder structure to carry out its tasks.

Lastly, are you using the right hook in the WordPress hook sequence? If your function isnt living in the init function, perhaps referencing the sequence order and what is available in said sequence order is a good step to determining that you are using functions and hooks that are available.

I hope this post is helpful to other people out there that may be looking to create reliable and stable WordPress scheduled cron jobs!