RailsCasts Pro episodes are now free!

Learn more or hide this

adam-pl's Profile

GitHub User: adam-pl

Comments by


SSH Timeouts - avoid ssh disconnection with Capistrano:

1) Add file config/recipes/ssh.rb

load "config/recipes/base"

namespace :ssh do
  desc "Setup long timeouts for ssh connection"
  task :install, roles: :app do
    sshd = <<-BASHRC
  ClientAliveInterval 60
  ClientAliveCountMax 1200
    cmd = %Q{grep -R "ClientAliveInterval" /etc/ssh/sshd_config}
    content = capture( %Q{bash -c '#{cmd}' || echo "false"}).strip
    if content == 'false'
      put sshd, '/tmp/sshd'
      run 'cat /etc/ssh/sshd_config /tmp/sshd > /tmp/sshd.tmp'
      run 'rm /tmp/sshd'
      run "#{sudo} mv /tmp/sshd.tmp /etc/ssh/sshd_config"
      run 'echo "FILE /etc/ssh/sshd_config" IS ALREADY UPDATED!'
  after "deploy:install", "ssh:install"

2) Edit config/deploy.rb file and add:

load "config/recipes/ssh"

It works when you call:

cap deploy:install


cap ssh:install

NOTE 1 - you can call cap ssh:install many times with no worries that file /etc/ssh/sshd_config includes string ClientAliveInterval 60 many times.
It's safe because following code:

    cmd = %Q{grep -R "ClientAliveInterval" /etc/ssh/sshd_config}
    content = capture( %Q{bash -c '#{cmd}' || echo "false"}).strip
    if content == 'false'
      # Here we know that we must do setup
      # Here we know that setup is already done

NOTE 2 - Additionally I've made the same kind of protection in file config/recipes/rbenv.erb. So now I can call cap deploy:install many times (well, it's not recommended but sometimes it's usefull if you tests deploying process many times).


Today I had a big problem with deploying on remote machine. Many hours spent on problem with hanging Capitrano.
When I did cap deploy:install all required packages were installed properly except one - ruby 1.9.3-p327.

Capistrano hangs forever on executing rbenv install 1.9.3-p327 with message Installing ruby-1.9.3-p327....

I've used second ssh connection with top running for checking numer of users logged in. I've detected that message Installing ruby-1.9.3-p327... still exists after number of logged in users decrease from 2 into 1.

What is the reason? SSH timeout session breaks connection.

How to solve the problem? My solution is:
1) Just edit file /etc/ssh/sshd_config and add following lines:

  ClientAliveInterval 18
  ClientAliveCountMax 100

Parameter ClientAliveInterval should have very small number to make pinging very often.
18*100 = 1800 seconds means 30 minutes of session timeout (enough I think).
2) Then restart ssh service:

sudo service ssh restart

3) Try to deploy:

cap deploy:install

It works now for me :-)

If you not, additionally try to edit file /etc/ssh/ssh_config:

  ServerAliveInterval 18
  ServerAliveCountMax 100

Then restart ssh service.
I hope it will be helpfull for somebody.


This code repeats 3 times. I've made press_enter method:

def press_enter( ch, stream, data)
  if data =~ /Press.\[ENTER\].to.continue/
    # prompt, and then send the response to the remote process
    ch.send_data( "\n")
    # use the default handler for all other text
    Capistrano::Configuration.default_io_proc.call( ch, stream, data)

I don't like to press Enter every time, so I've used ch.send_data( "\n") code.

Then you can use it like that:

run "#{sudo} add-apt-repository ppa:pitti/postgresql", pty: true do |ch, stream, data|
  press_enter( ch, stream, data)

Hi Mark,

Thank your for your info!

I'm not sure if I understand correctly.
Can you give me an example how it works and how it should work?

In the meantime I'll give you an idea how to make www. subdomain by default. Let's suppose:
1. First you open page that has url - for example <a href="http://mark.lvh.me:3000/">Show Mark</a>). You click it and new page opens.
2. Then you click link http://www.lvh.me:3000/adam (page has full url path - <a href="http://www.lvh.me:3000/adam">Show Adam</a>)
3. New page opens and it has only paths for example <a href="/adam">Show Adam</a>. It doen't have html code like <a href="http://lvh.me:3000/adam">Show Adam</a> - I guess you gets full url in this point.

How I did it?
1. added line before_filter :check_url_for_www
2. defined method check_url_for_www
It looks like that:

  def check_url_for_www
    redirect_to request.protocol + "www." + request.host_with_port + request.fullpath 
      if !/^www/i.match(request.host) 
      and !DomainFormatValidator::check_numeric_domain(request.host)
      and allowed_subdomains?
      and !Rails.env.test?

There is used DomainFormatValidator::check_numeric_domain method in the :check_url_for_www:

def self.check_numeric_domain( host)
  /^(\d{1,3}\.){3}(\d{1,3})$/.match( host)

and allowed_subdomains? ApplicationHelper's method:

def allowed_subdomains?

The reason is you can use numeric addresing like for opening your page. In this case we cannot add www. subdomain.
Besides we chec if domain is blank. If true the we do nothing.

It works fine on my local, development environment. I've never tested it in the poduction environment, but I'm going to do that very soon :)

I hope it is clear. If not let me know :)


I've also had the same problem.

The reason is unicorn_init.sh file doesn't have execute flag on server site.
To do that let's add following line into deploy.rb at :symlink_config task section:

sudo "chmod +x #{release_path}/config/unicorn_init.sh"

Finally :symlink_config task's code is:

  task :symlink_config, roles: :app do
    run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
    run "chmod +x #{release_path}/config/unicorn_init.sh"

You do not have replace any run into sudo.

For me it works fine.


Hi all!

Nice screencast but I don't like:
1. Using lambda in the routes.rb file
2. Problem with adding subdomain: false in every routing that I want to clean urls from subdomain
3. Problem with changing every link_to with _path to _url also for cleaning urls (many hours of work in large project).

My solutions:
ad. 1. Instead of using the lambda I can use smart regular expression:

match '/' => 'blogs#show', constraints: { subdomain: /^(?!www$)(.+)$/i }

Regular expression /^(?!www$)(.+)$/i doesn't allow to handle main domain with www. Really nice, isn't?

ad. 2. I prefer to add following line in development.rb and production.rb files:

config.action_controller.default_url_options = { subdomain: false }

Now using subdomain is disabled by default. I don't need to add subdomain: false in many lines in routes.rb file... ufff.

ad. 3. I prefer to create file url_helper.rb with a few lines of code:

module UrlHelper
  def url_for(options = nil)
    if request.subdomain.present? 
    and request.subdomain.downcase != 'www'
    and !options.nil? and options.is_a?(Hash)
    and options.has_key? :only_path
    and options[:only_path]
      options[:only_path] = false
      puts "Changed options[:only_path] to true. options=#{options.inspect}" unless options.nil?

Now I do not have to change thousands of links :-) ufff :-))

It works for me. Do you like it?

P.S. I'm using Rails 3.2