Easy Drupal maintenance and upgrades

Since Drupal has been coming out with rapid updates, mainly due to security fixes, it's quite cumbersome to have to keep it up to date. However, with the below setup and the script to help with the maintenance, it was a breeze with the last update. The script has been used to upgrade from 5.5 to 5.6 release.

Note: The script does not currently have any checks (extreme alpha stage) and my Drupal installation is not a standard install so usage may vary. Make sure you understand the script prior to running it. Usual disclaimer applies. You will also need root level access to shell to run the script as it is set to change ownership of files and folders using the "chown" command.

My current Drupal install are based on symbolic links for easy maintenance and upgrades. The layout is as below:

/var/www/html, /var/www/html/site_files, /var/www/html/sites are all symbolically linked to the /var/www/drupal-5.x, /var/www/drupal_files, /var/www/drupal_sites respectively where /var/www/html is the web root.

Document Root = /var/www/html            -> /var/www/drupal-5.x
Files Folder  = /var/www/html/site_files -> /var/www/drupal_files
Sites Folder  = /var/www/html/sites      -> /var/www/drupal_sites

Also, any customization to the .htaccess is on top of the default Drupal code. So the script will automatically prepend the data to the upgraded .htaccess file. Since, I also have the gallery module, the .htaccess file is also set to be writable by apache.

Don't forget to set your site in "maintenance mode" with the default theme, and disable all modules prior to the upgrade. Although, I've done some updates with all modules available without any issues. Also, my custom theme resides in the sites folder and stays untouched with the update.

Place the script in "/var/www" (just outside your document root) and run the update via:

# sh ./update_drupal.sh 5.x

Once completed, run update.php to update any changes to the database. Set site back to production mode, re-applying any customization as necessary.

Source Code for "update_drupal.sh"

#!/bin/bash
# update_drupal.sh
# Desc: Script to update drupal 5.x release.
# Usage: ./update_drupal.sh <version>
# Example: ./update_drupal.sh 5.6
# Note: Update the variables as required.

VERSION=${1?"Usage: $0 <version>"}
DOWNLOAD_URL=http://ftp.drupal.org/files/projects/
DRUPAL=drupal-${VERSION}

DB=("<db1>" "<db2>")
DB_USER=<db_user>
DB_PASS=<db_pass>
DB_BAK_PATH=./bak/db/

DATE_TODAY=`date +%Y%m%d`

USER=<username>
GROUP=<groupname>
APACHE_USER=<apache>

### Nothing to change below ###

#// Make a backup of database
[ ! -d "${DB_BAK_PATH}" ] && mkdir -p ${DB_BAK_PATH}

