Skip to content

Commit

Permalink
Add maint mode commands (#5383)
Browse files Browse the repository at this point in the history
* Add maint mode commands

* Add more docs
  • Loading branch information
weitzman authored Feb 15, 2023
1 parent a265292 commit 87480ba
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 2 deletions.
8 changes: 6 additions & 2 deletions docs/cron.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
Running Drupal cron tasks from Drush
====================================

Drupal cron tasks are often set up to be run via a wget call to cron.php; this same task can also be accomplished via the [cron command](commands/core_cron.md), which circumvents the need to provide a web server interface to cron.
Drupal cron tasks are often set up to be run via a wget/curl call to cron.php; this same task can also be accomplished via the [cron command](commands/core_cron.md), which circumvents the need to provide a web server interface to cron.

Quick start
----------

If you just want to get started quickly, here is a crontab entry that will run cron once every hour at ten minutes after the hour:

10 * * * * cd [DOCROOT] && /usr/bin/env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin COLUMNS=72 ../vendor/bin/drush --uri=your.drupalsite.org --quiet cron
10 * * * * cd [DOCROOT] && /usr/bin/env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin COLUMNS=72 ../vendor/bin/drush --uri=your.drupalsite.org --quiet maint:status && /vendor/bin/drush --uri=your.drupalsite.org --quiet cron

You should set up crontab to run your cron tasks as the same user that runs the web server; for example, if you run your web server as the user www-data:

Expand Down Expand Up @@ -47,3 +47,7 @@ Specifying the Drupal site to run

There are many ways to tell Drush which Drupal site to select for the active command, and any may be used here. The example uses `cd [DOCROOT]`, but you could also use the --root and --uri flags.

Avoiding Maintenance mode
---------------------------------

The call to maint:status checks to see if the site is in maintenance mode. If yes, cron will not run and the command returns a failure. It is not safe to run cron while the site is in maintenance. See https://drupal.slack.com/archives/C45SW3FLM/p1675287662331809.
2 changes: 2 additions & 0 deletions src/Drupal/Commands/core/DrupalCommands.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ public function __construct(CronInterface $cron, ModuleHandlerInterface $moduleH
*
* @command core:cron
* @aliases cron,core-cron
* @usage drush maint:status && drush core:cron
* Run cron unless maintenance mode is enabled
* @topics docs:cron
*/
public function cron(): void
Expand Down
82 changes: 82 additions & 0 deletions src/Drupal/Commands/core/MaintCommands.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace Drush\Drupal\Commands\core;

use Consolidation\AnnotatedCommand\CommandResult;
use Consolidation\AnnotatedCommand\Input\StdinAwareInterface;
use Consolidation\AnnotatedCommand\Input\StdinAwareTrait;
use Drupal\Core\State\StateInterface;
use Drush\Commands\DrushCommands;

class MaintCommands extends DrushCommands
{
const KEY = 'system.maintenance_mode';

protected $state;

public function __construct(StateInterface $state)
{
$this->state = $state;
}

public function getState(): StateInterface
{
return $this->state;
}

/**
* Get maintenance mode. Returns 1 if enabled, 0 if not.
*
* Consider using maint:status instead when chaining commands.
*
* @command maint:get
*
* @usage drush maint:get
* Print value of maintenance mode in Drupal
* @aliases mget
* @version 11.5
*/
public function get(): string
{
$value = $this->getState()->get(self::KEY);
return $value ? '1' : '0';
}

/**
* Set maintenance mode.
*
* @command maint:set
*
* @param mixed $value The value to assign to the state key.
* @usage drush maint:set 1
* Put site into Maintenance mode.
* @usage drush maint:set 0
* Remove site from Maintenance mode.
* @aliases mset
* @version 11.5
*/
public function set(string $value): void
{
$this->getState()->set(self::KEY, (bool) $value);
}


/**
* Fail if maintenance mode is enabled.
*
* This commands fails with exit code of 3 when maintenance mode is on. This special
* exit code distinguishes from a failure to complete.
*
* @command maint:status
*
* @usage drush maint:status && drush cron
* Only run cron when Drupal is not in maintenance mode.
* @aliases mstatus
* @version 11.5
*/
public function status(): int
{
$value = $this->getState()->get(self::KEY);
return $value ? self::EXIT_FAILURE_WITH_CLARITY : self::EXIT_SUCCESS;
}
}
5 changes: 5 additions & 0 deletions src/Drupal/Commands/core/drush.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ services:
arguments: ['@language_manager', '@config.factory', '@module_handler', '@state']
tags:
- { name: drush.command }
maint.commands:
class: \Drush\Drupal\Commands\core\MaintCommands
arguments: [ '@state' ]
tags:
- { name: drush.command }
messenger.commands:
class: \Drush\Drupal\Commands\core\MessengerCommands
arguments: ['@messenger']
Expand Down
23 changes: 23 additions & 0 deletions tests/integration/MaintTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Unish;

/**
* Tests Maintenance commands
*
* @group commands
*/
class MaintenanceTest extends UnishIntegrationTestCase
{
public function testMaint()
{
$this->drush('maint:set', [1]);
$this->drush('maint:get');
$this->assertOutputEquals('1');
$this->drush('maint:status', [], [], self::EXIT_ERROR_WITH_CLARITY);
$this->drush('maint:set', [0]);
$this->drush('maint:get');
$this->assertOutputEquals('0');
$this->drush('maint:status', [], [], self::EXIT_SUCCESS);
}
}

0 comments on commit 87480ba

Please sign in to comment.