Wednesday, 29 May 2013

Using Drush to sync live and dev Drupal websites

This post describes how to use Drush to synchronise a live drupal website with a local development copy and vice versa, to synchronise an updated dev site back to the server version.  Following on from previous posts about Drupal this blog assumes that both a live server-based and a local drupal website are in place.

Part 1: Local Drupal7 on Mac OSX Lion
Part 2: Set-up Multisite Drupal 7
Part 3: Using Drush to sync live and dev Drupal websites
The process consists of three key steps:
-Install Drush
-Set up Aliases
-Synchronising live site to local

Installing Drush

Following the very concise and clear instructions from Ayanim97
1. Download Drush to local folder as a tar.gz file. I got mine from https://www.drupal.org/node/97249/release
2. Launch Terminal and change directory to where the drush tar file is downloaded)
3. Extract it with tar -zxf drush-7.x-5.9.tar.gz (version downloaded May 2013)
4. Move it to /usr/local/lib with sudo mv drush /usr/local/lib/ If this directory does not exit create it
 with
sudo mkdir /usr/local/lib
5. Make it executable
sudo chmod u+x /usr/local/lib/drush/drush
6. Then add it to your path so that you can run it from anywhere
nano ~/.bash_profile
export PATH=$PATH:/usr/local/lib/drush
ctrl-x, Yes, Enter

Calling a drush command on my Mac OSX Lion e.g. drush status throws up some errors:
The following restricted PHP modes have non-empty values:            [error]
magic_quotes_gpc. This configuration is incompatible with drush. 
Please check your configuration settings in  or in your drush.ini
file; see examples/example.drush.ini for details.
 PHP configuration     :                                                  
 Drush version         :  5.9                                             
 Drush configuration   :                                                  

 Drush alias files     :  /Users/mattmapleston/.drush/aliases.drushrc.php

This is because there is no PHP configuration file.  This was solved by creating one from the example that came with drush.  Some helpful documents suggested using the php.ini file used by the webservice so this may need tweaking later on.  Useful information can be found with the Terminal commands
which php
whereis php
type -a php
Also a webpage showing phpinfo() is useful in particular the path of the php.ini configuration file and the list of Core Directives - Drush requires some of those to be turned off.  Creating a file called phpinfo.php containing <?php phpinfo(); ?> in ~/Sites allows you to use the URL localhost/~username/phpinfo.php

The solution to the error above was to copy example.drush.ini from '/usr/local/lib/drush/examples' folder into ~/.drush as drush.ini with
cp /usr/local/lib/drush/examples/example.drush.ini ~/.drush/drush.ini
then edit drush.ini to add magic_quotes_gpc = to the end.

(null):.drush mattmapleston$ drush status
 PHP configuration     :   /Users/mattmapleston/.drush/drush.ini          
 Drush version         :  5.9                                             
 Drush configuration   :                                                  
 Drush alias files     :

Remote Server Setup

The following steps are much easier if you also install Drush on any remote servers you wish to connect to.  According to a post on drush aliases on stack exchange you can get round this by specifying all the information required manually i.e. 'databases' and '%dump-dir'.  This didn't work for me so I installed drush on my cloud server manually as above.  Drush uses ssh to send commands to remote servers so one must set up a RSA key for ssh without password.

If you get a bash: rsync: command not found message when you try to use Drush it is because Drush uses system calls including rsync.  My server did not have this installed (check with which <command>).  This was rectified by running three commands, yum update to make sure the server was up to date, yum search rsync to see if I could install it and finally yum install rsync to install it.

Set Up Aliases

To simplify the use of Drush, aliases should be set up to define short names for local or remote Drupal installations.

Create an alias set up file in the ~/.drush folder following the instructions in the comments of /usr/local/lib/drush/examples/example.aliases.drushrc.php or example.aliases.drushrc.php on the web.  For some indication of settings for an alias, navigate to your drupal directory and type drush site-alias --full <name of site directory> which will return the required settings. Below is the ~/.drush/aliases.drushrc.php file I ended up with after some trial and error.

<?php
$aliases['c2.dev'] = array(
  'root' => '/Users/mattmapleston/Sites/drupal',
  'uri' => 'c2.dev',
  'path-aliases' => array(
     '%dump' => '/Users/mattmapleston/Sites/drupal/sqldumps/sqldump-c2-dev.sql',
     '%files' => '/Users/mattmapleston/Sites/drupal/sites/c2.dev/files',),
);

//@c2.live remote live version of www.chanzachanzo.com
$aliases['server'] = array(
  'remote-user' => 'root',
  'remote-host' => '108.161.133.223',
);

$aliases['c2.live'] = array(
  'parent' => '@server',
  'root' => '/var/www/html',
  'uri' => 'default',
  'path-aliases' => array(
     '%dump' => '/root/sqldumps/sqldump-c2-live.sql',
     '%files' => '/var/www/html/sites/default/files', ),
);

?>
There are a few commands that help test out your aliases: drush site-alias/drush sa, drush sa @<alias>, drush @<alias> status. For example:
(null):~ mattmapleston$ drush sa
@c2.dev
@c2.live
@none
@server


