15 Aug 2007
I wanted to be able to examine my development log for rails deprecation warnings, and came up with this handy one-liner:
grep “^DEPRECATION WARNING:” development.log | awk ‘{print $3, $4, $5, “:”, $NF}’ | sort | uniq
This gives me output something like this:
@params is deprecated! : script/../config/../app/views/waiting_messages/prepare_reply.rhtml:9)
@request is deprecated! : ./script/../config/../app/controllers/account_controller.rb:10)
You called render(‘new_member_in_program’), : /opt/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/li […]
end_form_tag is deprecated : script/../config/../app/views/members/bulknew.rhtml:10)
find_all is deprecated : (irb):3)
start_form_tag is deprecated : script/../config/../app/views/members/bulknew.rhtml:2)
It’s not perfect; I’m missing some useful info from some of the lines (such as the ‘You called render…’) that I’ll have to go back and pick over. But in broad strokes, it gives me a fairly concise list of some things that need to be cleaned up.
However, that one-liner is fairly meaty. Who wants to remember that, or make an alias for it, or need to look it up? Yuck.
How about a rake task? I’ve never written one before, but everyone’s always raving about how simple it is, so I figured I’d go ahead. Hopefully this helps show how simple it is. While I’m at it, I’ll go ahead and include the full text of the warning (except for the redundant “
DEPRECATION WARNING” at the beginning, since we already know we’re looking for that) instead of truncating it like I did in my awk-based one-liner.
Here it is:
namespace :utils do
desc "List deprecation warnings in development log"
task :find_deprecated do
File.open('log/development.log') do |file|
lines = file.select {|line| line =~ /^DEPRECATION WARNING:/}
lines.sort.uniq.each {|line| puts line.split('DEPRECATION WARNING: ')[1]}
end
end
end
Put that in a file called
utils.rake
inside your
lib/tasks
directory, and call it by typing
rake utils:find_deprecated
, and you’ll get something like this (lines chomped for presentation purposes):
@params is deprecated! Call params.[] instead of @params.[]. Args: [:response_text] See http://www. [...]
@request is deprecated! Call request.accepts instead of @request.accepts. Args: [] See http://www.r [...]
You called render('new_member_in_program'), which is a deprecated API call. Instead you use render : [...]
end_form_tag is deprecated and will be removed from Rails 2.0 See http://www.rubyonrails.org/deprec [...]
find_all is deprecated and will be removed from Rails 2.0 (use find(:all, ...)) See http://www.ruby [...]
start_form_tag is deprecated and will be removed from Rails 2.0 (use form_tag instead) See http://w [...]
There are certainly improvements that could be made, such as adding the ability to search test.log and production.log as well, but this’ll do for now.
Read on →
02 May 2007
Many of you have heard of web application deployment using the LAMP set of technologies that came into vogue a few years ago. Later, MARS was thrown about as a four-letter acronym to describe a Rails-centric deployment scheme, but some of the choices (Solaris? Apache? Please.) leave me cold.
So, without further ado, let me introduce you to RUMP:
- Rails
- Ubuntu
- Mongrel
- Postgresql
Why these choices? Well, Rails goes without saying (if you aren’t interested in Rails, then RUMP is not for you); Ubuntu because it offers a lightweight server config with a package system that is even better than Debian’s; Mongrel because it’s currently the best web server targetted at Ruby application deployment and is getting better all the time; and Postgresql because MySQL, despite all the good it’s done for the world, still falls behind on a number of features.
To help get you started, what follows is a reasonably accurate description of what I went through to get my RUMP in gear. I had occasion to do this a couple times within a few days a little while ago, and kept some reasonably complete notes as I went along. Hopefully this will help others experience the satisfaction of a nice, fit RUMP.
Wherever possible, I’ve tried to find the simplest configuration that works. Of course each component can be installed and configured in a variety of ways, and YMMV. For what it’s worth, the following is what seems to be working well for me.
Installation notes for RUMP deployment server (running ubuntu 6.10 “edgy eft”)
I started off with an empty image installed by my hosting company of choice. This was a bare-bones Ubuntu server install, containing a single root account with ssh enabled, and pretty much nothing else.
First, log in to your new system and use adduser
to create a user named “deploy” with homedir /home/deploy
, and then run visudo
to let the “deploy” user run commands with sudo
. Then log in as “deploy” and do the rest of this.
Start off with editing /etc/apt/sources.list
to enable some packages:
deb http://se.archive.ubuntu.com/ubuntu/ edgy main restricted
deb-src http://se.archive.ubuntu.com/ubuntu/ edgy main restricted
## Major bug fix updates produced after the final release of the
## distribution.
deb http://se.archive.ubuntu.com/ubuntu/ edgy-updates main restricted
deb-src http://se.archive.ubuntu.com/ubuntu/ edgy-updates main restricted
## Uncomment the following two lines to add software from the 'universe'
## repository.
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## universe WILL NOT receive any review or updates from the Ubuntu security
## team.
deb http://se.archive.ubuntu.com/ubuntu/ edgy universe
# deb-src http://se.archive.ubuntu.com/ubuntu/ edgy universe
## Uncomment the following two lines to add software from the 'backports'
## repository.
## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
deb http://se.archive.ubuntu.com/ubuntu/ edgy-backports main restricted universe multiverse
# deb-src http://se.archive.ubuntu.com/ubuntu/ edgy-backports main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu edgy-security main restricted
deb-src http://security.ubuntu.com/ubuntu edgy-security main restricted
# deb http://security.ubuntu.com/ubuntu edgy-security universe
# deb-src http://security.ubuntu.com/ubuntu edgy-security universe
After that, run sudo apt-get update
to get the latest package definitions, and then start installing:
Some common tools you will surely need at some point:
sudo apt-get install man curl wget
and some dev tools for later compilation steps
sudo aptitude install build-essential
Time for ruby:
sudo apt-get install ruby ri rdoc irb ri1.8 ruby1.8-dev libzlib-ruby zlib1g
and then postgres:
sudo apt-get install postgresql-8.2
sudo apt-get install postgres82-dev
Now we’ll configure postgres for our purposes. Creating a role with the same name as the user we’re running with makes everything a little easier:
sudo -u postgres createdb NAME_OF_YOUR_APP_HERE_production
sudo -u postgres createuser -P
Enter name of role to add: deploy
Enter password for new role:
Enter it again:
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) y
Shall the new role be allowed to create more new roles? (y/n) n
after that you should be able to do execute psql NAME_OF_YOUR_APP_HERE_production
as the deploy user and get right in.
One piece of the puzzle that didn’t quite make it into the RUMP moniker is pound, a handy reverse-DNS and load-balancer that fronts for our multiple mongrels. Install it thusly:
sudo apt-get install pound
sudo vi /etc/default/pound
setting startup=1 in there, and then:
sudo vi /etc/pound/pound.cfg
making it something like this:
## Minimal sample pound.cfg
##
## see pound(8) for details
######################################################################
## global options:
User "www-data"
Group "www-data"
#RootJail /chroot/pound
## allow PUT and DELETE also (by default only GET, POST and HEAD)?:
#ExtendedHTTP 0
#WebDAV 0
## Logging: (goes to syslog by default)
## 0 no logging
## 1 normal
## 2 extended
## 3 Apache-style (common log format)
LogLevel 1
## check backend every X secs:
Alive 30
## use hardware-accelleration card supported by openssl(1):
#SSLEngine <hw>
######################################################################
## listen, redirect and ... to:
## redirect all requests on port 8888 ("ListenHTTP") to the local webserver see "UrlGroup" below):
#ListenHTTP 127.0.0.1,8080
##
#UrlGroup ".*"
#BackEnd 127.0.0.1,80,1
#EndGroup
ListenHTTP
Address 0.0.0.0
Port 80
Service
BackEnd
Address 127.0.0.1
Port 8000
End
BackEnd
Address 127.0.0.1
Port 8001
End
BackEnd
Address 127.0.0.1
Port 8002
End
Session
Type COOKIE
TTL 900
ID "_myappname_session_id"
End
End
End
That sets us up with pound listening on port 80, transferring the request to one of our three mongrel instances (see Mongrel section). Note the Session
section, which may help keep things sorted out for some Rails session schemes.
Now start pound, like this:
sudo /etc/init.d/pound start
Try to connect to the site with a browser. you should get a 503 error, and something like this in /var/log/syslog:
Mar 15 23:51:31 ubuntu pound: backend 127.0.0.1:8000 connect: Connection refused
Mar 15 23:51:31 ubuntu pound: backend 127.0.0.1:8001 connect: Connection refused
Mar 15 23:51:31 ubuntu pound: backend 127.0.0.1:8002 connect: Connection refused
Mar 15 23:51:31 ubuntu pound: no back-end “GET / HTTP/1.1” from 123.123.123.123
Mar 15 23:51:31 ubuntu pound: no back-end “GET /favicon.ico HTTP/1.1” from 123.123.123.123
If you want to run subversion on this server, here’s how to do it. If you are running subversion elsewhere and don’t want to move it, skip this section.
sudo apt-get install subversion xinetd
Create a user that will own the repositories:
sudo adduser —system —no-create-home —home /var/svn —group —disabled-login svn
Create the directory that will hold the repositories:
sudo mkdir /var/svn
sudo chown svn:svn /var/svn
Create file /etc/xinetd.d/svnserve
with the following content, to autolaunch svn when it’s called upon:
service svn
{
port = 3690
socket_type = stream
protocol = tcp
wait = no
user = svn
server = /usr/bin/svnserve
server_args = -i -r /var/svn
}
Restart xinetd so that svn will work
sudo /etc/init.d/xinetd restart
Create a test repository:
sudo -u svn svnadmin create /var/svn/testrepo
It should be possible to check out the repository and work on it:
svn co svn://localhost/testrepo
Assuming that worked, create the real repository for your project:
sudo -u svn svnadmin create /var/svn/myproject
Add a little security:
cd /var/svn/myproject/conf
sudo vi svnserve.conf
Set up like this:
anon-access = none
auth-access = write
password-db = passwd
Create users for your remote username(s), and the local deploy user. This simplifies login for everyone, and makes it easier to spot changes that were committed from the production server! sudo vi passwd
, making it look about like this:
# create a user/pw or two
joe_user = superseekrit
deploy = soopersecret
Now try to check out, it should demand a valid username/password:
svn co svn://localhost/myproject
Assuming you have an existing repository you’d like to bring over, go to the old server and do this:
svnadmin dump /path/to/repos > my_repos.dump
gzip my_repos.dump
scp my_repos.dump.gz deploy@my_ubuntu_host:/home/deploy
Then, on the new machine:
cd /home/deploy
gunzip my_repos.dump.gz
cd /var/svn
sudo -u svn svnadmin load myproject < /home/deploy/my_repos.dump
Then make sure you can check it out:
cd /home/deploy
# delete the myproject directory if it's there, then:
svn co svn://localhost/myproject
Finally it’s time to install rails etc. I’ve installed them with rubygems:
curl -O http://rubyforge.org/frs/download.php/17190/rubygems-0.9.2.tgz
tar xzf rubygems-0.9.2.tgz ; cd rubygems-0.9.2
sudo ruby setup.rb
sudo gem update
sudo gem install rails --include-dependencies
sudo gem install postgres-pr
sudo gem install mongrel
(ignore warnings about not being able to compile fastthread stuff, it’s optional)
sudo gem install mongrel_cluster
If you’re using BackgroundRb, you’ll want these:
sudo gem install slave
sudo gem install daemons
Very soon we’ll have our app up and running. Create the database schema:
cd ~/myproject
rake db:schema:load
Configure a little mongrel cluster:
cd ~/myproject
mongrel_rails cluster::configure -p 8000 -N 3
As of this writing (May 2007), there’s a small bug that will bite you if you’re using both postgres and BackgroundRb. This is fixed in edge rails, but not yet in the released version. If you fall into this category, patch this file, as shown in <a href="http://dev.rubyonrails.org/attachment/ticket/7727/postgres_async_patch.diff">http://dev.rubyonrails.org/attachment/ticket/7727/postgres_async_patch.diff</a>
:
sudo vi /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_record/connection_adapters/postgresql_adapter.rb
Make sure you’re always running in production on this machine by putting the following line into your .bashrc:
export RAILS_ENV=production
If you’re using BackgroundRb, start the background processes:
cd ~/myproject
script/backgroundrb start
Tail log/backgroundrb.log to make sure it looks OK. Something like:
20070316-13:56:35 (12680) Starting WorkerLogger
20070316-13:56:35 (12681) In ResultsWorker
...
At long last, start the mongrel cluster:
cd ~/myproject
mongrel_rails cluster::start
At this point you should be able to smack your RUMP on port 80 and watch it wiggle!
In no particular order, here are some of the sites where I found information to put this all together:
http://wiki.rubyonrails.org/rails/pages/PostgreSQL/
http://happycodr.com/blog/view/13-putting-a-ruby-on-rails-application-into-production
http://mongrel.rubyforge.org/docs/pound.html
http://www.die.net/doc/linux/man/man8/pound.8.html
http://kurup.org/blog/tag/pound
http://ubuntuguide.org/wiki/Ubuntu_Edgy#How_to_install_Subversion_version_control_server_.28svnserve.29
http://blog.tupleshop.com/2006/7/8/deploying-rails-with-pound-in-front-of-mongrel-lighttpd-and-apache
That’s it, I guess. I hope this proves helpful to someone. Feel free to leave feedback in the comments below!
Read on →