Switching between Drush major versions

[Edit: updated for Drush 8. You might also want to consider entirely composer-based Drush version management.]

As I do a lot of work on legacy code and sites, I find it useful to have multiple versions of Drush installed on my laptop; it's also handy for testing version compatibility of my own projects like Drush Instance.

However, for convenience I also want to be able to refer to any given Drush version as just "drush" at the command prompt. If you want to do this, you need: local installations of more than one Drush versions, in different locations; and a switching mechanism. Here's one possible solution, for Debian/Ubuntu.

Installing Drush versions in /opt

My personal preference for manual installations is in /opt. I believe this can cause problems on some OSX versions at least, so if you've got some peculiarity with your own system then do feel free to install these packages where you see fit.

To begin, create /opt if it doesn't already exist, and make it owned by you.

sudo mkdir /opt
sudo chown MY-USERNAME /opt

Then install some Drush versions in some subdirectories. Drush 6 to 8 are straightforwardly installable using composer:

mkdir /opt/drush6 && cd /opt/drush6
composer require "drush/drush:6.*"
mkdir /opt/drush7 && cd /opt/drush7
composer require "drush/drush:7.*"
mkdir /opt/drush8 && cd /opt/drush8
composer require "drush/drush:dev-master"

Drush 5 and earlier don't seem to be installable using composer, but it's very quick to install these manually using the Github zipfile(s):

cd /opt
wget https://github.com/drush-ops/drush/archive/5.10.0.zip
unzip 5.10.0.zip
mv drush-5.10.0 drush5

You can now manually reference different versions of Drush thus:

/opt/drush5/drush --version
/opt/drush6/vendor/bin/drush --version
/opt/drush7/vendor/bin/drush --version
/opt/drush8/vendor/bin/drush --version

The next step is to make these switchable, so that you can change the version called when you just type "drush".

Installing into the "alternatives" framework

On Debian systems, many executables can be managed so that any one of them at any time "serves" the actual command in e.g. /usr/bin. The command to manage these alternative versions is called update-alternatives.

Install your three different Drush versions into the alternatives system using the following commands:

sudo update-alternatives --install /usr/bin/drush drush /opt/drush5/drush 5
sudo update-alternatives --install /usr/bin/drush drush /opt/drush6/vendor/bin/drush 6
sudo update-alternatives --install /usr/bin/drush drush /opt/drush7/vendor/bin/drush 7
sudo update-alternatives --install /usr/bin/drush drush /opt/drush8/vendor/bin/drush 8

The last figure is actually a priority: as it's currently set, the system will automatically prioritize Drush 8, because its priority "8" is highest. You could of course set different priorities, so that your preferred major version comes out on top, but we'll see below why it's useful to set the major version number as the priority.

Switching between Drush versions

As mentioned above, the highest-priority alternative will be the default, if the alternatives are configured in "auto mode" (again, the default.) However, it's very quick to switch to manual mode, and thus switch to a manually selected alternative.

The recommended way to choose a different alternative at the command line is the following, which calls up an interactive user interface in the terminal:

sudo update-alternatives --config drush
There are 3 choices for the alternative drush (providing /usr/bin/drush).
...

This interface does require you to then manually press the number of the alternative you want (1..3 in this case) and press enter. Also, the non-interactive alternatives require you to give the full path to the Drush executable, which seems to be a failing of the alternatives system: why register those alternatives in the first place, if you then have to supply their full paths at a later date in order to switch them?

However, there's a shortcut you can use. If you've set your priorities to be your Drush major versions, then the following one-liner will use the filtered output from one update-alternatives command to automagically set the alternative in a second command:

version=6; command=`update-alternatives --display drush | grep "priority $version" | awk '{print $1}'`; \
  sudo update-alternatives --set drush "$command"

You could actually save this as a file called /usr/bin/switchdrush:

#!/bin/bash
 
version="$1"
command=`update-alternatives --display drush | grep "priority $version" | awk '{print $1}'`
sudo update-alternatives --set drush "$command"

Then sudo chmod +x this file, and you can run it in the future as follows:

switchdrush 6

Summary

You should now be able to switch your Drush version very quickly using the alternatives system.

In principle, much of what the alternatives system provides, you could code yourself. Especially when it comes to having to write the switchdrush executable. However, in practice, it's reassuring to be able to rely an existing framework that you know is robust: if in doubt, you can always drop back down to that system.