drush sa @c2.dev
$aliases['c2.dev'] = array (
  'root' => '/Users/mattmapleston/Sites/drupal',
  'uri' => 'c2.dev',
  'path-aliases' => 
  array (
    '%dump' => '/Users/mattmapleston/Sites/drupal/sqldumps/sqldump-c2-dev.sql',
    '%files' => '/Users/mattmapleston/Sites/drupal/sites/c2.dev/files',
  ),
  '#file' => '/Users/mattmapleston/.drush/aliases.drushrc.php',
);
drush @c2.dev status
 Drupal version                  :  7.22                                            
 Site URI                        :  c2.dev                                          
 Database driver                 :  mysql                                           
 Database hostname               :  localhost                                       
 Database username               :  d7user                                          
 Database name                   :  c2devdb                                         
 Database                        :  Connected                                       
 Drupal bootstrap                :  Successful                                      
 Drupal user                     :  Anonymous                                       
 Default theme                   :  sub_zen                                         
 Administration theme            :  seven                                           
 PHP configuration               :   /Users/mattmapleston/.drush/drush.ini          
 Drush version                   :  5.9                                             
 Drush configuration             :                                                  
 Drush alias files               :  /Users/mattmapleston/.drush/aliases.drushrc.php 
 Drupal root                     :  /Users/mattmapleston/Sites/drupal               
 Site path                       :  sites/c2.dev                                    
 File directory path             :  sites/c2.dev/files                              
 Temporary file directory path   :  /tmp

drush sa @c2.live
$aliases['c2.live'] = array (
  'remote-user' => 'root',
  'remote-host' => '108.161.133.223',
  '#file' => '/Users/mattmapleston/.drush/aliases.drushrc.php',
  'root' => '/var/www/html',
  'uri' => 'default',
  'path-aliases' => 
  array (
    '%dump' => '/root/sqldumps/sqldump-c2-live.sql',
    '%files' => '/var/www/html/sites/default/files',
  ),
);

drush @c2.live status
 Drupal version                  :  7.22                
 Site URI                        :  default             
 Database driver                 :  mysql               
 Database hostname               :  localhost           
 Database username               :  d7user              
 Database name                   :  drupal7db           
 Database                        :  Connected           
 Drupal bootstrap                :  Successful          
 Drupal user                     :  Anonymous           
 Default theme                   :  sub_zen             
 Administration theme            :  seven               
 PHP configuration               :  /etc/php.ini        
 Drush version                   :  5.9                 
 Drush configuration             :                      
 Drupal root                     :  /var/www/html       
 Site path                       :  sites/default       
 File directory path             :  sites/default/files 
 Temporary file directory path   :  /tmp                

Syncing Local and Remote Drupal Sites

There are three things to synchronise between the local dev and remote live sites: themes in sites/all, the site's files, and its database.  The base command is drush rsync @from:path @to:path. The site's files are copied from live to dev with drush rsync @c2.live:%files @c2.dev:%files. To synchronise the database: drush sql-sync @c2.live @c2.dev.  To synchronise sites/all drush rsync @c2.live:sites/all/themes/ @c2.dev:sites/all/themes/.  All of these work in the opposite direction by swapping the c2.dev and c2.live aliases.  For example, if you have added a new sub-theme or altered an existing one on your local laptop, you can transfer those changes to the server with the following drush rsync @c2.dev:sites/all/themes/ @c2.live:sites/all/themes/.

After this, http://c2.dev URL brought up a local version of the website - happy days!  Short-lived happy days as there was a problem with logging on.  The live site had clean-urls enabled , the local version didn't.  Reverting to dirty URLs (www.mysite.com/?q=<user1>) brought up a page put wouldn't allow me to type in a password and login. Drush to the rescue again - drush vset clean_url 0 removes the clean_url setting and allowed login to work.

Development Workflow

This is my development workflow. My webpage does not encourage user input or have a shop so there is little chance the live webpage will change following a database download/sync.  If the site does become dynamic I will have to look into how to sync certain tables in the database to avoid losing user generated content on the live site.

  1. Make changes to local c2.dev in ~/Sites/drupal/ in particular sites/all/themes/sub_zen
  2. When ready sync files with drush rsync @c2.dev:%files @c2.live:%files or (mostly) drush rsync @c2.dev:sites/all/themes/sub-zen/.  If content has changed then drush sql-sync @c2.dev @c2.live should do the trick.


Some sites I found on the way:
http://drupal.org/files/drushguide2012.pdf
http://emspace.com.au/article/drush-aliases-primer-live-dev-syncing
http://www.monarchdigital.com/blog/2012-10-10/drush-aliases
http://www.matttarsi.com/using-drush-aliases
http://www.bariswanschers.com/blog/working-drush-alias-files-teams
http://drupal.org/node/670460
http://jtfdancer.wordpress.com/2013/04/06/drupaldevmac-drush/
http://drush.ws/examples/example.aliases.drushrc.php
http://getlevelten.com/blog/dustin-currie/synchronize-one-drupal-site-to-another#.UZ-KXGSY4-Y