Drupal automatic upgrade script

I got tired of always manually upgrading the necessary files for my Drupal installation and then copying the config back over. So I've automated almost the entire upgrade process with a shell script. All that I must do myself now is put Drupal into maintenance mode.

drupal_upgrade.sh (Don't forget to make it executable: chmod +x drupal_upgrade.sh)

Note: The script assumes that it and the extracted update is in the next directory up from Drupal. Don't forget to set the Drupal directory variable. Also, obligatory "I'm not responsible if you hose you database/Drupal install". TEST THIS SCRIPT IN A SAFE ENVIRONMENT FIRST.

#!/bin/bash

## Drupal Automatic Upgrade Script

TIMESTAMP=`date +%y%m%d%H%M`
BACKUPDIR=drupal_backup_$TIMESTAMP

## Drupal directory (relative to script)
DRUPALDIR='www'

## Database config
DBUSER='root'
DBPASS='password'
DBNAME='drupal'

## Backup Drupal files
mkdir $BACKUPDIR/

cp -pr $DRUPALDIR/includes/ $BACKUPDIR/
cp -pr $DRUPALDIR/misc/ $BACKUPDIR/
cp -pr $DRUPALDIR/modules/ $BACKUPDIR/
cp -pr $DRUPALDIR/profiles/ $BACKUPDIR/
cp -pr $DRUPALDIR/scripts/ $BACKUPDIR/
cp -pr $DRUPALDIR/sites/ $BACKUPDIR/
cp -pr $DRUPALDIR/themes/ $BACKUPDIR/
cp -p $DRUPALDIR/cron.php $BACKUPDIR/
cp -p $DRUPALDIR/index.php $BACKUPDIR/
cp -p $DRUPALDIR/robots.txt $BACKUPDIR/
cp -p $DRUPALDIR/update.php $BACKUPDIR/
cp -p $DRUPALDIR/xmlrpc.php $BACKUPDIR/
cp -p $DRUPALDIR/.htaccess $BACKUPDIR/

## Backup Drupal database
mysqldump -u $DBUSER -p$DBPASS $DBNAME > $BACKUPDIR/$DBNAME.sql

## Remove old and copy new files
rm -r $DRUPALDIR/includes
cp -pr drupal-6.*/includes/ $DRUPALDIR/

rm -r $DRUPALDIR/misc
cp -pr drupal-6.*/misc/ $DRUPALDIR/

rm -r $DRUPALDIR/modules
cp -pr drupal-6.*/modules/ $DRUPALDIR/

rm -r $DRUPALDIR/profiles
cp -pr drupal-6.*/profiles/ $DRUPALDIR/

rm -r $DRUPALDIR/scripts
cp -pr drupal-6.*/scripts/ $DRUPALDIR/

chmod -R +w $DRUPALDIR/sites/default
rm -r $DRUPALDIR/sites
cp -pr drupal-6.*/sites/ $DRUPALDIR/

rm -r $DRUPALDIR/themes
cp -pr drupal-6.*/themes/ $DRUPALDIR/

rm $DRUPALDIR/cron.php
cp -p drupal-6.*/cron.php $DRUPALDIR/

rm $DRUPALDIR/index.php
cp -p drupal-6.*/index.php $DRUPALDIR/

rm $DRUPALDIR/robots.txt
cp -p drupal-6.*/robots.txt $DRUPALDIR/

rm $DRUPALDIR/update.php
cp -p drupal-6.*/update.php $DRUPALDIR/

rm $DRUPALDIR/xmlrpc.php
cp -p drupal-6.*/xmlrpc.php $DRUPALDIR/

rm $DRUPALDIR/.htaccess
cp -p drupal-6.*/.htaccess $DRUPALDIR/

## Replace config
cp -pr $BACKUPDIR/sites/default/* $DRUPALDIR/sites/default/
chmod -w $DRUPALDIR/sites/default
chmod -w $DRUPALDIR/sites/default/settings.php
# Copy additional config files here

Trackback URL for this post:

http://emington.thenewagemedia.com/trackback/1012

Comments

Anonymous's picture

how to execute this script?

Justin's picture

Anonymous wrote:
how to execute this script?

:~$ cd /path/to/script
:~$ ./drupal_upgrade.sh

Anonymous's picture

Script looks nice and simple - easy to tweak. You can put the site offline by adding $conf['site_offline']=1; to your settings.php. And you can have it happen from your script by using sed (or other means I guess).

Justin's picture

Thanks for the tip, think I'll do that! (makes the upgrade completely automatic).

Anonymous's picture

Nice script -- haven't tested it yet. You may want to add the preserve timestamp (-p) parameter to all of your cp commands.

- Marc

Justin's picture

Good idea, added now. Thanks.

Anonymous's picture

Is this script meant to be run on the live server?

Wouldn't rsync be easier?
It can use a text file listing exclusions to avoid copying files or directories. The same exclusions list can be used for backing up and the upgrading, instead of maintaining this script with duplicate cp, rm, cp, entries.

It would boil down to something like this.

rsync -rptgo --exclude-from exclusions.txt source destination

…and the exclusions.txt file could contain…
.htaccess
CHANGELOG.txt
LICENSE.txt
MAINTAINERS.txt
UPGRADE.txt
robots.txt
sites

You could even use rsync to keep x versions of pre-update backups, without consuming too much extra space because rsync will link identical files instead of duplicating when using -aH (I think) instead of -rlptgo.

Justin's picture

Something to consider, thanks. I'll have to do some more reading on rsync if I'm going to do this, but as it is, I just needed something simple and my script fits the bill. By all means, if you want to write one and post it here, please do.

Anonymous's picture

rsync is very powerful, it's worth a look. It can also do snapshots with the only the differences stored. rsnapshot is a utility that makes 'snapshotting' servers really easy.
There are also scripts provided for rsnapshot to dump mysql dbs and rotate them through daily, weekly, monthly … backups.

If what you have works stick with it. I find a list of excludes easier to manage than multiple occurrences of the same path in a script. I'd be tempted to list the exclusions (or inclusions) then loop through them.

Here is my (untested rsync version)

#!/bin/bash

## Drupal Automatic Upgrade Script

TIMESTAMP=`date +%y%m%d%H%M`
BACKUPDIR=drupal_backup_$TIMESTAMP

## Drupal directory (relative to script)
DRUPALDIR='www'

## Database config
DBUSER='root'
DBPASS='password'
DBNAME='drupal'

## Backup Drupal files
mkdir $BACKUPDIR/
rsync -rptgo $DRUPALDIR $BACKUPDIR

## Upgrade drupal
rsync -rptgo --exclude-from exclusions.txt drupal-6.whatever $DRUPALDIR
## exclusions.txt - contains stuff you don't want to overwrite in the site eg sites/default/settings.php, sites/default/files

## Backup Drupal database
mysqldump -u $DBUSER -p$DBPASS $DBNAME > $BACKUPDIR/$DBNAME.sql

It copies everything in the site to a backup folder, then overwrites older Drupal files with ones from drupal6.whatever.

rsync has a lot of options, check out man rsync.

Justin's picture

Cool, I'll try this out and see how well it works. Thanks for the tips.

Anonymous's picture

Removing the 'sites' directory and its contents, only to replace its contents again is not necessary, since the core update leaves this directory explicitly for the site owner's use. Here's an updated script that may use fewer system resources to accomplish the update with less chance for messing up:

#!/bin/bash ## file name: drupal_upgrade.sh ## remember to set this file's permissions: chmod 755 drupal_upgrade.sh ## Drupal Automatic Upgrade Script

## Get the time and name a temporary directory for backup
TIMESTAMP=`date +%y%m%d%H%M`
BACKUPDIR=drupal_backup_$TIMESTAMP

## Drupal directory (relative to script)
## Example:
## If your drupal site is here: /home/user/www.mysite.com
## and your script is here: /home/user/drupal-upgrader/drupal-upgrade.sh
## your DRUPALDIR will be as follows:
## DRUPALDIR='../www.mysite.com'
## Your archives will show up here: /home/user/drupal-updater/drupal_backup_[timestamp]
DRUPALDIR='www'

## Database config
## DBHOST could be 'localhost' for a dev site,
## but for many shared hosting situations,
## you may end up using a named dbhost name.
## DBHOST = 'localhost'
DBHOST='mysql.mysite.com'
DBUSER='my_database_user'
DBPASS='my_password'
DBNAME='drupal_database'

## Backup Drupal files
mkdir $BACKUPDIR/

cp -pr $DRUPALDIR/includes/ $BACKUPDIR/
cp -pr $DRUPALDIR/misc/ $BACKUPDIR/
cp -pr $DRUPALDIR/modules/ $BACKUPDIR/
cp -pr $DRUPALDIR/profiles/ $BACKUPDIR/
cp -pr $DRUPALDIR/scripts/ $BACKUPDIR/
cp -pr $DRUPALDIR/sites/ $BACKUPDIR/
cp -pr $DRUPALDIR/themes/ $BACKUPDIR/
cp -p $DRUPALDIR/cron.php $BACKUPDIR/
cp -p $DRUPALDIR/index.php $BACKUPDIR/
cp -p $DRUPALDIR/robots.txt $BACKUPDIR/
cp -p $DRUPALDIR/update.php $BACKUPDIR/
cp -p $DRUPALDIR/xmlrpc.php $BACKUPDIR/
cp -p $DRUPALDIR/.htaccess $BACKUPDIR/

## Backup Drupal database
mysqldump -h$DBHOST -u$DBUSER -p$DBPASS $DBNAME > $BACKUPDIR/$DBNAME.sql

## Remove old and copy new files
rm -r $DRUPALDIR/includes
cp -pr drupal-6.*/includes/ $DRUPALDIR/

rm -r $DRUPALDIR/misc
cp -pr drupal-6.*/misc/ $DRUPALDIR/

rm -r $DRUPALDIR/modules
cp -pr drupal-6.*/modules/ $DRUPALDIR/

rm -r $DRUPALDIR/profiles
cp -pr drupal-6.*/profiles/ $DRUPALDIR/

rm -r $DRUPALDIR/scripts
cp -pr drupal-6.*/scripts/ $DRUPALDIR/

rm -r $DRUPALDIR/themes
cp -pr drupal-6.*/themes/ $DRUPALDIR/

rm $DRUPALDIR/cron.php
cp -p drupal-6.*/cron.php $DRUPALDIR/

rm $DRUPALDIR/index.php
cp -p drupal-6.*/index.php $DRUPALDIR/

rm $DRUPALDIR/robots.txt
cp -p drupal-6.*/robots.txt $DRUPALDIR/

rm $DRUPALDIR/update.php
cp -p drupal-6.*/update.php $DRUPALDIR/

rm $DRUPALDIR/xmlrpc.php
cp -p drupal-6.*/xmlrpc.php $DRUPALDIR/

rm $DRUPALDIR/.htaccess
cp -p drupal-6.*/.htaccess $DRUPALDIR/

## Copy additional config or include files here...

## Example for transferring your old imagemagick include file...
## This example only executes if the include file was already in
## your core include folder archive - (in the $BACKUPDIR).
MYFILE=$BACKUPDIR/includes/image.imagemagick.inc
if [ -e $MYFILE ];
then
cp -p $BACKUPDIR/includes/image.imagemagick.inc $DRUPALDIR/includes
fi

I've removed these snippets of code:
chmod -R +w $DRUPALDIR/sites/default
rm -r $DRUPALDIR/sites
cp -pr drupal-6.*/sites/ $DRUPALDIR/

and

## Replace config cp -pr $BACKUPDIR/sites/default/* $DRUPALDIR/sites/default/ chmod -w $DRUPALDIR/sites/default chmod -w $DRUPALDIR/sites/default/settings.php

To use this script from SSH logged into your shared server:
First:
A. Put your site in offline mode
B. Change to a core theme.
C. Uncheck all non-core modules. (Remember them for later so you can turn them back on.)

Second:
1. Go to drupal.org in firefox. Go to the download page for 6.x (or your preferred)
2. Right-click and copy the link location for the file download.
3. In shell, navigate to where your script is located. I've got mine at home/user/drupal-updater/.
4. TYPE: wget
5. Paste the link. In Putty, just right-click, and the link will paste. You'll see something like this:
wget http://ftp.drupal.org/files/projects/drupal-6.10.tar.gz
6. Hit return. The tar.gz file will download right next to your script.
7. TYPE: "tar -xzvf drupal-6.10.tar.gz" without quotes and hit return. You'll see the files unarchive nicely into a folder 'drupal-6.10' (or whatever version).
8. Make sure your script is chmodded to 755
chmod 755 drupal-upgrade.sh
9. Hit return.
10. Execute the script. This could take some minutes, looking like nothing is happen after you hit return, so don't panic. When the prompt comes back to it's normal blinking text entry mode you're done with this step.
./drupal-upgrade.sh
11. Go to your firefox browser and execute the mysql updater script:
http://www.mysite.com/update.php
This could take some time too, so again, don't panic.

Third:
A. Re-engage your preferred modules.
B. Re-engage your preferred theme if it's not a core theme.
C. Put the site back in online mode.

You're done.

Anonymous's picture

Thanks so much for this script!

I also tweaked it a little like gr33nman to save my sites directory by removing the following lines:

chmod -R +w $DRUPALDIR/sites/default rm -r $DRUPALDIR/sites cp -pr drupal-6.*/sites/ $DRUPALDIR/ cp -pr $BACKUPDIR/sites/default/* $DRUPALDIR/sites/default/ chmod -w $DRUPALDIR/sites/default chmod -w $DRUPALDIR/sites/default/settings.php Thanks again!

P.S. The comment preview on your site does not work for me.

Anonymous's picture

Your not moving a few files that should be moved and your overwriting cron by updating the script dir, which if working should probably not need updating.. a cp -pr of *.php should fix the update, index, etc in the root dir and commenting out scripts unless their's an update should fix any cron issues expectantly with multi sites.

TIP: With root access to your database you can add multiple databases on the same user..

in addition if you want to be lazy and not take your site off-line manually perhaps you should do what's found their..
samat.org/comment/reply/149

You should also flush the cache when doing, that script still allows people to view the site because of it.. Permissions and file properties should also be set with chown and chmod aswell unless the www-data user has been tied to the user of the user dir.

I haven't actually tried this yet if/when I do and finish it successfully I'll try and remember to repost my ideas/script.

Thank to everyone for their comments tips and ideas..

Anonymous's picture

Can this code applied to code with version control ? I try using it and it asking confirmation for deleted svn file.

Anonymous's picture

I'm a bit perplexed that Drush hasn't been mentioned here. It does this and a lot of other handy stuff too.

Anonymous's picture

@xurizaemon drush only updates modules, not drupal core. At least in drupal 6. I hear in drupal 7 will have this functionality.

Anonymous's picture

[...] tweaked Justin’s script a bit. The drupal_upgrade.sh script I [...]

Anonymous's picture

Are you a professional journalist? You write very well.

Anonymous's picture

[...] Drupal automatic upgrade script justin-hayes.com/2008-12-10/drupal-automatic-upgrade-script – view page – cached A simple bash script to automate the process of upgrading Drupal minor versions. — From the page [...]

Post new comment

  • Allowed HTML tags: <a> <em> <strong> <b> <p> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • You can use BBCode tags in the text. URLs will automatically be converted to links.
  • You may use [inline:xx] tags to display uploaded files or images inline.
  • You may quote other posts using [quote] tags.
  • Each email address will be obfuscated in a human readable fashion or (if JavaScript is enabled) replaced with a spamproof clickable link.
  • You may insert videos with [video:URL]

More information about formatting options