Drush: Selectively Syncing Remote Site(s)

David G - DrupalRecently on a project I was given access to a remote server, to work as a subcontractor for another client on a project. The dev team I’m working with doesn’t use Git, I believe they do nightly backups of the server — but they work directly on the server. It’s been 8+ years since I did that on a complete project; I need my Git and other tools. So given SSH access I want to clone the project locally. The caveat is that the project is 1 a Drupal subsite of a large Drupal multi-site installation. How can I work on this easily?

Drush Commands to Use

My project setup uses Drush Aliases:

  • @presidency.dev — the Remote Development server graphic artists and others are working in.
  • @presidency.local — my local server where I want to do my work and sync content back and forth to the Remote webhost.

So my desired workflow is to clone all of the Drupal docroot from @presidency.dev to @presidency.local; include my 1 drupal project subsite, and exclude all other subsites. This seemed like an easy 2 part task:

1. Get the remote Drupal root:

drush -s rsync @presidency.dev @presidency.local --exclude-sites --delete

But unfortunately this errors out! As we can see with -s (for simulate) this commands adds a / onto the Drupal root path 🙁

Calling system(rsync -e 'ssh -o PasswordAuthentication=yes -i /home/dgurba/.ssh/id_rsa' -akz --exclude=".git" --exclude=".gitignore" --exclude=".hg" --exclude=".hgignore" --exclude=".hgrags" --exclude=".bzr" --exclude=".bzrignore" --exclude=".bzrtags" --exclude=".svn" --exclude="settings.php" --include="sites/all" --exclude="sites/*" --delete webuser@remote-site.com:/www/drupal-7// /var/www/2015/presidency/drupal7-project/build/local/htdocs/);

/www/drupal-7//  is not a valid path. This sucks! So I asked on IRC why this command was failing, or for a workaround. I thought — hey I can run the simulated command amended but maybe there’s a better way!?

So I asked on IRC at #drush on Freenode:

Mar 16 13:32:56 <x13z>	Hi i'm trying to run drush rsync and when not using %sites my Source alias is getting a '/' appended to the rsync path and nothing is synching ...
Mar 16 13:34:26 <x13z>	i'm following the directions here to sync 1 multisite site to my local development system. http://c.pachabhaiya.com/blog/drush-rsync-and-sql-sync
Mar 16 14:56:52 <greg1anderson>	x13z: Drush always adds the / to help novices with paths such as drush rsync @a:%files @b:%files.  If you don’t like the /, then use rsync directly with drush dd

So, the MAN himself, greg1anderson maintainer of Drush answer my question! sqeee! haha.

He recommends to use Rsync directly and the dd command of Drush

$ drush help dd
Return the filesystem path for modules/themes and other key folders.

 cd `drush dd devel`    Navigate into the devel module directory                            
 cd `drush dd`          Navigate to the root of your Drupal site                            
 cd `drush dd files`    Navigate to the files directory.                                    
 drush dd @alias:%files      Print the path to the files directory on the site @alias.           
 edit `drush dd devel`/devel.module    Open devel module in your editor (customize 'edit' for your editor)

 target        A module/theme name, or special names like root, files, private, or an alias : path alias string such as @alias:%files. Defaults to root.

 --component    The portion of the evaluated path to return.  Defaults to 'path'; 'name' returns the site alias of the target.                                                                                                
 --local       Reject any target that specifies a remote site.

Aliases: dd

I opted to run the amended command to sync the whole Drupal root folder, ignoring subsites. This isn’t hard to get because the simulated Drush command outputs what it would attempt to run:

rsync -e 'ssh -o PasswordAuthentication=yes -i /home/dgurba/.ssh/id_rsa' -avkz --exclude=".git" --exclude=".gitignore" --exclude=".hg" --exclude=".hgignore" --exclude=".hgrags" --exclude=".bzr" --exclude=".bzrignore" --exclude=".bzrtags" --exclude=".svn" --exclude="settings.php" --include="sites/all" --exclude="sites/*" --delete webuser@remote-site.com:/www/drupal-7/ /var/www/2015/presidency/drupal7-project/build/gemini/htdocs/

This properly synced the files.

I then sync the subsite and sql-sync:

drush -v rsync @presidency.dev:%sites @presidency.local:%sites --delete
drush -v sql-sync @presidency.dev @presidency.local

%sites here is the sites directory on dev and local we’re syncing between — they differ in both locations. Usually these directories would have the same name, but they don’t have to have the same name.

%sites is defined per each alias in the following format (@dev here):

  'path-aliases' => array(
    '%drush-script' => '/local/pkg/php/bin/drush',
    '%sites' => 'sites/presidency.domain.edu',

Lastly I wrote a small PHP script to amend the db-url of the synced subsite settings.php file:

drush @presidency.local php-script /var/www/2015/presidency/drupal7-project/amend_settings_db_url.php

The amend_settings_db_url.php has the following code, note I literally copy 2 drush functions and rename them as mydrush_*:

because I’m lazy:


function mydrush_convert_db_from_db_url($db_url) { /* ... */ }

function mydrush_sitealias_convert_db_from_db_url($db_url) {
  $result = array();
  if (!is_array($db_url)) {
    $result = array('default' => array('default' => mydrush_convert_db_from_db_url($db_url)));
  else {
    foreach ($db_url as $one_name => $one_db_url) {
      $result[$one_name] = array('default' => drush_convert_db_from_db_url($one_db_url));
  return $result;

// My custom code for the file.
$db_url = "mysql://dev_user:****@localhost/presidency_local";
$settingsfile = '/var/www/2015/presidency/drupal7-project/build/gemini/htdocs/sites/presidency-local/settings.php';
// Need to do something here or else we can't write.
chmod($settingsfile, 0664);
file_put_contents($settingsfile, "\n" . '$databases = ' . var_export(mydrush_sitealias_convert_db_from_db_url($db_url), TRUE) . ";\n", FILE_APPEND);

I put all this into a script I can re-run, Cron and Git commit from periodically to see how the Dev site is being updated compared to my local work.

 Looking for quality web hosting? Look no further than Arvixe Web Hosting!


Tags: , , , , | Posted under Drupal, Drush | RSS 2.0

Author Spotlight

David Gurba

I am a web programmer currently employed at UCSB. I have been developing web applications professionally for 8+ years now. For the last 5 years I’ve been actively developing websites primarily in PHP using Drupal. I have experience using LAMP and developing data driven websites for clients in aviation, higher education and e-commerce. If you’d like to contact me I can be reached at david.gurba@arvixe.com

Leave a Reply

Your email address will not be published. Required fields are marked *