RailsアプリケーションをCapistranoでデプロイするのはよくあるやり方です。僕もその方法でサービスをデプロイしています。 ところがこの方法でデプロイしたサーバーではrails consoleがうまく動かないという問題(もしくは僕の設定不備)があることがわかりました。
Railsのルートに居るにも関わらずUsageがプリントされるだけで終わってしまうのです。
1$ cd /home/deploy/app/app_name/current
2$ bin/rails console
3Usage:
4 rails new APP_PATH [options]
5
6Options:
7 -r, [--ruby=PATH] # Path to the Ruby binary of your choice
8
9# 以下略
staging環境にしろproduction環境にしろ、ちょっとデータを見たかったりadmin権限をこっそり付与したりといったことはわりと多いので、rails consoleが使えないのはとても困ります。
そこでいつもお世話になっているQA@ITさんに質問を投げさせてもらいました。
AWSにデプロイしたRailsアプリケーションのコンソールを起動したいがUsageが出てしまう - QA@IT
[http://qa.atmarkit.co.jp/q/2925:image:large]
ですが、これといった回答は得られませんでした。仕方なくごまかしながら開発を進めていたのですが、ある時気がつきました。irbなりpryでRailsの環境をロードしてしまえばいいんだ!
rails console が動かない、効かない
そこでこんなスクリプトを書きましたよ。 必要なgemをrequireしてからRailsをロードし、最後にpryを実行します。
1#!/usr/bin/env ruby
2
3require 'pathname'
4ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
5 Pathname.new(__FILE__).realpath)
6
7require 'rubygems'
8require 'bundler/setup'
9
10require File.expand_path('../application', __FILE__)
11Rails.application.require_environment!
12
13load Gem.bin_path('pry', 'pry')
そうしたらこんなふうに実行します。
1$ cd /home/deploy/app/app_name/current
2$ RAILS_ENV=production config/rails_console.rb # configに置くのはどうよと思いますが、まあいいんです。
3[WARN] cannot load Rails console commands (Not on Rails2 or Rails3?)
4[1] pry(main)>
なんか警告が出ましたが、特に問題なく使えるので細かいことは気にしなくていいでしょう。
rails consoleコマンドが動かない理由をちゃんと解明していない気持ち悪さは残りますが、本番用サーバーでもrails console相当のことを実行できるようになってストレスを軽減できるようになりました。
Capistranoのタスクでリモートのconsoleを立ち上げる
先の方法ではSSHログイン後Railsのルートへ移動し、rails_console.rbスクリプトを叩いていました。大した手順じゃないですが面倒なのでCapistranoを使ってローカルのターミナルからダイレクトに接続してしまいましょう。
リモートのrails consoleを起動するためのタスクがこちらで紹介されているのでそれを流用しました。rails consoleのところをconfig/rails_console.rbにするだけですね。 Capistrano task to open a rails console on a remote server. Require this file in your deploy.rb and run “cap rails:console”
1namespace :rails do
2 task :console, :roles => :app do
3 run_interactively "RAILS_ENV=#{rails_env.to_s.shellescape} #{latest_release.shellescape}/config/rails_console.rb"
4 end
5end
6
7def run_interactively(command, server=nil)
8 server ||= find_servers_for_task(current_task).first
9 exec %Q(ssh #{server.host} -t 'sudo su - #{application} -c "cd #{current_path} && #{command}"')
10end
run_interactivelyではsshでリモートのコマンドを実行するために実行したいコマンドに-tオプションを付与して実行しています。
これで、次のようなコマンドでconsoleにダイレクトに接続できストレスフリーです!
1$ cap rails:console
2
3$ cap production rails:console # multistageを使っている場合