Monday, April 13, 2009
Friday, July 25, 2008
Passenger on CentOS, problems with passenger-memory-stats
I was having difficult running passenger-memory-stats, I was getting:
/usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.2/bin/passenger-memory-stats:145:in `list_processes': Invalid options. (ArgumentError)
from /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.2/bin/passenger-memory-stats:107:in `start'
from /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.2/bin/passenger-memory-stats:214
from /usr/bin/passenger-memory-stats:19:in `load'
from /usr/bin/passenger-memory-stats:19
After googling around, I found a post that said:
For those on CentOS/RHEL change line 107 in /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.2/bin/passenger-memory-stats from:
apache_processes = list_processes(:exe => PlatformInfo::HTTPD)
to
apache_processes = list_processes(:exe => 'httpd.worker')
This worked like a charm!
/usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.2/bin/passenger-memory-stats:145:in `list_processes': Invalid options. (ArgumentError)
from /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.2/bin/passenger-memory-stats:107:in `start'
from /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.2/bin/passenger-memory-stats:214
from /usr/bin/passenger-memory-stats:19:in `load'
from /usr/bin/passenger-memory-stats:19
After googling around, I found a post that said:
For those on CentOS/RHEL change line 107 in /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.2/bin/passenger-memory-stats from:
apache_processes = list_processes(:exe => PlatformInfo::HTTPD)
to
apache_processes = list_processes(:exe => 'httpd.worker')
This worked like a charm!
Thursday, July 24, 2008
Passenger Rocks
I set up Phusion Passenger which makes obsolete all the work I did for different Mongrel setups on my Capistrano scripts. It's amazing how much work I have done in my career that has now been made obsolute by something cooler. I still think FoxPro was the best.
Some notes to anyone setting up passenger. For CentOS, we had to install the package httpd-devel. The passenger setup script does the rest, you copy a few lines into your main http configuration file and it's good to go.
Here's my new configuration with SSL (names have been changed to protect my employer.) Note, my rails directory is /var/www/myrails/current:
Some notes to anyone setting up passenger. For CentOS, we had to install the package httpd-devel. The passenger setup script does the rest, you copy a few lines into your main http configuration file and it's good to go.
Here's my new configuration with SSL (names have been changed to protect my employer.) Note, my rails directory is /var/www/myrails/current:
<virtualhost>
ServerAdmin kevin@kenglish77.com
ServerName myrails.kenglish77.com
ErrorLog logs/myrails.kenglish77.com-error_log
CustomLog logs/myrails.kenglish77.com-access_log common
RewriteEngine On
RewriteCond %{SERVER_PORT} !443
RewriteRule ^(.*)$ https://myrails.kenglish77.com$1 [R=301,L]
</virtualhost>
<virtualhost>
ServerAdmin kevin@kenglish77.com
ServerName myrails.kenglish77.com
DocumentRoot "/var/www/myrails/current/public"
RailsEnv "id"
ErrorLog logs/myrails.kenglish77.com-ssl-error_log
CustomLog logs/myrails.kenglish77.com-ssl-access_log common
ExpiresActive On
ExpiresByType image/png "access plus 1 day"
ExpiresByType image/gif "access plus 1 day"
ExpiresByType image/jpeg "access plus 1 day"
ExpiresByType application/x-javascript "access plus 1 day"
ExpiresByType text/css "access plus 1 day"
RequestHeader set X_FORWARDED_PROTO 'https'
RewriteEngine On
# Force SSL
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,NE]
# Deflate
AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/javascript text/css application/x-javascript
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4.0[678] no-gzip
BrowserMatch bMSIE !no-gzip !gzip-only-text/html
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
SSLCertificateFile /etc/pki/tls/certs/wildcard-kenglish77.crt
SSLCertificateKeyFile /etc/pki/tls/private/wildcard-kenglish77.key
SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
</virtualhost>
Friday, February 15, 2008
Mongrel/Apache Setup on Ubuntu Server
This has been written up other places and most of what I know comes from Apache Best Practice Deployment By Charles Brian Quinn. I'm using Ubuntu Server 7.10 (Gusty Gibbons). I followed the "The Perfect Server - Ubuntu Gutsy Gibbon (Ubuntu 7.10)" guide, which is pretty good. I skipped the sections that didn't apply to my environment like Quotas and DNS.
After installing apache, I found out the version. Fortunately, it's 2.2:
$ apache2 -version
Server version: Apache/2.2.4 (Ubuntu)
Server built: Feb 4 2008 20:30:42
I had to manually link the apache logs directory to my /etc/apache2 directory.
$ cd /etc/apache2
$ sudo ln -s /var/log/apache2 logs/
Next, I needed to link all in the apache modules that I would be using from mods-available to mods-enabled . This is a nice feature of Apache 2.2. It sure beats copying a bunch of apache configuration commands into the http.conf.
$ cd /etc/apache2/mods-enabled
$ sudo ln -s ../mods-available/rewrite.load
$ sudo ln -s ../mods-available/proxy.load
$ sudo ln -s ../mods-available/proxy.conf
$ sudo ln -s ../mods-available/proxy_balancer.load
$ sudo ln -s ../mods-available/proxy_http.load
$ sudo ln -s ../mods-available/proxy_connect.load
(I found out the hard way that I needed the proxy_http.load module.)
Next I did my capistrano deploy to /var/www/myapp. I always make sure my mongrels are working by using lynx on the server box:
$ lynx http://127.0.0.1:3000
$ lynx http://127.0.0.1:3001
$ lynx http://127.0.0.1:3002
$ lynx http://127.0.0.1:3003
$ lynx http://127.0.0.1:3004
As long as the home page loads up, I'm good.
Finally, I created my myapp.conf in /etc/apache2/conf.d
$ cd /etc/apache2/conf.d
$ sudo vi myapp.conf
Here's what my apache config document looks like. It's very similar to Quinn's only I don't use seperate files:
ServerAdmin webmaster@localhost
# use my rails app as the document root.
DocumentRoot /var/www/myapp/current/public/
Options FollowSymLinks
AllowOverride None
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
RewriteEngine On
# Uncomment for rewrite debugging, this can come in handy
# RewriteLog logs/myapp_rewrite_log
# RewriteLogLevel 9
# Check for maintenance file and redirect all requests
# ( this is for use with Capistrano's disable_web task )
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /system/maintenance.html [L]
# Rewrite index to check for static
RewriteRule ^/$ /index.html [QSA]
# Rewrite to check for Rails cached page
RewriteRule ^([^.]+)$ $1.html [QSA]
# Redirect all non-static requests to cluster
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
# My balancer proxy
# You need these for Ubuntu
Order deny,allow
Deny from all
Allow from all
BalancerMember http://127.0.0.1:3000
BalancerMember http://127.0.0.1:3001
BalancerMember http://127.0.0.1:3002
BalancerMember http://127.0.0.1:3003
BalancerMember http://127.0.0.1:3004
# Loggin options
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
ServerSignature On
ErrorLog logs/myapp_errors_log
CustomLog logs/myapp_log combined
I know this post isn't very novel but I'm going to try to blog once a week now.
After installing apache, I found out the version. Fortunately, it's 2.2:
$ apache2 -version
Server version: Apache/2.2.4 (Ubuntu)
Server built: Feb 4 2008 20:30:42
I had to manually link the apache logs directory to my /etc/apache2 directory.
$ cd /etc/apache2
$ sudo ln -s /var/log/apache2 logs/
Next, I needed to link all in the apache modules that I would be using from mods-available to mods-enabled . This is a nice feature of Apache 2.2. It sure beats copying a bunch of apache configuration commands into the http.conf.
$ cd /etc/apache2/mods-enabled
$ sudo ln -s ../mods-available/rewrite.load
$ sudo ln -s ../mods-available/proxy.load
$ sudo ln -s ../mods-available/proxy.conf
$ sudo ln -s ../mods-available/proxy_balancer.load
$ sudo ln -s ../mods-available/proxy_http.load
$ sudo ln -s ../mods-available/proxy_connect.load
(I found out the hard way that I needed the proxy_http.load module.)
Next I did my capistrano deploy to /var/www/myapp. I always make sure my mongrels are working by using lynx on the server box:
$ lynx http://127.0.0.1:3000
$ lynx http://127.0.0.1:3001
$ lynx http://127.0.0.1:3002
$ lynx http://127.0.0.1:3003
$ lynx http://127.0.0.1:3004
As long as the home page loads up, I'm good.
Finally, I created my myapp.conf in /etc/apache2/conf.d
$ cd /etc/apache2/conf.d
$ sudo vi myapp.conf
Here's what my apache config document looks like. It's very similar to Quinn's only I don't use seperate files:
ServerAdmin webmaster@localhost
# use my rails app as the document root.
DocumentRoot /var/www/myapp/current/public/
Options FollowSymLinks
AllowOverride None
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
RewriteEngine On
# Uncomment for rewrite debugging, this can come in handy
# RewriteLog logs/myapp_rewrite_log
# RewriteLogLevel 9
# Check for maintenance file and redirect all requests
# ( this is for use with Capistrano's disable_web task )
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /system/maintenance.html [L]
# Rewrite index to check for static
RewriteRule ^/$ /index.html [QSA]
# Rewrite to check for Rails cached page
RewriteRule ^([^.]+)$ $1.html [QSA]
# Redirect all non-static requests to cluster
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
# My balancer proxy
# You need these for Ubuntu
Order deny,allow
Deny from all
Allow from all
BalancerMember http://127.0.0.1:3000
BalancerMember http://127.0.0.1:3001
BalancerMember http://127.0.0.1:3002
BalancerMember http://127.0.0.1:3003
BalancerMember http://127.0.0.1:3004
# Loggin options
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
ServerSignature On
ErrorLog logs/myapp_errors_log
CustomLog logs/myapp_log combined
I know this post isn't very novel but I'm going to try to blog once a week now.
Friday, December 14, 2007
Generator replacement for plugin_migration
I struggled last Friday trying to make loaded_plugins and plugin_migrations work in Rails 2.0. I was deep in the Rails source code when Seth suggest I simply create a generator. This is pretty easy. Here's what I came up with:
I place this in the file:
vendor/plugins/my_plugin/generators/my_plugin/my_plugin_generator.rb
To run it, I do:
ruby script/generate my_plugin migration
The generator will copy migrations from vendor/plugins/my_plugindb/migrate to db/migrate. It uses Rails functionality to ensure that the migration files are numbered sequentially starting with my application's next available migration number. If the migration is already in db/migrate, it will be skipped but it will not abort. This means I can add migrations to the plugin and run the generator again without worrying about it overwriting the old migrations.
Most of the work is done in the manifest method. By default, the Rails method migration_template looks for the template in a directory called template. In this case it would be looking for the migration file in vendor/plugins/my_plugin/generators/my_plugin/template which is what my relative_migration_path is relative to. My migration_exists method is basically a cut-and-paste from the Rails source code. I don't know why but they these methods are protected in Rails.
I hope this helps, it's a temporary fix. I'm sure the guys at plugin a week will have plugin_migrations fixed in no time :)
class MyPluginGenerator < Rails::Generator::NamedBase
def initialize(runtime_args, runtime_options = {})
super
@argument = runtime_args.shift
end
def manifest
relative_migration_path = "../../../db/migrate/"
recorded_session = record do |m|
get_migrations.each do | mf |
new_migration_file_name = mf.sub(/^(\d{3})_/,'')
new_migration_file_name.sub!(/\.rb$/,'')
unless migration_exists(new_migration_file_name)
m.migration_template "#{relative_migration_path}/#{mf}", 'db/migrate',
:assigns => { :migration_name => new_migration_file_name.camelize},
:migration_file_name => new_migration_file_name
puts " CREATING #{new_migration_file_name}."
else
puts " exists #{new_migration_file_name}, skipping."
end
end
end
end
protected
# Override with your own usage banner.
def banner
"Usage: #{$0} my_plugin migration"
end
def migration_exists(file_name)
migration_directory = File.dirname(__FILE__) + "/../../../../../db/migrate"
not Dir.glob("#{migration_directory}/[0-9]*_*.rb").grep(/[0-9]+_#{file_name}.rb$/).blank?
end
def get_migrations
migration_files = []
my_plugin_migration_path = File.dirname(__FILE__) + '/../../db/migrate'
Dir.entries(my_plugin_migration_path).sort.each do | migration_file |
if migration_file =~ /^(\d{3})/
migration_files << migration_file
end
end
migration_files
end
end
I place this in the file:
vendor/plugins/my_plugin/generators/my_plugin/my_plugin_generator.rb
To run it, I do:
ruby script/generate my_plugin migration
The generator will copy migrations from vendor/plugins/my_plugindb/migrate to db/migrate. It uses Rails functionality to ensure that the migration files are numbered sequentially starting with my application's next available migration number. If the migration is already in db/migrate, it will be skipped but it will not abort. This means I can add migrations to the plugin and run the generator again without worrying about it overwriting the old migrations.
Most of the work is done in the manifest method. By default, the Rails method migration_template looks for the template in a directory called template. In this case it would be looking for the migration file in vendor/plugins/my_plugin/generators/my_plugin/template which is what my relative_migration_path is relative to. My migration_exists method is basically a cut-and-paste from the Rails source code. I don't know why but they these methods are protected in Rails.
I hope this helps, it's a temporary fix. I'm sure the guys at plugin a week will have plugin_migrations fixed in no time :)
Thursday, December 6, 2007
Namespace Hell
I was writing a Rails plugin when I entered namespace hell. I had 2 classes with the same name and they were conflicting. I'm not sure if this was Rails problem or a simple ruby issue. Here is the scenario, the directory layout was as follows:
lib/query.rb
lib/warehouse/query.rb
lib/warehouse/table_report_query.rb
in query.rb I had:
class Query < ActiveRecord::Base
some_code_here
in lib/warehouse/query.rb I had:
module Warehouse
class Query
some_code_here
end
in lib/warehouse/table_report_query.rb I had:
module Warehouse
class TableReportQuery < Query
some_code_here
end
So, in the controller, when I did:
table_query = Warehouse::TableReportQuery.new()
You would think that TableReportQuery would inherit from Warehouse::Query. WRONG! It was inheriting from the first Query and throwing the classic activerecord "method not found" error.
So what's the solution. Well, I give credit to this blog article about Ruby Namespace Conflicts for inspiring my solution. I changed lib/warehouse/table_report_query.rb to be:
class Warehouse::TableReportQuery < Warehouse::Query
and it worked! Is that ruby Voodoo or what?
lib/query.rb
lib/warehouse/query.rb
lib/warehouse/table_report_query.rb
in query.rb I had:
class Query < ActiveRecord::Base
some_code_here
endin lib/warehouse/query.rb I had:
module Warehouse
class Query
some_code_here
endend
in lib/warehouse/table_report_query.rb I had:
module Warehouse
class TableReportQuery < Query
some_code_here
endend
So, in the controller, when I did:
table_query = Warehouse::TableReportQuery.new()
You would think that TableReportQuery would inherit from Warehouse::Query. WRONG! It was inheriting from the first Query and throwing the classic activerecord "method not found" error.
So what's the solution. Well, I give credit to this blog article about Ruby Namespace Conflicts for inspiring my solution. I changed lib/warehouse/table_report_query.rb to be:
class Warehouse::TableReportQuery < Warehouse::Query
some_code_here
endand it worked! Is that ruby Voodoo or what?
Tuesday, December 4, 2007
Plugin Development
Developing a Plugin for Rails can be a lot of fun. You can find a good guide here with the complete guide to rails plugins.
Piston
Be sure to read Managing Rails Plugins with Piston.
The best way to produce a good plugin is to create a separate application which can be used to test the plugin and use piston to import changes into you main application using 'piston update'.
Avoid Restarting Mongrel
I have learned one helpful trick. By default, you will have to restart your Mongrel server every time you make a change to your plugin. You can avoid this by placing the following code at the top of your plugin's init.rb file:
Piston
Be sure to read Managing Rails Plugins with Piston.
The best way to produce a good plugin is to create a separate application which can be used to test the plugin and use piston to import changes into you main application using 'piston update'.
Avoid Restarting Mongrel
I have learned one helpful trick. By default, you will have to restart your Mongrel server every time you make a change to your plugin. You can avoid this by placing the following code at the top of your plugin's init.rb file:
Dependencies.load_once_paths.delete(lib_path)
Subscribe to:
Posts (Atom)