Hooking into Drush and Aegir


(Disclaimer: I'm still just learning this stuff, so please let me know if you notice anything wrong in here)

If you build and maintain Drupal sites and haven't used Drush yet, it's time you take a look at it. Even if you only use it for very basic things such as downloading and updating modules it can still be a big time saver.

One of the things that makes Drush so powerful is it's flexibility with hooks. Each Drush command can be hooked in at three different levels; before, during, and after it runs. The hooks are pre, validate, and post, respectively. It works slightly differently than the Drupal hook system but the concept is the same.

In order to hook into a Drush command you need to create your own command file (i.e.: example.drush.inc). In a command file you can create your own commands or hook into existing ones. For this post I'm only going to talk about hooking into existing ones but the Drush documentation has examples of creating your own (thanks to Adrian for helping me out with this stuff! And happy birthday too!).

The major component of Aegir that uses Drush is the provision module. The provision module adds several commands to Drush to handle various site provisioning tasks such as install, enable, disable, backup, migrate, etc. When trying to hook into Aegir you can put your example.drush.inc file either in a custom module (in your hostmaster site) or within your ~/.drush/ folder. Just keep in mind that many provision commands execute before the the site has been bootstrapped and installed, and in these cases the .drush.inc must reside in you ~/.drush folder.

For example, let's say I want to add some extra actions to happen when the provision-backup command is called. I would create a file ~/.drush/extrabackup.drush.inc. In that file I'd place the following code:

function drush_extrabackup_pre_provision_backup($url = NULL) {
  // Code to run prior to the backup

function drush_extrabackup_provision_backup_validate($url = NULL, $backup_file = NULL) {
  // Code to run "during" the backup

function drush_extrabackup_post_provision_backup($url = NULL) {
  // Code to run after the backup

When inside of these hooks you can do things like drush_get_option('profile') so that you only apply actions to specific install profiles, for example. The $url represents the site that the command is being performed on.

Aegir's hosting module also adds Drush commands. Namely, hosting-dispatch, hosting-setup, and hosting-task. If you have a custom module you can hook into these too (in fact, this is one of the best ways to make data from Aegir accessible to your install profile). Just name your file <modulename>.drush.inc and check the hosting module folder for examples on how it's sub modules use those three commands.

Peanut Gallery

Many, many thanks for this,

Many, many thanks for this, we just added mirroring backups to s3 with the following code in a cm_functions.drush.inc file:

function drush_cm_functions_post_provision_backup($url = NULL) {
$backup_file = drush_get_option('backup_file');
// Make sure a backup happened:
if (is_file($backup_file)) {
// Upload the file to the correct place in S3:
$parts = array('cm-server-backups');
$filename = basename($backup_file);
list($site_name, $rest) = explode('-', $filename, 2);
list($date, $time, $rest) = explode('.', $rest, 3);
$year = substr($date, 0, 4);
$month = substr($date, 4, 2);
$day = substr($date, 6, 2);

$parts[] = $site_name;
$parts[] = "$year-$month";
$parts[] = $day;
$parts[] = $filename;

$command = 's3cmd put %s s3://%s';

$result = provision_shell_exec($command, $backup_file, implode('/', $parts));

if (!$result && !drush_get_option('force', false)) {
drush_set_error('PROVISION_BACKUP_FAILED', dt("Could not backup the file to S3"));

else {
drush_log(dt("Could not backup the file to S3 because I couldn't find: !backup_file", array('!backup_file' => $backup_file)), 'backup');


Cool! I think I could use

Scott Hadfield

Cool! I think I could use that s3 code myself :)