An Introduction to Drupal's Command Line Interface, Drush
I previously wrote about a couple of bash scripts I wrote to manage Drupal core and module updates via SVN. While those scripts handle the basics pretty well, I realized that I needed to get to know Drush. I have a few Drupal upgrade project's coming up, so I spent the past few days getting familiar with Drush. Here's what I've learned so far.
Drush, What is it? What does it do?
Drush is a command line interface to Drupal. At it's core, it's a shell script (Unix/Linux), or a bat script (Windows), and a collection of PHP scripts which handle most Drupal maintenance tasks. Here are some of the things you can do with the current Drush release, version 4.4.
- View info: version, install location, status, module info, site activity (watchdog)
- Manage modules: enable, disable, download, install, uninstall
- Update: update core (Drupal 6 to 7), modules, and the database (update.php)
- Deploy: install via profiles or update remote instances via rsync
- Maintain: dump the database, run cron, clear caches, build the search index, get and set core and module variables
- Extend: Several modules add Drush features and you can create your own.
Install Drush by either downloading it from its drupal.org project page or through a package manager on Debian or Ubuntu. MacPorts has an older version of Drush which requires PHP 5.2, so I downloaded and installed manually.
cd /usr/local wget http://ftp.drupal.org/files/projects/drush-7.x-4.4.tar.gz tar xvf drush-7.x-4.4.tar.gz
Then add Drush to your path in your profile.
Basic Drush Commands
Now you're ready to give it a try. Here are a few basic commands to get you started.
View Drush and Drupal information. You can either change to your root Drupal installation directory, or use the --root/-r flag and provide the path to Drupal regardless of where you happen to be in the file system.
cd /var/www/drupal drush status Drupal version : 6.22 Site URI : http://default Database driver : mysqli Database hostname : localhost Database username : root Database name : drupal6 Default theme : garland Administration theme : garland PHP configuration : Drush version : 4.4 Drush configuration : Drush alias files : Drupal root : /home/chad/drupal-6 Site path : sites/default
Run cron for the site.
drush cron Cron run successfully. [success]
Clear site caches, which comes in handy while developing themes and modules.
drush cc Enter a number to choose which cache to clear.  : Cancel  : all  : theme registry  : menu  : css+js  : block  : module list  : theme list 1 'all' cache was cleared [success]
List all available modules and themes, including version, description, and status.
drush pm-list Package Name Type Status Version <snip> Core - optional PHP filter (php) Module Not installed 6.22 Core - optional Ping (ping) Module Not installed 6.22 Core - optional Poll (poll) Module Not installed 6.22 Core - optional Profile (profile) Module Not installed 6.22 Core - optional Search (search) Module Not installed 6.22 </snip>
Enable an existing module.
drush pm-enable poll The following extensions will be enabled: poll Do you really want to continue? (y/n): y poll was enabled successfully. [ok]
Download, install, and enable a new contributed module in sites/all/modules/.
drush dl vertical_tabs Project vertical_tabs (6.x-1.0-rc1) downloaded to [success] /home/chad/drupal-6/sites/all/modules/vertical_tabs. % drush en vertical_tabs The following extensions will be enabled: vertical_tabs Do you really want to continue? (y/n): y vertical_tabs was enabled successfully.
Update an existing module(s).
drush pm-updatecode vertical_tabs-1.0-rc2 Update information last refreshed: Wed, 07/06/2011 - 22:14 Update status information on all installed and enabled Drupal projects: Name Installed version Proposed version Status Administration menu 6.x-3.0-alpha4 6.x-3.0-alpha4 Up to date Drupal core 6.22 6.22 Up to date Vertical Tabs 6.x-1.0-rc1 6.x-1.0-rc2 Specified version available Views 6.x-2.12 6.x-2.12 Up to date Code updates will be made to the following projects: Vertical Tabs [vertical_tabs-6.x-1.0-rc2] Note: A backup of your project will be stored to backups directory if it is not managed by a supported version control system. Note: If you have made any modifications to any file that belongs to one of these projects, you will have to migrate those modifications after updating. Do you really want to continue with the update process? (y/n): y Project vertical_tabs was updated successfully. Installed version is now 6.x-1.0-rc2. Backups were saved into the directory [ok] /usr/local/drush-backups/drupal6/20110707052105/modules/vertical_tabs. 'all' cache was cleared [success] You have pending database updates. Run `drush updatedb` or visit update.php in your [warning] browser.
Run update.php after installing updates.
drush updatedb The following updates are pending: color module 6001 - Warn site administrator if unsafe CSS color codes are found in the database. Do you wish to run all pending updates? (y/n): y Executing color_update_6001 [success] 'all' cache was cleared [success] Finished performing updates.
Pretty cool, isn't it? And this is just the tip of the Drush iceberg.
If you have trouble running commands, try the verbose (-v) and debug (-d) flags to show more output. There are known issues with Drush failing to make database connections when mysql.sock doesn't exist in the standard location. I found this Drush issue thread very helpful and in my case, changing my development server's database host name from localhost to 127.0.0.1 in settings.php allowed me to run module-related commands.
Try 'drush help', download a cheatsheet, or checkout the Drush homepage for a complete list of commands. There are shorter aliases for most Drush commands.
Configure Drush for Multisite and Remote Operations
It doesn't take long to get up and running with a single site, but if you're running multisite, multiple instances (development, staging, live), or remote instances, there's a bit more configuration you'll want to do.
Drush will look for configuration files in several places, including your drush install folder, root drupal install directories, and your home directory. I chose to use my home directory and created a dot drush folder there.
Now create your Drush configuration file. I have both Drupal 6 and 7 development instances installed locally. Since most of my sites are still running on Drupal 6, I set my default root and URI flags to my Drupal 6 instance.
<?php // Increase PHP's memory limit, -1 for no limit ini_set('memory_limit', '256M'); // Local root Drupal directory $options['r'] = '/home/chad/drupal-6'; // URI of my local Drupal instance $options['l'] = 'http://d6.local'; ?>
In multisite environments, set up an alias configuration file to avoid the need to specify a --uri for each site you maintain. I defined shortcuts for my each of my local development and remote production Drupal instances.
<?php $aliases['dev-d7'] = array( 'uri' => 'd7.local', 'root' => '/home/chad/drupal-7', ); $aliases['live-mysite'] = array( 'uri' => 'mysite.com', 'root' => '/var/www/mysite.com/htdocs', 'remote-host' => 'ssh.server.com', 'remote-user' => 'ssh-login', ); $aliases['dev-mysite'] = array( 'uri' => 'mysite.local', 'root' => '/home/chad/Sites/drupal', ); $aliases['live-mysite'] = array( 'uri' => 'mysite.com', 'root' => '/var/www/mysite.com/htdocs', 'remote-host' => 'ssh.server.com', 'remote-user' => 'ssh-login', ); ?>
Now, instead of specifying --uri for a Drupal multisite instance, specify the alias instead. The following lists just active modules for a site.
drush @dev-mysite pm-list
Simplify Drupal Maintenance with Drush
Think of all the possibilities Drush opens up for maintaining existing sites and deploying new ones. You can write command line scripts to build workflows which combine Drush with your existing version control workflow, perform smart database backups which omit unneeded cache tables, and much more. Write a script which deploys site and module updates via Git, Subversion, or rsync!
What will you do or have you done with Drush?
2012-04-28 - Updated drush.rc.php to drushrc.php, thanks anonymous commenter!