Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403] [Versions 402 and 403]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * CLI task execution.
  19   *
  20   * @package    core
  21   * @subpackage cli
  22   * @copyright  2014 Petr Skoda
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  define('CLI_SCRIPT', true);
  27  
  28  require(__DIR__ . '/../../config.php');
  29  require_once("$CFG->libdir/clilib.php");
  30  
  31  list($options, $unrecognized) = cli_get_params(
  32      [
  33          'help' => false,
  34          'list' => false,
  35          'execute' => false,
  36          'showsql' => false,
  37          'showdebugging' => false,
  38          'force' => false,
  39          'disable' => false,
  40          'enable' => false,
  41      ], [
  42          'h' => 'help',
  43          'f' => 'force',
  44      ]
  45  );
  46  
  47  if ($unrecognized) {
  48      $unrecognized = implode("\n  ", $unrecognized);
  49      cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
  50  }
  51  
  52  $commands = ['list', 'execute', 'disable', 'enable'];
  53  $hascommand = count(array_filter($commands, fn($command) => $options[$command])) > 0;
  54  if ($options['help'] || !$hascommand) {
  55      $help =
  56      "Scheduled cron tasks.
  57  
  58      Options:
  59      --disable=\\some\\task  Disable scheduled task
  60      --enable=\\some\\task  Enable scheduled task
  61      --execute=\\some\\task  Execute scheduled task manually
  62      --list                List all scheduled tasks
  63      --showsql             Show sql queries before they are executed
  64      --showdebugging       Show developer level debugging information
  65      -h, --help            Print out this help
  66      -f, --force           Execute task even if cron is disabled
  67  
  68      Example:
  69      \$sudo -u www-data /usr/bin/php admin/cli/scheduled_task.php --execute=\\core\\task\\session_cleanup_task
  70  
  71      ";
  72  
  73      echo $help;
  74      die;
  75  }
  76  
  77  if ($options['showdebugging'] || !empty($CFG->showcrondebugging)) {
  78      set_debugging(DEBUG_DEVELOPER, true);
  79  }
  80  
  81  if ($options['showsql'] || !empty($CFG->showcronsql)) {
  82      $DB->set_debug(true);
  83  }
  84  if ($options['list']) {
  85      cli_heading("List of scheduled tasks ($CFG->wwwroot)");
  86  
  87      $shorttime = get_string('strftimedatetimeshort');
  88  
  89      $tasks = \core\task\manager::get_all_scheduled_tasks();
  90      echo str_pad(get_string('scheduledtasks', 'tool_task'), 50, ' ') . ' ' . str_pad(get_string('runpattern', 'tool_task'), 17, ' ')
  91          . ' ' . str_pad(get_string('lastruntime', 'tool_task'), 40, ' ') . get_string('nextruntime', 'tool_task') . "\n";
  92      foreach ($tasks as $task) {
  93          $class = '\\' . get_class($task);
  94          $schedule = $task->get_minute() . ' '
  95              . $task->get_hour() . ' '
  96              . $task->get_day() . ' '
  97              . $task->get_day_of_week() . ' '
  98              . $task->get_month() . ' '
  99              . $task->get_day_of_week();
 100          $nextrun = $task->get_next_run_time();
 101          $lastrun = $task->get_last_run_time();
 102  
 103          $plugininfo = core_plugin_manager::instance()->get_plugin_info($task->get_component());
 104          $plugindisabled = $plugininfo && $plugininfo->is_enabled() === false && !$task->get_run_if_component_disabled();
 105  
 106          if ($plugindisabled) {
 107              $nextrun = get_string('plugindisabled', 'tool_task');
 108          } else if ($task->get_disabled()) {
 109              $nextrun = get_string('taskdisabled', 'tool_task');
 110          } else if ($nextrun > time()) {
 111              $nextrun = userdate($nextrun);
 112          } else {
 113              $nextrun = get_string('asap', 'tool_task');
 114          }
 115  
 116          if ($lastrun) {
 117              $lastrun = userdate($lastrun);
 118          } else {
 119              $lastrun = get_string('never');
 120          }
 121  
 122          echo str_pad($class, 50, ' ') . ' ' . str_pad($schedule, 17, ' ') .
 123              ' ' . str_pad($lastrun, 40, ' ') . ' ' . $nextrun . "\n";
 124      }
 125      exit(0);
 126  }
 127  
 128  if (moodle_needs_upgrading()) {
 129      mtrace("Moodle upgrade pending, cannot manage tasks.");
 130      exit(1);
 131  }
 132  
 133  if ($disable = $options['disable']) {
 134      if (!$task = \core\task\manager::get_scheduled_task($disable)) {
 135          mtrace("Task '$disable' not found");
 136          exit(1);
 137      }
 138  
 139      try {
 140          $task->disable();
 141          mtrace("Disabled '$disable'");
 142      } catch (Exception $e) {
 143          mtrace("$e->getMessage()");
 144          exit(1);
 145      }
 146  } else if ($enable = $options['enable']) {
 147      if (!$task = \core\task\manager::get_scheduled_task($enable)) {
 148          mtrace("Task '$enable' not found");
 149          exit(1);
 150      }
 151  
 152      try {
 153          $task->enable();
 154          mtrace("Enabled '$enable'");
 155      } catch (Exception $e) {
 156          mtrace("$e->getMessage()");
 157          exit(1);
 158      }
 159  } else if ($execute = $options['execute']) {
 160      if (!$task = \core\task\manager::get_scheduled_task($execute)) {
 161          mtrace("Task '$execute' not found");
 162          exit(1);
 163      }
 164  
 165      if (!get_config('core', 'cron_enabled') && !$options['force']) {
 166          mtrace('Cron is disabled. Use --force to override.');
 167          exit(1);
 168      }
 169  
 170      \core\task\manager::scheduled_task_starting($task);
 171  
 172      // Increase memory limit.
 173      raise_memory_limit(MEMORY_EXTRA);
 174  
 175      // Emulate normal session - we use admin account by default.
 176      \core\cron::setup_user();
 177  
 178      // Execute the task.
 179      \core\local\cli\shutdown::script_supports_graceful_exit();
 180      $cronlockfactory = \core\lock\lock_config::get_lock_factory('cron');
 181      if (!$cronlock = $cronlockfactory->get_lock('core_cron', 10)) {
 182          mtrace('Cannot obtain cron lock');
 183          exit(129);
 184      }
 185      if (!$lock = $cronlockfactory->get_lock('\\' . get_class($task), 10)) {
 186          $cronlock->release();
 187          mtrace('Cannot obtain task lock');
 188          exit(130);
 189      }
 190  
 191      $task->set_lock($lock);
 192      if (!$task->is_blocking()) {
 193          $cronlock->release();
 194      } else {
 195          $task->set_cron_lock($cronlock);
 196      }
 197  
 198      \core\cron::run_inner_scheduled_task($task);
 199  }