Drush: An Expert's Technique

Chances are you know that drush is a command line utility for Drupal that allows site administrators to interface with the site directly from the command line shell. It contains simple commands such as drush st , which simply print the status report to the terminal, to the more powerful drush updb, equivalent to visiting the update.php script in your web browser.

An Advanced Perspective

I will assume, since you’re reading this article, that you have some knowledge of the power of this utility and know that, while drush on the surface, can enhance a developer workflow greatly; it also has the benefits of being complex and flexible. Just a couple of the concepts which make drush very powerful are:

  • remote site aliases: a simple way to define many remote destinations; useful when you want to skip the step of having to ssh to a particular site and/or combine the drush output with some other local utility on your system.
  • user defined commands: Drush is just as extensible as Drupal, allowing an ambitious developer to enhance and suit the utility to their particular workflow. The highly useful drush make command is one such example.

Two-Factor Authentication with Drush

Because of Drush’s ability to set configuration parameters with its remote aliases, drush can be configured to tunnel its requests through a two-factor model such as a bastion host. This would require you use a standard *nix utility such as nc, also known as netcat, to forward the requests with a combination of the ProxyCommand directive.

Tunneling through a Bastion Host

Assuming you have setup a Drupal site on a remote instance, your configuration entry (inside ~/.drush/aliases.drushrc.php) may look like this:

$aliases['mysite'] = array(
&nbsp; 'uri' => '<a href="https://www.foo.com',<br />">https://www.foo.com',</a>
&nbsp; 'root' => '/var/www/drupal',
&nbsp; 'db-url' => 'mysqli://user:<a href="mailto:[email protected]">[email protected]</a>’,
&nbsp; 'remote-host' => 'webserver.address',
&nbsp; 'remote-user' => 'root',
&nbsp; 'ssh-options' => '-o "ProxyCommand ssh <a href="mailto:[email protected]">[email protected]</a> nc %h %p"',

The ssh-options entry tells drush to run the commands inside it when drush attempts to connect to your remote destination.
The entry tells drush when you run drush @mysite st it should connect first as [email protected] and use netcat to tunnel the drush status command to webserver.com as the root user. It will then return the output to your local machine.

(As a bonus, the Drupal rock-star Greg Anderson took an issue I had submitted for 5.x on this concept and wrote up some excellent documentation with a few network-aware examples and committed it to Drush. Check out the original issue here: http://drupal.org/node/1189230)

Using Drush as Part of a Daily Linux Workflow

As we’ve seen, Drush can be combined with many other commands in the shell. To your operating system, it’s no less flexible in its ability to pipe and receive input then standard commands such as ls, or grep. With that in mind, the following command would be perfectly legitimate:

To see a list of all the enabled modules on a site:
drush pm-list | grep “Enabled”

Showing Configuration Differences Between Two Installations

Many times something works on your development environment that just doesn’t work on your production instance. You have verified the code is the same but how do you know something isn’t different in the database?

You could go through each configuration screen laboriously and try to find the differences. Pouring over the module screen, browsers side by side, and looking for which checkboxes are ticked and which aren’t.

Or you could simply combine the common Linux utility diff with Drush:

diff -u <(drush @site-dev pm-list --uri="http://dev.foo.com" | grep Enabled) <(drush @site-prod pm-list --uri="www.foo.com" | grep Enabled)

The command says, take the output of the enabled modules on my development site, defined by an alias, and the output of the enabled modules on my production site, also an alias, and send it as arguments to the diff command (in unified patch format).

It might produce this which shows that one site has two enabled CCK modules the other does not:

--- /dev/fd/632011-06-07 23:51:47.893992259 +0000
+++ /dev/fd/622011-06-07 23:51:47.897992197 +0000
@@ -7,7 +7,6 @@     
CCK    Content Copy (content_copy) Module  Enabled        6.x-2.8        
CCK    Email (email)    Module  Enabled        6.x-1.2         

That might be a place to start your investigation! As an exercise, can you figure out how you might do the same for all of your configuration variables? (Hint: You’ll want to know the drush vget command)

Drush Make

Since Drush can also provide an API for user defined commands, many useful packages have been released by the Drupal community of contributors. One such custom command is drush make which takes a standard .ini format file and produces a working Drupal installation. You can download drush make and read its extensive documentation from the project page.

Among some of the capabilities listed on the project page, it can:

  • Download core and contributed modules.
  • Apply patches from, checkout, and commit to a range of source control systems.
  • Fetch modules, themes, and installation profiles, but also external libraries (Such as Apache SOLR).

A simple use case might be setting up a simple Drupal install to do some blogging. You might create a simple text file in the following format:

core = 7.x
projects[] = drupal
projects[cck][subdir] = "contrib"
projects[filefield][subdir] = "contrib"
projects[imagefield][subdir] = "contrib"
projects[link][subdir] = "contrib"
projects[date][subdir] = "contrib"
projects[views][subdir] = "contrib"

Name the file sample.make and run the following command: drush make ~/path/to/files/sample.make
Now CD into the root and install Drupal using this command: drush ic
Lastly, you’ll want to enable your modules: drush en cck filefield views imagefield link date

Setting up Common Troubleshooting Scenarios

Because drush make can be configured with literally hundreds of options, and combined with a standard bash script, you can easily create common troubleshooting scenarios when trying to isolate problems in a Drupal installation or when maintaining your own modules.

Perhaps a bug has been filed against your latest version that may or may not be caused by the specific way in which the site is configured. You could easily script several drush make scenarios (using something as simple as a bash script to combine commands) to be better equipped to handle them.

Common scenarios could be: A blog site, an image gallery site, a simple commerce site, etc.


Drush is a powerful tool on its own but when combined with its ability to run custom commands, integrate with existing systems administration tools, and utilize the power of aliases and configuration options the possibilities are endless.

Do you have some non-standard ways of using drush? If so, please share them with the community in the comments here or, better still, submit patches to the verbose example documentation that comes with drush.