#!/bin/bash # Written by Peter over at RimuHosting.com (we provide Linux VPS hosting services) # Last major update: 2006-06-18 # for a bit of a blurb about this script see http://bliki.rimuhosting.com/space/knowledgebase/linux/miscapplications/ruby+on+rails # the latest version of this script is typically found at http://downloads.rimuhosting.com/miscproj/rails.sh # todo: # require 'mysql' not working? Try gem install mysql. Then # cp: /usr/local/lib/ruby/gems/1.8/gems/mysql-2.7/mysql.so /usr/local/lib/ruby/site_ruby/1.8/mysql.so # # a function just so we can see on screen what is happening as well as view the install log later on function echolog() { echo $* | tee -a /root/install.log } # download a file and cd into there. With a bit of error handling function download() { local name=$1 local version=$2 local url=$3 mkdir -p /usr/local/src cd /usr/local/src if [ -d /usr/local/src/$name-$version ]; then echolog "$name directory already exists, skipping the download" cd /usr/local/src/$name-$version return 0 fi echolog "Grabbing $name from $url" wget -qO - $url | tar xz if [ $? -ne 0 ]; then echolog "failed getting $url" >&2 return 1 fi cd /usr/local/src/$name-$version } function installrails() { function installprerequisites() { if [ -e /etc/redhat-release ] ; then # Getting errors like: custom_require.rb:21:in `require__': No such file to load -- zlib (LoadError) # Then you need zlib devel _before_ compiling ruby apt-get -y install zlib-devel apt-get -y install readline-devel readline apt-get -y install mysql-devel apt-get -y install ImageMagick-devel ImageMagick else apt-get install -y zlib1g-dev apt-get install -y 'g++-3.4' apt-get install -y libmysqlclient14-dev apt-get -y install libmagick++6-dev libmagick++6 apt-get -y install libreadline5-dev fi if [ -e /etc/issue ] && grep -qai 'Ubuntu 6' /etc/issue ; then # note ubuntu comes with 1.8.4 so no ruby compile needs to be done # else you will get gem spitting out extconf.rb:1:in `require': no such file to load -- mkmf (LoadError) apt-get -y install ruby1.8-dev apt-get -y install libmagick9 libmagick9-dev # /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:21:in `require__': no such file to load -- rdoc/rdoc (LoadError) apt-get -y install rdoc1.8 apt-get -y install make apt-get -y install libmagick9-dev libmagick9 fi if [ -e /usr/bin/irb1.8 -a ! -e /usr/bin/irb ] ; then ln -sf /usr/bin/irb1.8 /usr/bin/irb fi # else ./configure may fail with the script not finding cpp or a c++ compiler if [ ! -e /usr/bin/g++ -a -e /usr/bin/gcc-3.4 ]; then ln -sf /usr/bin/gcc-3.4 /usr/bin/gcc; ln -sf /usr/bin/g++-3.4 /usr/bin/g++ fi } installprerequisites if [ $? -ne 0 ]; then echolog "failed prerequisites" >&2; return 1; fi # debian is -dev, rh is -devel function installruby() { echolog "checking ruby is latest version" # try to scrape the version off the ruby home page VERSION=$(wget -qO - http://www.ruby-lang.org/en/20020102.html| grep "The stable release" | sed 's/.*tar.gz">ruby-//g' | sed 's/<\/a>.*//g') # correct as at 2006-06-18 if [ -z "$VERSION" -o $? -ne 0 ]; then VERSION=1.8.4 fi # check if we have ruby 1.8 already and then exit if [ -e /usr/bin/ruby ] && /usr/bin/ruby --version | grep -qai $VERSION ; then echolog "/usr/bin/ruby already version $VERSION, skipping install" return 0 elif [ -e /usr/bin/ruby ]; then # if we have an old version of ruby then move it out of the way and clear out the devel libraries so they do not conflict mv /usr/bin/ruby /usr/bin/ruby.not$VERSION if [ -e /etc/redhat-release ] ; then apt-get -y remove ruby apt-get -y remove ruby-devel else apt-get -y remove ruby fi fi if [ -e /usr/local/bin/ruby ] && /usr/local/bin/ruby --version | grep -qai $VERSION ; then echolog "/usr/local/bin/ruby already version $VERSION, skipping install" return 0 fi echolog Installing Ruby VERSION=$VERSION download ruby $VERSION ftp://ftp.ruby-lang.org/pub/ruby/ruby-$VERSION.tar.gz if [ $? -ne 0 ]; then echolog "failed downloading ruby" >&2; return 1; fi ./configure && make && make test && make install if [ $? -ne 0 ]; then echolog "Ruby make install failed">&2 return 1 fi # so there'll be a /usr/bin/ruby to use if [ -e /usr/local/bin/ruby -a ! -e /usr/bin/ruby ]; then ln -sf /usr/local/bin/ruby /usr/bin/ruby fi # doing this voodo to prevent errors like: # /usr/local/lib/ruby/1.8/irb/completion.rb:10:in `require’: no such file to load—readline (LoadError) cd /usr/local/src/ruby-$VERSION/ext/readline if [ $? -ne 0 ]; then echolog "no /usr/local/src/ruby-$VERSION/ext/readline dir">&2;return 1;fi ruby extconf.rb if [ $? -ne 0 ]; then echolog "readline extconf.rb failed">&2;return 1;fi make clean && make install if [ $? -ne 0 ]; then echolog "readline make failed">&2;return 1;fi if ! ruby --version | grep -qai $VERSION ; then echolog "$(which ruby) version is not as expected. Expected $VERSION, got: $(ruby --version)" >&2 return 1 fi } installruby if [ $? -ne 0 ]; then echolog "failed installing ruby" >&2; return 1; fi # gems is an app kind of like apt or up2date or yum which lets you gem install modulename for ruby function installgems() { ########################################### # the rubyforge download pages confound my screen # scraping ability to get the latest version. so you # will need to manually check this if you want the # latest version gemsversion=0.8.11 echolog "installing rubygems" download rubygems $gemsversion http://rubyforge.org/frs/download.php/5207/rubygems-$gemsversion.tgz || return 1 if [ -e builtok ] ; then echolog "ruby gems already installed, skipping"; return 0; fi ruby setup.rb if [ $? -ne 0 ]; then echolog "gems setup failed">&2 return 1 fi touch builtok } installgems if [ $? -ne 0 ]; then echolog "failed installing gems" >&2; return 1; fi # this function installs commonly requested 'gems' function installgems() { ########################################### echolog "installing gems rails fcgi" gem install -y rails if [ $? -ne 0 ]; then echolog "rails gem install failed">&2 return 1 fi if [ ! -e /usr/local/bin/mongrel_rails ]; then echo "If prompted select the latest mongrelversion. Typically item 1 on the list. Do not choose the mswin ones." gem install -y mongrel if [ $? -ne 0 ]; then echolog "mongrelgem install failed">&2 return 1 fi fi if ! echo "require 'rubygems'; require_gem 'mysql'" | irb | grep -qai true; then echo "You probably want to choose the 'mysql 2.7 (ruby)' option. Don't choose the mswin options." gem install -y mysql if [ $? -ne 0 ]; then if [ -e /usr/local/lib/ruby/gems/1.8/gems/mysql-2.7/extconf.rb ]; then cd /usr/local/lib/ruby/gems/1.8/gems/mysql-2.7 # the regular gem install mysql should work, but if not then you may need to fall back on this ruby extconf.rb --with-mysql-config if [ $? -ne 0 ]; then echolog "mysql gem install failed (0) ">&2; return 1; fi make install if [ $? -ne 0 ]; then echolog "mysql gem install failed (1) ">&2; return 1; fi else echolog "mysql gem install failed">&2 return 1 fi fi fi # using irb (interactive ruby) we can check that the module we thought was installed is actually there if ! echo "require 'rubygems'; require_gem 'mysql'" | irb | grep -qai true; then echolog "myql gem install failed" fi if ! echo "require 'rubygems';require_gem 'rmagick'" | irb | grep -qai true; then gem install rmagick if [ $? -ne 0 ]; then echolog "rmagick gem install failed">&2 return 1 fi fi } installgems if [ $? -ne 0 ]; then echolog "failed installing gems" >&2; return 1; fi # the setup for fastcgi for rhel4 and debian is different enough that we'll just use different functions for each function debianfastcgi() { function debinstallpcre() { echolog "installing pcre" pcreversion=5.0 download pcre $pcreversion ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-$pcreversion.tar.gz if [ $? -ne 0 ]; then echolog "pcre download failed" >&2; return 1; fi if [ -e builtok ]; then echolog "Looks like we'd already built it, skipping this step" return 0 fi ./configure && make && make test && make install if [ $? -ne 0 ]; then echolog "pcre install failed" >&2; return 1; fi touch builtok } debinstallpcre if [ $? -ne 0 ]; then echolog "debinstallpcre failed" >&2; return 1; fi function debinstallfcgi() { echolog "installing fcgi" fcgiversion=2.4.0 download fcgi $fcgiversion http://www.fastcgi.com/dist/fcgi-$fcgiversion.tar.gz || return 1 if [ $? -ne 0 ]; then echolog "download fcgi failed" >&2; return 1; fi if [ -e builtok ]; then echolog "Looks like we'd already built fcgi, skipping this step" return 0 fi ./configure && make && make install if [ $? -ne 0 ]; then echolog "fcgi compile" >&2; return 1; fi cd /etc/apache2/mods-enabled ln -s ../mods-available/fcgid.* . ln -s ../mods-available/rewrite.* . touch builtok } debinstallfcgi if [ $? -ne 0 ]; then echolog "debinstallfcgi failed" >&2; return 1; fi function debinstallrubyfcgi() { echolog "installing ruby fcgi" echolog "require 'fcgi'"| irb | grep -q true if [ $? -eq 0 ]; then echolog "rubyfcgi already working, skipping this step" >&2; return 0; fi rubyfcgiversion=0.8.6 download ruby-fcgi $rubyfcgiversion http://sugi.nemui.org/pub/ruby/fcgi/ruby-fcgi-$rubyfcgiversion.tar.gz if [ $? -ne 0 ]; then echolog "installrubyfcgi download failed" >&2; return 1; fi ruby install.rb config if [ $? -ne 0 ]; then echolog "installrubyfcgi install config failed" >&2; return 1; fi ruby install.rb setup ruby install.rb install if [ $? -ne 0 ]; then echolog "installrubyfcgi install failed" >&2; return 1; fi echolog "require 'fcgi'"| irb | grep -q true if [ $? -ne 0 ]; then echolog "installrubyfcgi require fcgi failed" >&2; return 1; fi } debinstallrubyfcgi if [ $? -ne 0 ]; then echolog "debinstallrubyfcgi failed" >&2; return 1; fi } function redhatfastcgi() { function installfcgi() { fcgiversion=2.4.0 echolog "installing fcgi" download fcgi $fcgiversion http://www.fastcgi.com/dist/fcgi-$fcgiversion.tar.gz || return 1 if [ -e builtok ] ; then echolog "fcgi already installed, skipping"; return 0; fi ./configure && make && make install if [ $? -ne 0 ]; then echolog "fgci compile failed">&2 return 1 fi touch builtok } installfcgi if [ $? -ne 0 ]; then echolog "failed installing fcgi" >&2; return 1; fi function installmodfastcgi() { if [ -e /etc/debian_version ]; then echolog "Skipping fcgi for Debian" return 0 fi ########################################### modfastcgiversion=2.4.2 echolog "installing mod_fcgi" download mod_fastcgi $modfastcgiversion http://www.fastcgi.com/dist/mod_fastcgi-$modfastcgiversion.tar.gz || return 1 if [ -e builtok ] ; then echolog "ruby gems already installed, skipping"; return 0; fi /bin/cp -f Makefile.AP2 Makefile if [ -e /etc/debian_version ]; then apt-get -y install apache2-threaded-dev make top_dir=/etc/apache2 && make top_dir=/etc/apache2 install elif [ ! -e /etc/redhat-release ]; then echolog "Don't recognise this distro. Can't build mod_fastcgi" >&2 return 1 else apt-get -y install httpd-devel make top_dir=/etc/httpd && make top_dir=/etc/httpd install fi if [ $? -ne 0 ]; then echolog "mod_fastcgi install failed" >&2 return 1 fi if ! grep -qai fastcgi /etc/httpd/conf/httpd ; then echo 'LoadModule fastcgi_module modules/mod_fastcgi.so FastCgiConfig -minProcesses 1 -maxProcesses 2 -processSlack 1 AddHandler fastcgi-script .fcgi # to avoid Permission denied: FastCGI: failed to connect to (dynamic) server FastCgiIpcDir /tmp ' >> /etc/httpd/conf/httpd.conf mkdir -p /tmp/dynamic chmod o+rwx /tmp/dynamic fi /etc/init.d/httpd restart if [ $? -ne 0 ]; then echolog "failed restarting httpd" >&2; return 1; fi touch builtok } installmodfastcgi if [ $? -ne 0 ]; then echolog "failed installing mod_fastcgi" >&2; return 1; fi function installfcgigem() { gem install -y fcgi if [ $? -ne 0 ]; then echolog "fcgi gem install failed">&2 return 1 fi # not sure why the .rb and .so are not put where ruby can find them, do it manually if [ ! -e /usr/local/lib/ruby/1.8/fcgi.so ]; then if [ ! -e /usr/local/lib/ruby/gems/1.8/gems/fcgi-0.8.6.1/fcgi.so ] ; then echolog "could not find /usr/local/lib/ruby/gems/1.8/gems/fcgi-0.8.6.1/fcgi.so" return 1 fi /bin/cp -f /usr/local/lib/ruby/gems/1.8/gems/fcgi-0.8.6.1/fcgi.so /usr/local/lib/ruby/gems/1.8/gems/fcgi-0.8.6.1/fcgi.rb /usr/local/lib/ruby/1.8/ fi } installfcgigem if [ $? -ne 0 ]; then echolog "failed installing fcgi gem" >&2; return 1; fi } if [ -e /etc/debian_version ]; then debianfastcgi if [ $? -ne 0 ]; then echolog "fcgi setup failed" >&2; return 1; fi else redhatfastcgi if [ $? -ne 0 ]; then echolog "fcgi setup failed" >&2; return 1; fi fi # lighttpd is a standalone web server often used/requested by the rails community function installlighthttpd() { echolog "installing lighttpd" lighttpd 2>&1| grep -q "No configura" if [ $? -eq 0 ]; then echolog "looks like it is already working" >&2; return 0; fi version=1.4.11 download lighttpd $version http://www.lighttpd.net/download/lighttpd-$version.tar.gz if [ $? -ne 0 ]; then echolog "download lighttpd failed" >&2; return 1; fi ./configure && make && make install if [ $? -ne 0 ]; then echolog "download compile failed" >&2; return 1; fi lighttpd 2>&1| grep -q "No configura" if [ $? -ne 0 ]; then echolog "lighttpd startup failed" >&2; return 1; fi } installlighthttpd if [ $? -ne 0 ]; then echolog "lighttpd install failed" >&2; return 1; fi # create a test project so we can have something to display function createtestrailsproj() { echolog "creating a test rails project in /var/www/test" cd /var/www rails test if [ $? -ne 0 ]; then echolog "failed doing rails test" >&2; return 1; fi #railsdir=$(find /usr/lib/ruby/gems/1.8 -type d | grep rails | head -n 1) #if [ -z "$railsdir" ]; then echolog "could not find the rails dir under /usr/lib/ruby/gems/1.8" >&2; return 1; fi #echo railsdir=$railsdir #replace "server.port = 3000" "server.port = 80" -- $railsdir/configs/lighttpd.conf #if [ $? -ne 0 ]; then echolog "expected rails config setting not found" >&2; return 1; fi cd /var/www/test echolog "press ctrl-c after this has started up" ruby script/server } createtestrailsproj if [ $? -ne 0 ]; then echolog "createtestrailsproj failed" >&2; return 1; fi function testapachefcgi() { echolog "Testing that apache works with fastcgi" ########################################### # create a 'hello world' fcgi test if [ -e /etc/debian_version ]; then CGIBINDIR=/usr/lib/cgi-bin /etc/init.d/apache2 restart else CGIBINDIR=/var/www/cgi-bin /etc/init.d/httpd restart fi if [ ! -e $CGIBINDIR/test.fcgi ] ; then echo "#"'!'"/usr/bin/ruby require 'cgi' require 'fcgi' FCGI.each_cgi{|cgi| cgi.out{'<HTML>hello, world.</HTML>'}} " > $CGIBINDIR/test.fcgi chmod +x $CGIBINDIR/test.fcgi fi sleep 3 # grab the server IP ip=$(ifconfig | grep --after-context=1 "eth0 " | grep inet | cut -d: -f2 | cut -f1 -d' ') if wget -O - http://$ip/cgi-bin/test.fcgi 2>/dev/null| grep -qai hello ; then echolog "Looks like http://$ip/cgi-bin/test.fcgi is loading"; else echolog "apache fcgi page http://$ip/cgi-bin/test.fcgi does not appear to load corectly" >&2 return 1 fi } testapachefcgi if [ $? -ne 0 ]; then echolog "test apache cgi failed" >&2; return 1; fi # automatically tests that lighttpd is working ok. Sets itself up on port 3000 function testlighttpd() { echolog "setting up an /etc/init.d/lighttpd script that will start up lighttpd pointing at the project in /var/www/test" echo '#!/bin/bash # # chkconfig: 345 94 16 # description: Startup script for Lighttpd BASEDIR=/var/www/test case "$1" in start) echo "starting up lighttpd in $BASEDIR" cd $BASEDIR ./script/server -d lighttpd 2>&1 >> /var/log/messages & ;; stop) echo "stopping lighttpd" pid="$(pidof lighttpd) $(ps auxf | grep $BASEDIR | awk '"'"'{print $2}'"'"')" if [ -z "$pid" ]; then echo "lighttpd not running"; else kill -9 $pid fi ;; restart) stop sleep 3 start ;; esac ' > /etc/init.d/lighttpd chmod +x /etc/init.d/lighttpd #if [ -e /etc/debian_version ]; then #update-rc.d rails start 99 3 . #else #chkconfig --level 35 lighttpd on #fi /etc/init.d/lighttpd start ip=$(ifconfig | grep --after-context=1 "eth0 " | grep inet | cut -d: -f2 | cut -f1 -d' ') sleep 5 wget -O - http://$ip:3000 2>&1 | grep -q "Welcome ab" if [ $? -ne 0 ]; then echolog "Test load of http://$ip:3000 indicates rails or lighttpd is not working. failed." >&2; return 1; else echolog "Test load of http://$ip:3000 indicates rails andlighttpd is working ok" >&2; fi /etc/init.d/lighttpd stop echolog "To check lighttpd, run /etc/init.d/ligttpd start then go to http://$ip:3000/ check it works" } testlighttpd if [ $? -ne 0 ]; then echolog "testlighttpd failed" >&2; return 1; fi # automatically tests that mongrel is working ok. Sets itself up on port 3000 function testmongrel() { echolog "setting up an /etc/init.d/mongrel script that will start up lighttpd pointing at the project in /var/www/test" echo '#!/bin/bash # # chkconfig: 345 94 16 # description: Startup script for mongrel BASEDIR=/var/www/test case "$1" in start) echo "starting up mongrel in $BASEDIR" cd $BASEDIR mongrel_rails start -d 2>&1 >> /var/log/messages & ;; stop) echo "stopping mongrel" cd $BASEDIR mongrel_rails stop ;; restart) stop sleep 3 start ;; esac ' > /etc/init.d/mongrel chmod +x /etc/init.d/mongrel #if [ -e /etc/debian_version ]; then #update-rc.d rails start 99 3 . #else #chkconfig --level 35 lighttpd on #fi /etc/init.d/mongrel start ip=$(ifconfig | grep --after-context=1 "eth0 " | grep inet | cut -d: -f2 | cut -f1 -d' ') sleep 5 wget -O - http://$ip:3000 2>&1 | grep -q "Welcome ab" if [ $? -ne 0 ]; then echolog "Test load of http://$ip:3000 indicates rails or mongrel is not working. failed." >&2; return 1; fi echolog "Looks like http://$ip:3000 is loading OK with Mongrel" >&2; echolog "To check mongrel, run /etc/init.d/mongrel start then go to http://$ip:3000/ and check it works" /etc/init.d/mongrel stop } testmongrel echolog "All Done!" } installrails