Author image
Developer

How to write your own Drush command

Occasionally there's something you need to achieve, which would be really easy if only you could have it performed via Drush - some script that could be run on the server during an update or migration process, perhaps. But it all looks a bit too scary, right? "The task is tricky enough already, let's just do it some other way"?

Well, it's actually surprisingly easy to write your own Drush commands, and it's totally something worth learning. Let's take a look.

(Though do check DrushCommands.com to make sure you're not trying to do something that's already been done!)

Writing a basic Drush command

You need four things, which should feel vaguely familiar as they follow some fairly normal Drupal conventions: A module, a file, a hook implementation and a function to provide your command.

A module

You could probably put your Drush command almost anywhere in your Drupal installation, but usually it makes sense to put it inside a module along with your other code, keeping things nice and tidy.

Let's assume you either have a module, or will disappear quickly to go write a .info file and a .module file. I'll call mine my_awesome_module.

A Drush command file

This is where we'll write our command. It goes in your module folder, and has the naming convention my_awesome_module.drush.inc . As usual, start it off with <?php at the top.

Drush will find our file (and thus our Drush command) by looking across the codebase for all files with the .drush.inc file extension. It'll pick up all the Drush commands in the installation and cache them ready for use.

A simple hook

Adding an implementation of hook_drush_command() inside your .drush.inc file tells Drush what commands we're going to provide. We can declare as many commands as we like - it's just an array - but we'll start with one.

/**
* Implements hook_drush_command().
*/
function my_awesome_module_drush_command() {
  $items['something-awesome'] = array(
    'description' => 'Does something really useful.',
    'aliases' => array('woah'),
  );
  return $items;
}

Each item needs a description and, additionally, you could provide an alias - a shorter name which can be used to call your command. For our example, running drush something-awesome or drush woah will run our command. (The alias 'sa' would make more sense, but it's taken already!)

A function to provide the command

So, we should define the function which will be called to actually do the business. When we use our command in the terminal, Drush will match the command we entered against the hook implementations and find our entry. Having found that, it will try to call our function by translating the name something-awesome into something_awesome and fitting it into the format drush_FILENAME_COMMANDNAME(). (This format makes sure all the Drush commands provided are neatly namespaced and don't clash.)

Since we're following convention, FILENAME (of the .drush.inc file) is our module name, so we get the function name drush_my_awesome_module_something_awesome().

Don't get caught out here - in hook_drush_command you define your command name with -hyphens-, but, as the norm for PHP, function names can't have hyphens, so instead use with underscores.

So, our function definition, inside our .drush.inc file, starts off as:

/*
 * Something-awesome drush command.
*/
function drush_my_awesome_module_something_awesome() {
  // TODO: Write something really awesome.
}

Done!

Ta-da! That's all it takes :) Ensure your module is enabled, clear the Drush cache with drush cc drush, and you should be able to call your command. The Drupal world is your oyster!

Doesn't work?

If your command isn't working, take a look through this checklist:

  1. Is your module enabled? If you wrote it just a minute ago, it's easy to forget to enable it.
  2. Try clearing Drush's cache with drush cc drush. If it previously couldn't find your command, it should now.
  3. Double-check your function names. Make sure you've not left "my_awesome_module" in there somewhere ;)
  4. If your command appears to be running, but you're not sure what it's doing, try adding a print 'hello'; or a drupal_set_message('Testing, testing...'); statement to your command function. XDebug could be your best friend here though.
  5. Try calling it with the --show-invoke option. This will print out all the function names Drush is looking for, which could help you double check your function name.

Doing clever things

Having a basic Drush command is great, but there are some little extras that would allow us to do some slightly clever things... Drush.org has all the documentation you might want and is surprisingly readable, thanks to some clear examples.

Next article in series: