General
There is an extensive page on drupal.org for solving problems with cron: Solving cron problems .
There are a few modules aimed at helping debug cron. The one most commonly used is Cron debug .
If you're having problems with cron and search (or think you might be), see Debugging Cron / Search Indexing.
There are a number of ways explored here :
Drush
Drush offers a multitude of methods to troubleshoot cron and just about everything else.
Modules
The Drush Debug Tools are a group of extensions for Drush, written by Acquians, with more extensive cron debug capabilities.
Note that this is only for Drupal 7.
php-eval
You can debug cron by using the Drush utility using php-eval
.
The code below runs drush php-eval
using the respective functions :
- the module_implements() function (for Drupal 7) and
- the ModuleHandler::getImplementations() function (for Drupal 8)
It logs each part of cron as cron runs, and then outputs that to the terminal.
There is a version of drush php-eval
for Drupal 7 and Drupal 8 :
Drupal 7 Code
drush php-eval 'global $timers; $return = $args = array();foreach (module_implements("cron") as $module) { $function = $module . "_cron"; print($function ." - "); timer_start($function); $result = call_user_func_array($function, $args); if (isset($result) && is_array($result)) { $return = array_merge_recursive($return, $result); } else if (isset($result)) { $return[] = $result; } timer_stop ($function); print($timers[$function]["time"] ."\r\n");} '
This code will return results like:
ctools_cron - 9.74
field_cron - 83.14
node_cron - 3.91
search_cron - 1.97
system_cron - 1282.06
trigger_cron - 7.53
update_cron - 1036.85
Drupal 8 Code
drush php-eval 'use Drupal\Component\Utility\Timer;global $timers; $return = $args = array(); foreach (\Drupal::moduleHandler()->getImplementations("cron") as $module) { $function = $module . "_cron"; print("Starting execution of " . $module . " cron ... "); Timer::start($function);$result = call_user_func_array($function, $args);if (isset($result) && is_array($result)) {$return = array_merge_recursive($return, $result);} else if (isset($result)) {$return[] = $result;} Timer::stop($function); print("Execution of " . $module . " cron took " . Timer::read($function) . "ms\r\n"); }'
This code will return results like:
Starting execution of dblog cron .... Execution of dblog cron took 10.18ms
Starting execution of field cron ..... Execution of field cron took 11.19ms
Starting execution of file cron ..... Execution of file cron took 27.31ms
Starting execution of history cron ..... Execution of history cron took 0.91ms
Starting execution of node cron ..... Execution of node cron took 0.03ms
Starting execution of scheduled_updates cron ..... Execution of scheduled_updates cron took 43.72ms
Starting execution of search_api cron ..... Execution of search_api cron took 26.54ms
Starting execution of system cron ..... Execution of system cron took 20.58ms
Updater Publish multiple nodes at a certain time complete. Results: No updates were performed. [status]
Updater Publish single node at certain time complete. Results: No updates were performed. [status]
Modifying Drupal Core
Alternately, you can use the following code to help you debug cron. The code is a replacement function that goes in includes/module.inc
in place of the existing module_invoke_all() function (for Drupal 7). It logs each part of cron as cron runs, and then logs that to the system log.
There is a version for Drupal 7 :
<?php
/**
* Invokes a hook in all enabled modules that implement it.
*
* @param $hook
* The name of the hook to invoke.
* @param ...
* Arguments to pass to the hook.
*
* @return
* An array of return values of the hook implementations. If modules return
* arrays from their implementations, those are merged into one array.
*/
function module_invoke_all($hook) {
$args = func_get_args();
// Remove $hook from the arguments.
unset($args[0]);
$return = array();
foreach (module_implements($hook) as $module) {
// BEGIN CRON LOG
if ($hook == "cron") {
watchdog('cron', 'Running cron for: %module', array('%module' => $module), WATCHDOG_NOTICE);
}
// END CRON LOG
$function = $module . '_' . $hook;
if (function_exists($function)) {
$result = call_user_func_array($function, $args);
if (isset($result) && is_array($result)) {
$return = array_merge_recursive($return, $result);
}
elseif (isset($result)) {
$return[] = $result;
}
}
}
return $return;
}
?>
This file is able to be downloaded also.