Drupal upgrade script

EDIT: The script below has been updated to work with Drush 3.x. Those using previous versions of Drush will need to edit the script appropriately. The nature of the change was to use the new Drush 3.x standard of no spaces with command names, so "drush sql dump" was changes to drush sql-dump."

Before using this script, make sure that all your contributed themes and modules are somewhere in the "sites/" directory. If they are in any other Drupal core directories, your modules and themes will be lost.

I run a handful of small Drupal sites that I can't afford to spend too much maintenance time on, but that still need to be updated with the occasional maintenance version of Drupal.

It can be quite time-consuming to manually update 4 or 5 sites each time a security release is published.

So, a couple months ago I spent an afternoon writing a shell script to automate the whole task. With a little help from Drush, it turns a 10 or 15 minute maintenance task into about 10 or 15 seconds.

Here's what it looks like.

$ drupal-upgrade 6.15
Putting site in offline mode...
Backing up current Drupal core files... Done.
Backing up current Drupal database... Done.
Start downloading drupal-6.15.tar.gz... Done.
Upgrading Drupal core files... Done.
Upgrading Drupal database... No database updates required
Cache cleared.
Finished performing updates.
Putting site back online... Done.
If something went horribly wrong type "restore" to restore from backup:
Your upgrade is complete
Backup files before the upgrade where saved in the following locations:

From the output, you can see that the script does the following:

  • Take the site offline
  • Backup the Drupal core files
  • Backup the database
  • Download the chosen version of Drupal
  • Update the filesystem with the new version of Drupal
  • Run any database updates (update.php)
  • Put the site back online

Before the script finishes, it gives you the chance to restore both the filesystem and the database in case anything went horribly wrong.

Now updating to the latest maintenance release is a breeze.

Here is the script.

# A script to upgrade a Drupal installation to the next minor version
# This script uses drush to initiate database updates; comment out lines beginning with "drush" if you don't have drush installed
# check for user input
if [ ! $@ ]; then
  echo "  Usage:"
  echo "    $0 VERSION [DIRECTORY]"
  echo "    VERSION: The new version to install"
  echo "    DIRECTORY: The relative path to your Drupal installation; if blank the current directory is assumed"
  echo "  Example usage:"
  echo "    $0 6.9 public_html/"
  exit 0
if [ ! $2 ]; then
# Put the site offline
echo "Putting site in offline mode..."
drush vset --yes site_offline 1 > /dev/null
# backup core files
echo -n "Backing up current Drupal core files... "
tar -czf ../drupal-core.backup.tgz ./.htaccess ./*.php ./includes ./misc ./modules ./profiles ./scripts ./themes
echo "Done."
#backup database; use result-file option to prevent charset corruption
echo -n "Backing up current Drupal database... "
drush sql-dump --result-file=../drupal-upgrade.backup.sql.tgz
echo "Done."
# example download link http://ftp.drupal.org/files/projects/drupal-6.9.tar.gz
echo -n "Start downloading $DRUPAL_PACKAGE... "
wget -q $DOWNLOAD
echo "Done."
echo -n "Upgrading Drupal core files... "
tar -xzf $TMP_FILE --exclude-from=.htaccess -C $TMP
rm -rf "./includes"
cp -pr "${TMP}/${DRUPAL_VERSION}/includes" "./includes"
rm -rf "./misc"
cp -pr "${TMP}/${DRUPAL_VERSION}/misc" "./misc"
rm -rf "./modules"
cp -pr "${TMP}/${DRUPAL_VERSION}/modules" "./modules"
rm -rf "./profiles"
cp -pr "${TMP}/${DRUPAL_VERSION}/profiles" "./profiles"
rm -rf "./scripts"
cp -pr "${TMP}/${DRUPAL_VERSION}/scripts" "./scripts"
rm -rf "./themes"
cp -pr "${TMP}/${DRUPAL_VERSION}/themes" "./themes"
# The .htaccess file is purposely not copied
cp -p ${TMP}/${DRUPAL_VERSION}/*.* ./
rm -rf "${TMP}/${DRUPAL_VERSION}/"
echo "Done."
echo -n "Upgrading Drupal database... "
yes | drush updatedb
echo "Done."
# Put the site back online
echo -n "Putting site back online... "
drush vset --yes site_offline 0 > /dev/null
echo "Done."
echo -n "If something went horribly wrong type \"restore\" to restore from backup: "
if [ "$RESTORE" = "restore" ]; then
  echo -n "Restoring database... "
  MYSQL_CONNECT=$(drush sql-connect)
  $MYSQL_CONNECT < ../drupal-upgrade.backup.sql.tgz
  echo "Done."
  echo -n "Restoring files... "
  tar -xzf ../drupal-core.backup.tgz -C ./
  echo "Done."
  drush vset --yes site_offline 0 > /dev/null
  echo "Your upgrade failed, but the backup was restored"
  echo "Your upgrade is complete"
BACKUP_DIR=$(readlink -f ../)
echo "Backup files before the upgrade where saved in the following locations:"
echo "  ${BACKUP_DIR}/drupal-core.backup.tgz"
echo "  ${BACKUP_DIR}/drupal-upgrade.backup.sql.tgz"

To make the script available to any user on the command line, put it in the /usr/local/share directory then create a symlink from the /usr/local/bin directory.

$ mkdir /usr/local/share/drupal
$ cp drupal-upgrade.sh /usr/share/drupal/drupal-upgrade.sh
$ ln -s /usr/local/share/drupal/drupal-upgrade.sh /usr/local/bin/drupal-upgrade
$ chmod 755 /usr/local/bin/drupal-upgrade
drupal-upgrade.sh_.gz1.2 KB


What about non-core modules?

Is there a way to automate saving status of, then disabling and re-enabling the non-core modules, to ensure nothing goes wrong there?

At least, I know the upgrade instructions always include to disable non-core modules, then re-enable after the upgrade.

I was thinking of how nice it'd be to automate the whole thing and include that. My thought is that couldn't you run a few queries to take care of this part, or is it possible to run queries from such a script?

No need that I see

There isn't a need to disable any modules if you are doing a minor release upgrade. You only need to do that if you are doing a major release upgrade, like from Drupal 5.x to 6.x.

Hello! And thanks for this

Hello! And thanks for this usefull script! With the command "up", Drush update, upgrade, and make a backup of the old files. You just need to make a backup of the db with the sql-dump command. Is there a special reason you didn't proceed that way? Greetings. MR