By: Raman
June 6 2018

Configuring Cron with Drupal 8

If you are familiar with UNIX or Linux, you may recall cron as a daemon, or a background process which is used to schedule tasks at regular intervals of time. These tasks or “cron jobs” are generally performed on servers and they include backing up of databases and other files, clearing up logs, sending system reports or newsletters, and so on. They are defined inside a crontab file and are represented as the following expression.

 # minute hour day_of_month month day_of_week command
 
 # For example, to take daily database backups at 00:00 using drush
 
  0 0 * * * /usr/bin/drush sql-dump --gzip --result-file="/path/db_`date '+%Y_%m_%d'`.sql"

Now, when it comes to Drupal, the purpose of cron is similar, but its implementation is different. Drupal’s automated cron is a core module and it is different from the cron available on UNIX like operating systems. 
The automated cron registers an Event Subscriber. Whenever a request is made on our Drupal site, a piece of code is executed. Digging into some of this code, we can see that, if enabled, the automated cron executes the scheduled jobs or tasks only when the difference between the timestamps of last request and the cron’s last execution is greater than the cron’s configured interval.

 $interval = $this->config->get('interval');
 if ($interval > 0) {
   $cron_next = $this->state->get('system.cron_last', 0) + $interval;
   if ((int) $event->getRequest()->server->get('REQUEST_TIME') > $cron_next) {
     $this->cron->run();
   }
 }

The Drupal’s automated cron is used by many core and contributed modules. If you dig further into the run method, you will observe that it mainly does two things – executes the hook_cron and processes the queue workers of all the core and contributed modules. We will come back to this later and see how we can implement them in our custom module.

What is Drupal Cron used for?

Many core and contributed modules use cron to perform regular maintenance work. All these jobs are performed whenever cron executes. However, you have to allocate different time period to every cron job. Few of them are described below.

Module

Type

Job

dblog

Core

Remove expired log messages and flood control events

Field

Core

Purges deleted Field API data

History

Core

Deletes history

Search  

Core

Updates indexable active search pages

Scheduler

Contributed

Publish or unpublish nodes

System

Core

Cleanup (caches, batch, flood, temp-files, etc.)

Update

Core

Checks for updates

How to execute cron?

Now that we understand what cron is and what it is used for, let us see how we can execute cron and perform these jobs.

  1. Automated execution
    By default, cron is set to execute after every 3 hours. This duration can be increased or decreased, and this automated execution can be disabled as well. If detailed logging is enabled, the execution time and all the hook_cron will be logged in the log messages,
     
    Configuring interval of cron
    Configuring interval

    But as discussed earlier, this will occur only when your site is active. If your site does not get any requests, then cron will never execute.

  2. Manual execution
    If you want to execute manually there are 4 ways to do so:

    1. Using Admin UI
      Navigate to Manage → Configuration → System → Cron and click on “Run Cron”Running cron manually

    2. Using Secret key
      Cron can also be executed from outside the site using the secret key and making a request at cron/{your-secret-key}. Your secret key will be available at admin/config/system/cron.

      $ wget -q -O /dev/null "{your-drupal-site}/cron/{your-secret-key}"
      # Or
      
      $ curl -s -o /dev/null "{your-drupal-site}/cron/{your-secret-key}"
    3. Using Drush
      $ drush cron

    4. Using Drupal Console
      $ drupal cron:execute # or use an alias - croe or cre

  3. Executing it using system cron
    It is recommended to use the system cron over Drupal’s automated whenever possible. If you depend on Drupal cron to perform some important jobs, you may want to disable the automated cron entirely and use system cron to execute Drupal cron. This way you can get the best of both worlds.

    If you have access to your server through SSH, you can open up crontab file using crontab -e and add the following cron expression to execute cron in, let’s say every hour.
     0 * * * * cd /var/www/html/drupal8 && /usr/bin/drush cron 
    
     # or execute cron from outside the website 
    
     0 * * * * wget -q -O /dev/null "{your-drupal-site}/cron/{your-secret-key}"
    
     # or
    
     0 * * * * curl -s -o /dev/null "{your-drupal-site}/cron/{your-secret-key}"
    Some hostings like cPanel even provide a GUI to set up cron jobs. But if your hosting does not allow you to run system cron, you can use webcron services like cronless or EasyCron.

Implementing Cron Jobs in a Custom Module

You can implement jobs in your custom module. They will be executed whenever cron executes. There are two ways to do this – using hook_cron and using queue workers.

  1. Using hook_cron
    Implement hook_cron in the .module file just like any other hook. 
    /**
     * Implements hook_cron().
     */
     function custom_module_cron() {
      // your job here
     }
    Note that cron will execute all the hook_cron implementations one by one and if there is any error, its execution will stop and remaining hook_crons will not be executed. Also, since a page request fires the event to trigger cron execution, if your job takes time, it will result in poor response time. You may want to explore a contributed module, Ultimate cron if you want to execute the jobs parallelly.
     
  2. Using QueueWorkers and Queues
    For jobs that require longer processing time, we can add them to queues. We need to define a QueueWorker plugin in the /src/Plugin directory of our module by extending the QueueWorkerBase class and implementing the processItem method.

To Conclude

Drupal cron is a pseudo cron and is usually used to perform regular maintenance jobs. It is often referred to as “poor man’s cron” as it depends on page requests for its execution and is mostly used when your hosting does not allow you to run system cron. Hence, use the system cron whenever possible to perform any important jobs.