Search code examples
ruby-on-rails-3capistrano

Cap deploy:setup stuck at sftp command (using Simone Carletti's recipe for database.yml)


I m deploying my rails 3 app with capistrano and I can't figure out why at some point during cap deploy:setup task the command line is waiting on a sftp command.

I searched into the recipe where this command is sent in order to understand but couldn't find it.

As sidenote, I'm using Simon Carlett's recipe to generate the database.yml file instead of storing & fetching it on github).

Here it is my output :

/var/www/odpf/config$ cap deploy:setup
    triggering load callbacks
  * 2014-01-07 09:03:03 executing `deploy:setup'
  * executing "mkdir -p /var/www/odpf /var/www/odpf/releases /var/www/odpf/shared /var/www/odpf/shared/system /var/www/odpf/shared/log /var/www/odpf/shared/pids"
    servers: ["*****"]
Enter passphrase for /home/me/.ssh/id_rsa: 
    [*****] executing command
 ** [out :: *****]
    command finished in 355ms
    triggering after callbacks for `deploy:setup'
  * 2014-01-07 09:03:12 executing `deploy:db:setup'
  * executing "mkdir -p /var/www/odpf/shared/db"
    servers: ["*****"]
    [*****] executing command
 ** [out :: *****]
    command finished in 350ms
  * executing "mkdir -p /var/www/odpf/shared/config"
    servers: ["*****"]
    [*****] executing command
 ** [out :: *****]
    command finished in 350ms
    servers: ["*****"]
 ** sftp upload #<StringIO:0x000000010579f8> -> /var/www/odpf/shared/config/database.yml

After this last instruction, the command line seems to wait infinitely... I hit CTRL+C and some ruby error are outputed :

^C/home/me/.rvm/gems/ruby-2.1.0@rails3/gems/capistrano-2.15.5/lib/capistrano/processable.rb:25:in `select': Interrupt
etc...

I looked into this file around line 25 and found this :

  21> readers = sessions.map { |session| session.listeners.keys }.flatten.reject { |io| io.closed? }
  22> writers = readers.select { |io| io.respond_to?(:pending_write?) && io.pending_write? }
  23>
  24> if readers.any? || writers.any?
  25>   readers, writers, = IO.select(readers, writers, nil, wait)
  26> else
  27>   return false
  28> end

Here it is Simone Carletti's recipe :

#
# = Capistrano database.yml task
#
# Provides a couple of tasks for creating the database.yml
# configuration file dynamically when deploy:setup is run.
#
# Category::    Capistrano
# Package::     Database
# Author::      Simone Carletti
# Copyright::   2007-2009 The Authors
# License::     MIT License
# Link::        http://www.simonecarletti.com/
# Source::      http://gist.github.com/2769
#
#

unless Capistrano::Configuration.respond_to?(:instance)
  abort "This extension requires Capistrano 2"
end

Capistrano::Configuration.instance.load do

  namespace :db do

    desc <<-DESC
      Creates the database.yml configuration file in shared path.

      By default, this task uses a template unless a template
      called database.yml.erb is found either is :template_dir
      or /config/deploy folders. The default template matches
      the template for config/database.yml file shipped with Rails.

      When this recipe is loaded, db:setup is automatically configured
      to be invoked after deploy:setup. You can skip this task setting
      the variable :skip_db_setup to true. This is especially useful
      if you are using this recipe in combination with
      capistrano-ext/multistaging to avoid multiple db:setup calls
      when running deploy:setup for all stages one by one.
    DESC
    task :setup, :except => { :no_release => true } do

      default_template = <<-EOF
      base: &base
        adapter: sqlite3
        timeout: 5000
      development:
        database: #{shared_path}/db/development.sqlite3
        <<: *base
      test:
        database: #{shared_path}/db/test.sqlite3
        <<: *base
      production:
        database: #{shared_path}/db/production.sqlite3
        <<: *base
      EOF

      location = fetch(:template_dir, "config/deploy") + '/database.yml.erb'
      template = File.file?(location) ? File.read(location) : default_template

      config = ERB.new(template)

      run "mkdir -p #{shared_path}/db"
      run "mkdir -p #{shared_path}/config"
      put config.result(binding), "#{shared_path}/config/database.yml"
    end

    desc <<-DESC
      [internal] Updates the symlink for database.yml file to the just deployed release.
    DESC
    task :symlink, :except => { :no_release => true } do
      run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
    end

  end

  after "deploy:setup",           "db:setup"   unless fetch(:skip_db_setup, false)
  after "deploy:finalize_update", "db:symlink"

end

Any help would really be appreciated.

Thanks


Solution

  • After a long search I decided to upgrade to Capistrano 3.x thinking that maybe it would solve my problem as it use ssh-kit instead of sftp.

    It did not solved this issue.

    I opened a new question linked to Capistrano 3.x and found the solution.

    This might be as well the solution for Capistrano 2.x though I didn't tested it. So I post here this possible solution in case somebody is interested to test it.

    In fact in Capistrano 3.x the, issue was linked to net-scp that is bugged since year 2000. So maybe sftp work the same way as net-scp.

    The problem was coming from my .bashrc file (and the echo commands I put into) that is being executed during the ssh connexion (non-login, non-interactive). More information here

    If anyone test it successfully, please tell us about it.

    my few cents on this.