$PATH when Using Passenger (mod_rails) aka BJ does work with Rails 4

Posted by Ben Reubenstein Wed, 18 Feb 2009 00:25:00 GMT

Phusion Passenger has become my default Rails setup lately. Today I had issues when using BJ on a production box, and it came down to two issues. The first was Bj not working quite right with Rails Time. The gist of that fix is to change every reference of Time.now to Time.now.utc. The next however was tougher to track down. I was getting error messages in my email:

no bj found in ["RAILS_ROOT/script", "/sbin", "/usr/sbin", "/bin", "/usr/bin"]

I jumped into the console, and ENV["PATH"] reported the correct paths, including /usr/local/bin. It turns out that passenger inherits the $PATH of apache, so I manually set the path in environment.rb and my problem was solved.

ENV['PATH'] = "#{ENV['PATH']}:/usr/local/bin"

RHEL5 Getting The Rails Console Working 2

Posted by Ben Reubenstein Tue, 10 Feb 2009 16:42:00 GMT

If you compile Ruby from scratch you may get this error when starting a script/console session:

`require': no such file to load -- readline (LoadError)

To solve this you need to install the readline ruby extension. Here I assume you are using the 1.8.7 Ruby.

sudo yum install ncurses-devel readline-devel
cd ~
mkdir src
cd src
wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p72.tar.gz
tar zxvf ruby-1.8.7-p72.tar.gz
cd ruby-1.8.7-p72.tar.gz/ext/readline
ruby extconf.rb
make
sudo make install

iPhone Optimized Olypic Medal Totals 16

Posted by Ben Reubenstein Sun, 10 Aug 2008 16:39:00 GMT

After my initial surfing on my iPhone for Olympic medal totals, I found no immediate results for an optimized mobile experience. I wrote up a quick site after which I immediately found NBC's mobile site. Mine is super simple, and can be found at iPhone Olympic Medal Counts. CHEERS.

Web Server Type Determination Ruby Script

Posted by Ben Reubenstein Sat, 05 Apr 2008 13:18:00 GMT

After seeing the Python version, then the shell script version, I decided to write the Ruby version. You could use the class anywhere, but this example is a nice command line script you can call.

#!/usr/bin/env ruby

require 'net/http'

class WebServerInfo
  def self.server_type(host)
    http = Net::HTTP.new(host, 80)
    resp, data = http.get('/', nil)
    resp['server']
  end
end

if ARGV[0].nil?
  puts "usage: which_webserver DOMAIN || IP"
else
  puts WebServerInfo.server_type(ARGV[0])
end

Cheers to Corey Goldberg and Brock

Taking Merb to Production 12

Posted by Ben Reubenstein Mon, 24 Dec 2007 15:11:00 GMT

UPDATE: I wrote this post very early in the evolution of the Merb platform. For more recent developments and tips, visit the Merb Wiki.

This past week I needed to implement a small webservice that needed to be fast and work well under a heavy load. I had part of the service implemented in Rails, but it was not as fast as I thought it could be so I decided to check out Merb. Merb is a lightweight MVC framework much like Rails. Merb however doesn't try to put a lot of "magic" at its core, so overall less time is spent in the framework and more time is spent in your code.

When I jumped into Merb, there were a lot of good articles but not much on how to productionize Merb, so I hope I can fill in the gap with this article.

NOTE: I am explaining a lot here, so if you run into spots that are confusing or you think could be done more efficiently, comment and I will get those adjustments into the doc.

Setting up Capistrano (Using 2.0)
Install Capistrano:

gem install capistrano

Like Rails apps there are certain files that will change in the production environment so they should not be in your repo. The ones I chose to exclude:
config/merb.yml
config/database.yml
Your excluded files may differ depending on the ORM you chose. I setup DataMapper for this particular application, though you could install the merb_activerecord gem and plug right into ActiveRecord.

Just like in a rails app run the capify command to get rolling:

$ capify .
[add] writing `./Capfile'
[add] writing `./config/deploy.rb'
[done] capified!

Edit your config/deploy.rb to match your settings here is my example with some notes:


set :application, "YOUR_APPLICATION_NAME"

# Set the path to your version control system (Subversion assumed)
set :repository, "http://something.com/svn/yourapplication/trunk"

# Set your SVN and SSH User
set :user, "your_ssh_user"
set :svn_user, "your_svn_user"
#Set the full path to your application on the server
set :deploy_to, "/PATH/TO/YOUR/#{application}"

#Define your servers
role :app, "your.appserver.com"
role :web, "your.webserver.com"
role :db, "your.databaseserver.com", :primary => true

desc "Link in the production extras and Migrate the Database ;)"
task :after_update_code do
  run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
  run "ln -nfs #{shared_path}/config/merb.yml #{release_path}/config/merb.yml"
  run "ln -nfs #{shared_path}/log #{release_path}/log"
  #if you use ActiveRecord, migrate the DB
  #deploy.migrate
end

desc "Merb it up with"
deploy.task :restart do
  run "cd #{current_path};./script/stop_merb"
  run "cd #{current_path};env EVENT=1 merb -c 4"
# If you want to run standard mongrel use this:
# run "cd #{current_path};merb -c 4"
end

#Overwrite the default deploy.migrate as it calls:
#rake RAILS_ENV=production db:migrate
#desc "MIGRATE THE DB! ActiveRecord"
#deploy.task :migrate do
#  run "cd #{release_path}; rake db:migrate MERB_ENV=production"
#end


Use Capistrano to initiate the environment, setting up the necessary directories on the server.
$ cap deploy:setup

Next, install the Gems you need on the Production server.

Note: if you are on the gem 0.9.4 run this upgrade, 0.9.5 is super nice ;). the -y / --include-dependencies option is on by default.

sudo gem update --system

sudo gem install merb
sudo gem install rspec

# For ActiveRecord
sudo gem install merb_activerecord
# For DataMapper
sudo gem install datamapper
sudo gem install do_mysql

# For Evented Mongrel
sudo gem install swiftiply

Create the directories and files that will be linked in.

mkdir /YOURDEPLOYPATH/shared/config
touch /YOURDEPLOYPATH/shared/config/database.yml
touch /YOURDEPLOYPATH/shared/config/merb.yml

Edit the .yml files to your liking and then be sure to create your database in MySQL! There is probably some neat deploy tricks you can do here with Capistrano, comment if you know it and I will update this section.

Deploy your app:

cap deploy

Now if you are amazing, it works the first time. If not check the errors. Most of them will likely be paths or a gem you missed.

Recap: We should now have our app deployed to the server and if you used the example config, 4 instances running. Hooray!

Setting up: NGINX
General Tip: If your server is still using Apache and you are just starting to experiment, run NGINX on another port, like 81. Be sure to clear a path through your Firewall ;)

Add the appropriate ip:ports to the upstream section for the merb instances you are running. The port that merb runs on and number of instances started are controlled by the deployment script and the merb.yml file.

upstream YOURUPSTREAMNAME {
 server 127.0.0.1:4000;
 server 127.0.0.1:4001;
 server 127.0.0.1:4002;
 server 127.0.0.1:4003;
}

Next lets add in a host section. This is just like a Rails host.


server {
 listen 80;

 client_max_body_size 50M;

 server_name YOURSERVERNAME;

 root /YOURPATH/current/public;

 #Want to log? include this
 #access_log /var/log/nginx/nginx.YOURAPPNAME.access.log main;

 if (-f $document_root/system/maintenance.html) {
  rewrite ^(.*)$ /system/maintenance.html last;
  break;
 }

 location / {
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_redirect false;
  proxy_max_temp_file_size 0;
  if (-f $request_filename) {
   break;
  }
  if (-f $request_filename/index.html) {
   rewrite (.*) $1/index.html break;
  }

  if (-f $request_filename.html) {
   rewrite (.*) $1.html break;
  }

  if (!-f $request_filename) {
   proxy_pass http://YOURUPSTREAMNAME;
   break;
  }  }

 error_page 500 502 503 504 /500.html;
 location = /500.html {
  root /YOURPATH/current/public;
 }
}


Restart nginx and enjoy your new Merb application!

Thanks to the folks in #merb and #datamapper for answering questions I had. Special thanks to Ezra for creating Merb and pushing performance in the Ruby web application world.

Resources:

Ruby Script to Simplify Setting up Subversion, Trac, and Apache

Posted by Ben Reubenstein Tue, 18 Dec 2007 13:35:00 GMT

I host svn and trac projects via apache on several servers. I found the task of setting them up repetitive so I set up this little script:

add_project.rb

Google Co-op Custom Search Engines

Posted by Ben Reubenstein Thu, 07 Jun 2007 11:33:00 GMT

When Google announced the new Google Co-op, which includes custom search engines, I did not immediately see the value. I wish I understood this services huge value sooner! I was trying to configure a reliable Apache with Mongrel Clustering setup, but was having a very tough time finding information. The Mongrel-users mailing list is hosted using Mailman, which does not have an obvious search function. When querying Google I was getting those results mixed in with the rest of the web. This is a perfect example of how a custom search engine can narrow your scope and get you the right answer fast. I setup a simple custom engine that just searched http://rubyforge.org/pipermail/mongrel-users/. I used the same query I had been using within Google, but this time found my answer almost immediately.

I have started another Ruby on Rails dedicated search engine that I hope to refine as I find more sources of information. This one searches the major Rails/Ruby mailing lists, the wiki, and the main site. I have left the search engine open, so if you have a site to contribute, feel free!

Ruby On Rails Custom Search
Google Custom Search


Mongrel Mailing List Search
Google Custom Search