Drupal 7 Upgrades with Scripts and Drush

A Drupal upgrade between major versions rarely means doing the upgrade procedure once. A new configuration, changing content, or needing to test different module versions typically means redoing the upgrade from scratch a number of times, a tedious, error-prone and time consuming process. Fortunately there's a solution: automation!

Scripting was always possible, but Drush has made it so much simpler. What follows is a review of the Drush commands I used via script to upgrade my Group 42 website to Drupal 7. The hand full of shell commands are basic and covered many other places on the net. The full upgrade scripts are at the end of the post.

If you're familiar with Drush I recommend jumping directly to the scripts.

Starting Notes

-y / --yes option: This option skips the yes/no confirmation question required by some Drush commands. Since the examples in this post come from scripts this option is shown in the examples.

Drush site aliases: I almost always use a Drush site alias (the "@site-name) parameter, with a command. Some of the commands outlined in this post will only work if you have a site alias. Among other things, it means you can run the command from anywhere.

Drush site-upgrade command: One command you won't find in this post is the Drush site upgrade command. After 20 minutes of trying to use it I gave up. As nearly as I can tell my site wasn't configured the way the command needed it configured. Your results could be different so you'll want to check it out.

Watchdog Log Commands

At various points in the upgrade it's a good idea to check the watchdog log:

drush wd-show

Module Commands

The term module is commonly used to refer to an entire Drupal project even though a typical Drupal project contains more than one module. This can be confusing if the project also has a module with the same name, such as Views. Drush downloads and uninstalls projects, but lists, enables, and disables modules. For example, to remove the Views project in Drupal 6 you disable the Views, Views UI, and Views Export modules, then uninstall the Views project.

Multiple modules can be acted on at once. Examples are shown for both a single and multiple modules.

Listing modules

Drush is an easy way to list installed modules. This is useful for module research lists and creating a list of modules to cut and paste into your script.

For a full summary:

drush pm-list

For a lists all of enabled contributed modules displayed one module per line:

Running update.php using Drush means you don't need to log on as user 1 or use $update_free_access if you forget. Although Drush will tell you if an update error occurred, I like displaying the watch dog log as well.

Theme Commands

Themes are enabled and disabled in the same way modules are. You can also set the current theme, administration theme, and theme settings from the Drush command line.

Enable a theme

drush @g42dev -y pm-enable garland

Disable a theme

drush @g42dev -y pm-disable barron

Set the default theme

drush @g42dev -y vset theme_default garland

Set the default administration theme

drush @g42dev vset -y admin_theme seven

Set the theme settings

Theme settings are a bit challenging. In Drupal 7 they're stored as an array. As of writing the current version of Drush could not set arrays with the vset command. However, using the php-eval command it's possible to use the Drupal variable_set() function to set the theme variables.

The following example has been broken into multiple lines for display purposes, but is one, long wrapped line when executed:

July 13, 2011: Per the comment from dalin, the following syntax is probably better than using the BASH back-tick syntax. If I had known about it I would have used it instead.

drush @g42dev sql-cli < /tmp/group42db.sql

Changing Settings

Many Drupal system and contributed module settings are easily changed using the variable set command. A number of other settings require a direct database update. Since you can easily damage your database doing direct updates I wouldn't recommend using this option unless you know what you're doing.

Site Online / Offline

Since I run my scripts on a development server with no users I don't usually bother with offlining my site. I've included it here because it's easy and something others may want to do in their upgrades.

Whether from Drush or the web administration interface, I've found I need to clear the page cache if it's enabled.

Site Offline

drush vset site_offline 1 --yes
drush cc all

Site Online

drush vset site_offline 0 --yes
drush cc all

Site Information

In the early stages of upgrade testing I'll change my site name and slogan to make my test site easy to tell apart from my production site.

Site Name

drush @g42dev vset --yes site_name "G42 Clone"

Site Slogan

drush @g42dev vset --yes site_slogan "Drupal 7 Upgrade Testing"

Block Position

Since you can corrupt your database with a bad SQL command I wouldn't recommend doing this command unless you're comfortable that you know what you're doing.

Path Alias

The default feed URLs for taxonomy terms have changed from /taxonomy/term/n/0/feed to /taxonomy/term/n/feed. There was only one taxonomy term feed I was worried about (Drupal Planet!), so I created an alias for it:

The Attached Scripts

The two attached scripts are the actual scripts I used for the Drupal 7 upgrade of this website. They are intended as real-world examples and NOT meant to be prescriptive. Everyone's workflow tends to be different, and these scripts are in service of my workflow. I recommend adapting them to yours. Also, I only loosely followed the upgrade sequence outlined in UPDATE.txt. My upgrade sequence may not work for your site. Take what works for you and leave the rest behind!

In case it's useful, my upgrade workflow was:

Clone the production site as required, either to reset for an upgrade run or to refresh content

Run the upgrade script and test as required

Merge the upgraded file base into the main trunk

Upgrade production site by switching to the new file base and copying the database from the upgrade test site to production site

clonetodev.sh script

This script copies the source website to the upgrade testing site. It's used to reset the upgrade site for repeated testing.

upgrade_d7.sh script

As I mentioned, this script does not follow the same sequence outlined in UPGRADE.txt. If you use this script as a starting point it's your call whether you maintain the sequence, change it to follow UPGRADE.txt, or adopt a sequence of your own. The nice thing about scripts is it's easy to try different scenarios.

This site has one node-type using CCK and it isn't used anymore, so I don't have a lot of experience yet with CCK updates. I did run the CCK field upgrade just to see what would happen and it worked OK. It's not a complicated content-type, though.

For a complicated build or taking fields from Drupal 5 to 7 it might almost be better to build the Drupal 7 site fresh and import the date from the old site. There's a growing set of tools and scripting techniques that make this straightforward.

Thanks for the sql-cli heads-up, dalin. Using sql-connect came from the Drush documentation page: http://drush.ws/#sql-connect. I like the sql-cli syntax better.

Regarding path auto, I discovered the load/save by accident when I edited and saved a single node while troubleshooting and saw all of the path aliases suddenly start working. The node_load/node_save is a code version of the manual process. Point taken on the batch tool.

At the time that this post was written, the site-upgrade command was of limited use for anything but the simplest sites; the new version makes the upgrade process significantly easier, though. The beta release is out today; for more information, see the project page at http://drupal.org/project/drush_sup