This article demonstrates Drush aliases and the configuration you need to pull the database and files from one Drupal site to another with the following commands:


# Syncronize sites/emspace.com.au/files from production to dev.
drush rsync @prod:%files @dev:%files

# Syncronize database (minus ‘custom’ tables) from production to dev
drush sql-sync –structure-tables-key=custom –no-cache @prod @dev

Background

I spoke with Moshe at Drupalcon SF about some new tricks in Drush. I realised that my bespoke deployment scripts would soon be obsolete. Today I figured out what I needed from Drush and this article describes my new preferred “one-liners”.

Along with Moshe et all, I want to specifically thank Greg Anderson. Judging by his answer to my issue here, he’s put a lot of work into this part of Drush, and I think we’ve only scratched the surface of what is possible.

Set-up

You need two working Drupal sites for this example – preferably on the same server (to begin with). I created two sites on my localhost. This simply makes debugging easier while you get the hang of aliases.

My setup, in case it helps:

  • Mac OSX
  • MAMP PRO 1.9 (Normal MAMP would be OK, but harder to configure custom hostnames)
  • Drupal 6
  • Drush 3.1 lives in /Library/PHP/drush
  • “Production site” is set up as http://prod.local and lives at /Users/sime/Sites/prod.local
  • “Development site” is set up as http://dev.local and lives at /Users/sime/Sites/dev.local

I have /usr/bin/php soft-linked to the MAMP php 5.2 executable. In MAMP I’ve edited the php.ini template for 5.2, increasing the memory limit to 128mb. I have Drush aliased simply as alias drush="php /Library/PHP/drush/drush.php" in my .bash_profile.

Set up your aliases

For these examples you only need one configuration file on your local machine. Even if you’re working with a remote production server, the configuration still lives on your own machine.

Open the terminal, or bash window. Create a directory called .drush in your home directory, if it doesn’t exist already. Add the drush aliases file here.

mkdir ~/.drush
touch ~/.drush/aliases.drushrc.php

(~/.drush/ is one of the places where Drush will look for configuration files. There are other configuration files that can live here.)

Start with a very simple example using the dev site only. Note, a syntax error in this file will kill drush with the error “Drush command could not be completed.”.


<?php
$aliases['dev'] = array(
'uri' => 'dev.local',
'root' => '/Users/sime/Sites/dev.local', // This doesn't work with ~/Sites/dev.local
'path-aliases' => array(
'%files' => 'sites/emspace.com.au/files',
'%dump' => '/Users/sime/tmp/drush/sql-sync-dev-local.sql', // Arbitrary location for temp files
),
?>

Some alias-enhanced Drush commands

Let’s run a few commands to verify that the aliases are working correctly and to get the hang of things.

See the status of the site. This should print a dozen+ rows of information:

drush @dev status

Print where the files directory is

drush dd @dev:%files

Switch to the files directory (note the backticks to express the output as part of the command):

cd `drush dd @dev:%files`

Dump the database, and then load the same database. Keep these handy especially when you’re experimenting.

drush @dev sql-dump > `drush dd @dev:%dump`
`drush @dev sql-connect` < `drush dd @dev:%dump`

Final aliases.drushrc.php


<?php

$aliases[‘dev’] = array(
‘uri’ => ‘dev.local’,
‘root’ => ‘/Users/sime/Sites/dev.local’,
‘path-aliases’ => array(
‘%files’ => ‘sites/emspace.com.au/files’,
‘%dump’ => ‘/Users/sime/tmp/drush/sql-sync-dev-local.sql’,
),
‘command-specific’ => array (
‘sql-sync’ => array (
‘simulate’ => ‘0’,
‘structure-tables’ => array(
‘custom’ => array(‘cache’, ‘cache_filter’, ‘cache_menu’, ‘cache_page’, ‘history’, ‘sessions’, ‘watchdog’),
),
),
‘rsync’ => array (
‘simulate’ => ‘0’,
‘mode’ => ‘rlptDz’,
),
),
);

$aliases[‘prod’] = array(
‘uri’ => ‘prod.local’,
‘root’ => ‘/Users/sime/Sites/prod.local’,
‘path-aliases’ => array(
‘%files’ => ‘sites/emspace.com.au/files’,
‘%dump’ => ‘/Users/sime/tmp/drush/sql-sync-prod-local.sql’,
),
‘command-specific’ => array (
‘sql-sync’ => array (
‘simulate’ => ‘1’,
),
‘rsync’ => array (
‘simulate’ => ‘1’,
‘ssh-options’ => ‘-p9999’,
),
),
);
?>

The command options

Apart from adding the Production alias, the full configuration adds additional keys.command-specific

This defines a list of Drush commands for which we want to define options. Both “prod” and “dev” site aliases define options for “sql-sync” and “rsync” which are the two Drush commands we will need.

simulate

This allows us to set the Drush option “simulate”, which will dry-run the command. It’s the equivalent of:

drush --simulate=1 command

Simulation isn’t just a party trick here. Setting simulation for the Production site means that we cannot accidentally overwrite the Production data or files.

structure-tables

Allows us to define a set of tables for which we never want to pull down the data. It can significantly improve download speeds to avoid the data overhead of the cache/search/session/watchdog tables.

Each set of tables has a key, in this example the key is “custom”. This can be specified in the drush command like this:

drush sql-sync --structure-tables-key=custom @site1 @site2

mode and ssh-options

These two options are relevant to the drush rsync command. Mode is for setting unary options: a mode of “avz” will result in “rsync -avz”.

SSH Options allows additional options to the ssh component of the command. In my case I have a few servers with ssh on a non-standard port – not common, but is a good example. “rlptDz” is my preferred – it is the same as Drush’s default (“az”) except it doesn’t try to sync Groups and Users.

The commands

With the aliases.drushrc.php in place, the commands we need are as follows.

# Syncronize sites/emspace.com.au/files from production to dev.
drush rsync @prod:%files @dev:%files

# Syncronize database (minus ‘custom’ tables) from production to dev
drush sql-sync –structure-tables-key=custom –no-cache @prod @dev

Final notes

Soon you’ll want “Production” to point to a real live website. The remote server will need to have Drush available, but it doesn’t necessarily need any more than this. You simply need to add some extra options in your aliases.drushrc.php.

There is another strategy for protecting the live site. Read the example policy.drush.inc for more. My understanding is that this will allow us to set a universal policy for different sites in the deployment chain. In practice sometimes I want to push data to the live site, so my preference was to go with aliases which can be overridden in the drush command.