Illustration of Yeti character writing with a pencil.

Drush Pro Tip: Automatic Site Aliases


If you’re using Drush, you might have bumped into the Site Aliases feature (or at least heard about it). For those who don’t know, a site alias specifies a Drupal site, giving it a short name. These are super useful for running commands against remote sites, automating database syncs, and speeding up your development workflow.

If you work on more than one project, it can be tedious to maintain your Drush alias files. In this article we explore a couple of ways you can automate the process of creating site aliases, and/or extract alias information from other places you might have this data stored. All of the techniques below are possible because Drush alias files are simple PHP files.

Level 1: Local Development Sites:

First up, let’s cover the most common use case: creating site aliases for your local versions of development sites. In my development environment, I use a single web root, with each project I’m working on being a subfolder of that directory. So if my web root is /var/www, project1’s web root is /var/www/project1, and the URI is http://localhost/project1. Given that simple setup, all you have to do to automate aliases for ALL of your projects is find the subdirectories of /var/www and apply a pattern to them to find the root and URI.

 

$aliases = array(); $dir_handle = new DirectoryIterator('/var/www'); while($dir_handle->valid()) { if($dir_handle->isDir() && !$dir_handle->isDot()) { // Does this subdirectory contain a Drupal site? if(file_exists($dir_handle->getPathname() . '/sites/default/default.settings.php')) { $basename = $dir_handle->getBasename(); $aliases[$basename] = array( 'uri' => 'http://localhost/' . $basename, 'root' => $dir_handle->getPathname() ); } } $dir_handle->next(); } @

 

Level 2: From a project management system:

Here at left-click advanced, we use Redmine to store all everything about a project in a single place. Our continuous integration (CI) system produces automated builds every time we push a new commit to a project. I’ll save talking about our CI setup for a later date, but in brief, our CI system loops through Drush site aliases and runs a drush command against each one. On our CI machine, our aliases.drushrc.php works kind of like this:

  1. Query Redmine for a list of projects and extract the project id, repository URL and project name. We do this through a direct database query, although it could also be done using Redmine’s REST API.
  2. Loop through the projects, creating a Drush alias array for each one based one some simple patterns. For example, the web root becomes “/var/www/PROJECTID” and the URI becomes “PROJECTID.lcadvanced.com”. We also have some more complicated operations here, such as specifying a database name/user/password based on the project ID.
  3. Return the populated $aliases array.

Once we’ve got our aliases specified, running a command against any of our CI sites from the CI machine is as simple as drush @alias command. Which is handy, since that’s what we do in our build command.

Level 3: Remote aliases:

We’ve covered a couple of ways to dynamically generate lists of aliases, but they only work on the local machine. Wouldn’t it be cool if developers had access to a canonical set of aliases? Then they could run commands any site on a server they have shell access to. Here at LCA, we haven’t done this yet, but here are a few ideas we’ve been kicking around, assuming that our CI aliases (coming from Redmine) are the set we want to distribute.

  • Run the same Redmine query from the developer machine, and build the $aliases array as you would above. This would work, but it would be much nicer to get the aliases from Drush instead.
  • Serialize the result of running drush site-alias —full to a web page, then call that page and unserialize it on your developer machine. This is easy, but access control could be problematic.
  • Serialize the result of drush site-alias —full inside of a custom Drush command, then run that command over SSH inside the developer’s aliases.drushrc.php (eg: exec(“ssh someserver.com ‘drush some-command-to-list-aliases’ ”)). This solves the access control issue neatly, since you’d need shell access to see the data.

Make sure that each of the remote server’s aliases either get the ‘parent’ key set to an alias containing the remote-host options, or specify these options for each alias. You’ll also want to cache the list locally, since these remote calls could add a lot of overhead for everyday Drush use. Last but not least, you could use Drush’s alias grouping feature (using GROUPNAME.aliases.drushrc.php rather than aliases.drushrc.php) to avoid alias names clashing with your local versions.

Your method?

If you have any questions or suggestions, we’d love to hear from you! Hit the comments below.

comments powered by Disqus