for ((i=0; i<${#DB[@]}; i++))
do
  echo "Creating backup of database ${DB[$i]} ..."
  mysqldump --opt -u $DB_USER --password=${DB_PASS} ${DB[$i]} > ${DB_BAK_PATH}${DB[$i]}_${DATE_TODAY}.sql
done

echo "Database backups done."

#// Download source
echo "Downloading source ${DOWNLOAD_URL}${DRUPAL}.tar.gz ..."
wget ${DOWNLOAD_URL}${DRUPAL}.tar.gz
echo "Download done."

#// Extract source
echo "Extracting ./${DRUPAL}.tar.gz ..."
tar -xvzf ./${DRUPAL}.tar.gz
echo "Extraction done."

#// Port custom .htaccess content over
echo "Porting custom .htaccess content over ..."
BYTE_OFFSET=$(expr `grep -b "Apache/PHP/Drupal settings:" ./html/.htaccess | awk -F':' '{print $1}'` - 2)
head -c $BYTE_OFFSET ./html/.htaccess | cat - ./${DRUPAL}/.htaccess > ./${DRUPAL}/.htaccess.new
mv ./${DRUPAL}/.htaccess.new ./${DRUPAL}/.htaccess
echo "Porting custom .htaccess complete."

#// Set the permissions
echo "Setting permissions for ${USER}:${GROUP} ..."
chown -R ${USER}:${GROUP} ./$DRUPAL
chown $APACHE_USER ./$DRUPAL/.htaccess
find ./$DRUPAL -type d -exec chmod 755 {} \;
find ./$DRUPAL -type f -exec chmod 644 {} \;
echo "Setting permissions done."

#// Link the sites
echo "Linking the ./${DRUPAL}/sites folder ..."
mv ./${DRUPAL}/sites ./${DRUPAL}/sites_orig
ln -s ../drupal_sites ./${DRUPAL}/sites
echo "Linking sites done."

#// Link the site_files
echo "Linking ./${DRUPAL}/site_files ..."
ln -s ../site_files ./${DRUPAL}/site_files
echo "Linking site_files done."

#// Update the html link
echo "Updating html link to $DRUPAL ..."
rm -f ./html
ln -s $DRUPAL html
echo "Updating html link done."

#// Clean Up
echo "Removing source file ..."
rm -f ./$DRUPAL.tar.gz
echo "Removing source file done."

#// Echo futher instructions
echo "Run the update.php script for each site."

exit 0

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

running the update.php script from a cli or shell script

Hi,

great script. I have used some of your ideas (DB array, download Drupal 5.x) in my script. I also have a script to update Drupal, and another one to update modules. My script also backs up the entire website into a tar.gz file. It also makes a copy of the .htaccess, robots.txt and settings.php files.

Have you figured out a method of running update.php from a script?

You can see further info here: http://drupal.org/node/299039 and here: http://drupal.org/node/299199

Thanks.

Cheers,

Paul

Use Selenium or BadBoy to replay update

I haven't figured that out yet. Yes, it is a big pain to be doing manual updates specially if you have several sites running with the same code.

I would look into using something like "Selenium" or "BadBoy" to be able to replay the update.

Updated code with checks...

Updated to 5.7 successfully with the below code:

#!/bin/bash
# update_drupal.sh

USAGE="Usage: $0 <version>"

VERSION=${1?$USAGE}
DOWNLOAD_URL=http://ftp.drupal.org/files/projects/
DRUPAL=drupal-${VERSION}

DB=("<db1>" "<db2>")
DB_USER=<user>
DB_PASS=<pass>
DB_BAK_PATH=./bak/db/

DATE_TODAY=`date +%Y%m%d`

USER=<user>
GROUP=<group>
APACHE_USER=apache

function check_error()
{
        if (( e = $? )); then
                echo "ERROR: $e, $1 Exiting..."
                exit $e
        else
                echo $2
        fi
}


#// Make a backup of database
for ((i=0; i<${#DB[@]}; i++))
do
  echo "Creating backup of database ${DB[$i]} ..."
  mysqldump --opt -u $DB_USER --password=${DB_PASS} ${DB[$i]} > ${DB_BAK_PATH}${DB[$i]}_${DATE_TODAY}.sql
  check_error "${DB[$i]} failed to backup." "${DB[$i]} successfully backed up."
done

#// Download source
echo "Downloading source ${DOWNLOAD_URL}${DRUPAL}.tar.gz ..."
wget ${DOWNLOAD_URL}${DRUPAL}.tar.gz
check_error "Download source failed." "Download source done."

#// Extract source
echo "Extracting ./${DRUPAL}.tar.gz ..."
tar -xzf ./${DRUPAL}.tar.gz
check_error "Source extraction failed." "Source extraction done."

#// Port custom .htaccess content over
echo "Porting custom .htaccess content over ..."
BYTE_OFFSET=$(expr `grep -b "Apache/PHP/Drupal settings:" ./html/.htaccess | awk -F':' '{print $1}'` - 2)
head -c $BYTE_OFFSET ./html/.htaccess | cat - ./${DRUPAL}/.htaccess > ./${DRUPAL}/.htaccess.new &&
mv ./${DRUPAL}/.htaccess.new ./${DRUPAL}/.htaccess
check_error ".htaccess porting failed." "Porting custom .htaccess complete."

#// Set the permissions
echo "Setting permissions for ${USER}:${GROUP} ..."
chown -R ${USER}:${GROUP} ./$DRUPAL &&
chown $APACHE_USER ./$DRUPAL/.htaccess &&
find ./$DRUPAL -type d -exec chmod 755 {} \; &&
find ./$DRUPAL -type f -exec chmod 644 {} \;
check_error "Setting permissions failed." "Setting permissions done."

#// Link the sites
echo "Linking the ./${DRUPAL}/sites folder ..."
mv ./${DRUPAL}/sites ./${DRUPAL}/sites_orig && ln -s ../drupal_sites ./${DRUPAL}/sites
check_error "Linking sites failed." "Linking sites done."

#// Link the site_files
echo "Linking ./${DRUPAL}/site_files ..."
ln -s ../site_files ./${DRUPAL}/site_files
check_error "Linking site_files failed." "Linking site_files done."

#// Update the html link
echo "Updating html link to $DRUPAL ..."
rm -f ./html && ln -s $DRUPAL html
check_error "Linking html failed." "Updating html link done."

#// Clean up the txt files
echo "Cleaning drupal txt files"
find ./html/ -name "*.txt"| grep -v robots.txt| xargs rm -f
check_error "Clean up of txt files failed." "Drupal txt files removed."

#// Clean Up of source
echo "Removing source file ..."
rm -f ./$DRUPAL.tar.gz
check_error "Could not remove source file." "Removing source file done."

#// Echo futher instructions
echo "Run the update.php script for each site."

exit 0
Comment