Shell Script to Upgrade Ruby Enterprise Edition while Maintaining Directory Naming Sanity

As you're likely already aware, a denial of service (DoS) vulnerability in Ruby's BigDecimal library was uncovered, fixed and reported on June 9, 2009. Patching options include:

The latter approach only postpones the inevitable, so I opted for the former. If you're using the debian packages, it's a simple call to aptitude update. However, if you've installed from source, this presents a few challenges.

The upgrade is actually quite straightforward. According to the REE Documentation, you simply need to run the new installer over top of your previous installation. This includes specifying the exact same directory name that you used to install the previous version.

As you may know, REE installs by default into /opt/ruby-enterprise-1.8.6-\. However, after completing this, you're left with a directory name that doesn't reflect what's actually installed in there. If you've a little neurotic like I am, you're going to want to rename that directory. However, be careful. Your Passenger configuration is likely pointing to the directory that you want to rename, so you'll have to remember to update your apache/nginx configuration to reflect this.

When we install REE we create a symlink at /opt/ruby which points to the version of ruby that we want passenger to run. This allows us to quickly swap in/out different versions of ruby for testing/upgrading/etc.

Considering we have dozens of client applications running on distinct servers each with their own versions of REE installed, I decided to write a script to minimize the manual effort required to upgrade several production servers.

#!/bin/sh
# Author: John Trupiano
# Script to upgrade an REE installation on a hot server and maintain sane directory names

if ["$(whoami)" != "root"]; then  
  echo "You need to be root to run this!"
  exit 2
fi

RF_RELEASE=58677  
REE_VERSION=20090610  
REE=ruby-enterprise-1.8.6-$REE_VERSION  
URL=http://rubyforge.org/frs/download.php/$RF_RELEASE/$REE.tar.gz

# Determine what the most recent version of REE is that is installed
MOST_RECENT_REE_VERSION=`ls /opt | awk -F"-" '$4 > max && $2 == "enterprise" { max=$4; maxline=$0 }; END { print max }'`  
MOST_RECENT_REE=ruby-enterprise-1.8.6-$MOST_RECENT_REE_VERSION

WORKING_DIR=/root/src

echo "Going to update $MOST_RECENT_REE to $REE"

echo "Back up previous release"  
cp -R /opt/$MOST_RECENT_REE /opt/$MOST_RECENT_REE.bak

echo "Download new release"  
mkdir -p $WORKING_DIR  
cd $WORKING_DIR && wget $URL

echo "Untar and install over the previous release for 'upgrade' according to REE manual"  
tar xzf $REE.tar.gz  
./$REE/installer --auto /opt/$MOST_RECENT_REE

echo "Shuffle folder names to remain sane"  
mv /opt/$MOST_RECENT_REE /opt/$REE && mv /opt/$MOST_RECENT_REE.bak /opt/$MOST_RECENT_REE

echo "Actually symlink in the new version of REE"  
rm /opt/ruby && ln -s /opt/$REE /opt/ruby

echo "Clean up after ourselves"  
rm -f $WORKING_DIR/$REE  

Simply upload this script to your server, su - up to root and run it. Then restart apache/nginx so that passenger will pick up the new version of ruby. All of your gems will be maintained, and your most recent version of REE will remain in tact at /opt/ruby-enterprise-1.8.6-\ in case you need it again.

View the script on github

comments powered by Disqus