Getting rid of routine tasks with Drush

Preface

Drush (The Drupal Shell) is a command line utility for Drupal, which provides many commands to interact with Drupal, its modules, themes, etc. Drush is a great developer’s helper and it allows to avoid or at least to speed up many kinds of routine tasks.

There are many articles telling about different Drush commands and how they help are, so I'd like to focus on Drush configuration possibilities and do a quick overview of Drush commands and Drush make. When you use Drush all the interactions with a Drupal site happen by executing commands, but there are some other Drush parts you may deal with:

  • Drush make which is combination of a special definition stored in the (make) file and a few specific commands to build a Drupal site codebase;
  • possibilities to add your own Drush commands by writing code in the files called in a special way and placed properly;
  • tuning Drush and Drupal via configuration files and more.

Drush processes described below are not necessarily should be implemented together. Since it’s not an algorithm of working with Drush, but a descriptive compilation, you may refer to the any article’s part when needed.

Drush commands

As you already know,  an interaction with a Drupal site happens via Drush commands. The Drush core provides many commands for many different purposes, but I believe the most used Drush commands are:

  • drush pm-download (dl) - download one or several projects (the Drupal core, module, theme, distribution), so you don't have to visit drupal.org to download and then unpack projects one by one;

  • drush pm-enable (en) - enable (install, if wasn't enabled before) one or several modules or themes;
  • drush cache-clear (cc) - clear cache (routing, theme, all, Drush, etc. cache).

With Drush you also can:

  • make a full site backup;
  • update the Drupal core, contrib modules and themes;
  • run cron jobs;
  • execute SQL query;
  • block user account(s);
  • change Drupal settings;

and other.

Drush make

Drush make allows to create a ready-to-use Drupal site codebase including the Drupal core, modules, themes, etc., (but without installation) from a definition stored in the just one file. Drush make does the work for you:

  • downloads the Drupal core, modules, themes;
  • fetches code from Git, SVN repositories;
  • downloads and applies patches;
  • downloads .tar.gz and .zip archives in general;
  • downloads libraries in particular.

The Drush make file can be written in 2 formats: YAML and the older Drupal .info INI format similar to modules' .info. YAML is recommended though since Drupal is switched to YAML for configurations (since Drupal 8).

There are 2 main commands to work with Drush make:

  • drush make example.make.yml docroot - make a Drupal codebase using the definition stored in the example.make.yml file;
  • drush make-generate example.make.yml - generate the makefile from a current Drupal site.

In case you develop Drupal distributions with following publishing at drupal.org, you have to deal with Drush make anyway.

Drush make file example (in YAML):

core: 7.x
 api: 2
 projects:
   drupal:
     type: core
   admin_menu:
     subdir: contrib
   ctools:
     version: "1.7"
   tao:
     type: theme
     download:
       url: "git://github.com/developmentseed/tao.git"

Extending the list of Drush commands

New commands can be easily added to Drush, and many contrib modules provide their own Drush commands: there is the modulename.drush.inc file in the module containing Drush integration code in this case. For example:

  • drush fn-hook (Devel module) - shows a list of implementations for the particular hook;
  • drush generate-content (Devel module) - generates dummy content;
  • drush features-revert-all (Features module) - reverts all the configurations exported into modules via the Features module to the code state;
  • drush views-list (Views module) - lists all the views on the site.

It's also possible to add Drush commands outside of modules, for example, to perform some specific actions for deployment, so you don't have to create and install a module on the site just to be able to invoke these Drush commands.

Drush configuration

Drush as well as a Drupal site can be configured in the context of running Drush commands. Needed configurations are defined in the drushrc.php file (DrushRC = Drush Runtime Config). For example, it's possible to force some global options for the Drush commands like always answering "yes" to all the confirmation prompts, force some of the command-specific options, change some of the Drupal settings (like an emails handler class and so on).

Drush looks for the drushrc.php file in the following directories, one by one as listed below. The order is basically the same when Drush looks for the files containing additional Drush commands (if the commands aren't related to the particular module):

  • sites/{default|example.com}/drushrc.php - a site-specific directory;
  • Drupal /drush and sites/all/drush directories;
  • /drush directory 1 level above the Drupal root;
  • as specified by --config (-c) option when running a Drush command;
  • User's .drush folder (~/.drush/drushrc.php);
  • /etc/drush/drushrc.php;
  • the Drush installation folder.

Let's see some examples (see the code comments for more info on what each setting means):

/**
 * Drush commands configuration.
 */
// Force verbose mode for all commands.
$options['v'] = 1;
// Answer "yes" to all confirmation prompts.
$options['y'] = 1;
// Force --notes option for pm-update command.
$command_specific['pm-update'] = ['notes' => TRUE];
// Use admin/admin as superuser credentials when installing Drupal site.
$command_specific['site-install'] = [
 'account-name' => 'admin',
 'account-pass' => 'admin',
];

/**
 * Site configuration.
 */
// Change site name.
$options['variables']['site_name'] = 'My Drupal site';
// Use different theme.
$options['variables']['theme_default'] = 'minnelli';
// Disable clean URLs.
$options['variables']['clean_url'] = 0;
// Use different directory for temporary.
$options['variables']['file_temporary_path'] = '/home/vagrant/tmp';

/**
 * SQL dump and structure tables.
 */
// List of tables to export structure only without data on dump.
$options['structure-tables']['common'] = [
 'cache',
 'cache_*',
 'history',
 'search_*',
 'sessions',
];
// Force "common" structure tables list by default on sql-dump command.
$command_specific['sql-dump'] = [
 'structure-tables-key' => 'common',
];

Shell aliases

Drush also allows to define short aliases for a command or a number of commands, potentially used with a number of set options, via drushrc.php file, and this is not limited by Drush commands only.

// drush wipe
$options['shell-aliases']['wipe'] = 'cache-clear all';
// drush pulldb
$options['shell-aliases']['pulldb'] = '!git pull && drush updatedb';
// drush offline
$options['shell-aliases']['offline'] = 'variable-set -y --exact maintenance_mode 1';
// drush online
$options['shell-aliases']['online'] = 'variable-delete -y --exact maintenance_mode';
// drush unsuck
$options['shell-aliases']['unsuck'] = 'pm-disable -y overlay, dashboard';
The lines starting with ! are not Drush commands, the lines without ! - are supposed to be Drush commands and the leading drush word is not needed in this case.

As it was shown, Drush allows to shorten the entered commands (executed at the command line) via different configurations and to properly configure a Drupal site when you interact with it via Drush. All of these decrease a number of routine actions and speed up the process of dealing with Drupal as a result.

Drush site aliases

Let’s expand on an interaction with Drupal via Drush. Usually, the interaction and an execution of some commands require that you have to navigate to the Drupal root directory first. If it’s a Drupal multi-site you need to navigate deeper to the site directory (sites/site-name), or explicitly set --uri (a site address when the site is opened in a browser) and --root (a path to the Drupal root directory) options when executing a Drush command. With the help of Drush site aliases all of these can be shortened to drush @example.com status with no difference from where the command is executed.

Drush site aliases can be defined in the file similar to drushrc.php, and Drush looks for this file in the same places it looks for drushrc.php. To define the site alias you just need to set uri and root properties.

// drush @example status
$aliases['example'] = [
  'root' => '/var/www/example.dev/docroot',
  'uri' => 'http://dev.example.com',
];

There are 3 ways to name the file where the site aliases are defined:

  • ALIASNAME.alias.drushrc.php - commands are executed like drush @ALIASNAME status;
  • aliases.drushrc.php - commands are executed like drush @ALIASNAME status;
  • GROUPNAME.aliases.drushrc.php - commands are executed like drush @GROUPNAME.ALIASNAME status.

The 3rd way is convenient for defining several instances / environments of the same site:

/**
 * @file
 * example.aliases.drushrc.php
 */
// drush @example.dev status
$aliases['dev'] = [
  'root' => '/var/www/example.dev/docroot',
  'uri' => 'http://dev.example.com',
];
// drush @example.stage status
$aliases['stage'] = [
  'root' => '/var/www/example.stage/docroot',
  'uri' => 'http://stage.example.com',
];
It's also possible to execute a command for all sites in a group simultaneously: drush @example status Actually, Drush allows interacting via the site aliases not with local sites only, but also with remote sites. In this case, you need to set a few more properties, at least remote-host and remote-user (but there are more options available).
$aliases['example.stage'] = [
  'remote-host' => 'server.example.com',
  'remote-user' => 'www-admin',
  'root' => '/var/www/example.stage/docroot',
  'uri' => 'http://stage.example.com',
];

When you deal with the remote sites, you definitely want to avoid any mistakes: this can be done by adding a validation via Drush command hooks:

/**
 * @file
 * policy.drush.inc
 */

/**
 * Implements drush_hook_COMMAND_validate().
 */
function drush_policy_sql_sync_validate($source = NULL, $destination = NULL) {
  // Deny sync to prod/production.
  if (preg_match("/^@.*prod/i", $destination)) {
    return drush_set_error('POLICY_DENY', dt('Nope.'));
 }
}

Basically, this is the same way how new Drush commands are added, so file naming is the same. In this particular case, there is a convention to call this "Policy".

Drush contains a number of special commands for usage with the remote sites and the sites aliases.

drush core-rsync @site.remote:db.sql @site.local:backup/
drush core-rsync @site.remote:%files/ @site.local:%files/

- to rsync the Drupal tree to/from another server using ssh. %files is a special token pointing to a public file uploads directory, but there are more tokens available and custom ones may be defined via path-aliases site alias property.

drush sql-sync @site.remote @site.local

- to copy the database content from a source site to a target site, a database dump is transferred via rsync.

To connect to the Drupal site's server via SSH for an interactive session:

drush @site.remote site-ssh

or to run a shell command:

drush @site.remote site-ssh ls -la
drush @site.remote core-execute ls -la
drush @site.local core-execute ls -la

Drush and Drupal 8 

There are many changes in Drupal 8 in comparison with the previous version. When it comes to Drush, there is no big difference in dealing with a Drupal site. Probably the most noticeable change is that there is no more drush cache-clear all to flush all the caches. There is drush cache-rebuild instead. Other kinds of caches can still be cleared via drush cache-clear. An interaction with Drupal 8 via Drush requires Drush 8 version and newer.

Also, there are few new Drush commands to interact with things specific to Drupal 8:

config-edit (cedit)
config-export (cex)
config-get (cget)
...

- to deal with configurations;

state-get (sget)
state-set (sset)
...

- to deal with states.

Conclusion 

Drush is a great tool which can help you with a Drupal site building, development, and maintenance, and it noticeably speeds up these processes. The main part of  Drush is its commands, of course, but you can also tune Drush and Drupal (in context of interaction via Drush) for your own needs via configuration files, you can add custom commands like contrib modules often do, build a Drupal site codebase from a single file, deal with remote Drupal sites via Drush site aliases and more. Drush exists for a long time, but it's still a must-have: a very stable, well maintained and always evolving tool for Drupal. Stable and actively maintained Drush version for that moment is 8.x (you need this version or newer to deal with Drupal 8), Drush 9.x is in alpha and is being actively developed.

The observed Drush parts and processes are definitely going to cross your development and site-building path, so make sure to save and share this article with fellow Drupal developers. Good luck!

You might also like