Capistrano3.0.1でcap production deploy
を実行すると、Unicornを起動または再起動しようとしています。次のようなものを使用してCapistrano2.xで作業した例がいくつかあります。
namespace :Unicorn do
desc "Start Unicorn for this application"
task :start do
run "cd #{current_path} && bundle exec Unicorn -c /etc/Unicorn/myapp.conf.rb -D"
end
end
しかし、Capistrano3.xのdeploy.rb
でrun
を使用しようとすると、未定義のメソッドエラーが発生します。
これが私が試したいくつかのことです:
# within the :deploy I created a task that I called after :finished
namespace :deploy do
...
task :Unicorn do
run "cd #{current_path} && bundle exec Unicorn -c /etc/Unicorn/myapp.conf.rb -D"
end
after :finished, 'deploy:Unicorn'
end
また、:restartタスク内に実行を入れてみました
namespace :deploy do
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
# Your restart mechanism here, for example:
# execute :touch, release_path.join('tmp/restart.txt')
execute :run, "cd #{current_path} && bundle exec Unicorn -c /etc/Unicorn/deployrails.conf.rb -D"
end
end
ローカルシェルでrun "cd ... " then I'll get a
間違った数の引数(0の場合は1) `を使用した場合。
Ssh'd VM ShellからUnicorn -c /etc/Unicorn/deployrails.conf.rb -D
を使用してUnicornプロセスを開始できます。
KillUSR2を使用してVMシェルからマスターUnicornプロセスを強制終了できますが、プロセスが強制終了されてもエラーが発生します。その後、Unicorn -c ...
を使用してプロセスを再開できます。
$ kill USR2 58798
bash: kill: USR2: arguments must be process or job IDs
私はRubyに非常に慣れていません、Railsおよび一般的なデプロイメント。Ubuntu、Nginx、RVM、およびUnicornを使用したVirtualBoxセットアップがあります。これまでのところかなり興奮していますが、これは本当に私をいじって、アドバイスや洞察をいただければ幸いです。
Capistrano 3(私は2を使用)について具体的なことは何も言えませんが、これは役立つと思います: Capistrano v3のサーバーでシェルコマンドを実行する方法は? 。また、ユニコーン関連の経験を共有することもできます。これがお役に立てば幸いです。
24時間年中無休のグレースフルリスタートアプローチが必要だと思います。
この件については ユニコーンのドキュメント を参照してみましょう。正常な再起動(ダウンタイムなし)には、次の2つの戦略を使用できます。
kill -HUP Unicorn_master_pid
アプリで「preload_app」ディレクティブを無効にする必要があり、すべてのUnicornワーカーの開始時間が長くなります。あなたがそれと一緒に暮らすことができるなら-続けてください、それはあなたの呼び出しです。
kill -USR2 Unicorn_master_pid
kill -QUIT Unicorn_master_pid
すでにパフォーマンスの問題に対処している場合の、より洗練されたアプローチ。基本的に、Unicornマスタープロセスを再実行します。その後、前のプロセスを強制終了する必要があります。理論的には、usr2-sleep-quitアプローチを扱うことができます。もう1つの(そして正しい方法は)Unicorn before_forkフックを使用することです。これは、新しいマスタープロセスが生成されたときに実行され、新しい子を自分で探します。 config /Unicorn.rbに次のようなものを置くことができます。
# Where to drop a pidfile
pid project_home + '/tmp/pids/Unicorn.pid'
before_fork do |server, worker|
server.logger.info("worker=#{worker.nr} spawning in #{Dir.pwd}")
# graceful shutdown.
old_pid_file = project_home + '/tmp/pids/Unicorn.pid.oldbin'
if File.exists?(old_pid_file) && server.pid != old_pid_file
begin
old_pid = File.read(old_pid_file).to_i
server.logger.info("sending QUIT to #{old_pid}")
# we're killing old Unicorn master right there
Process.kill("QUIT", old_pid)
rescue Errno::ENOENT, Errno::ESRCH
# someone else did our job for us
end
end
end
新しいユニコーンが労働者をフォークする準備ができたら、古いユニコーンを殺すのは多かれ少なかれ安全です。その方法でダウンタイムが発生することはなく、古いユニコーンはワーカーが終了するのを待ちます。
そしてもう1つ-あなたはそれを runit またはinitの監督下に置くことをお勧めします。そうすれば、capistranoのタスクはsv reload Unicorn
、restart Unicorn
、または/etc/init.d/Unicorn restart
のように簡単になります。これは良いことです。
私は次のコードを使用しています:
namespace :Unicorn do
desc 'Stop Unicorn'
task :stop do
on roles(:app) do
if test("[ -f #{fetch(:Unicorn_pid)} ]")
execute :kill, capture(:cat, fetch(:Unicorn_pid))
end
end
end
desc 'Start Unicorn'
task :start do
on roles(:app) do
within current_path do
with Rails_env: fetch(:Rails_env) do
execute :bundle, "exec Unicorn -c #{fetch(:Unicorn_config)} -D"
end
end
end
end
desc 'Reload Unicorn without killing master process'
task :reload do
on roles(:app) do
if test("[ -f #{fetch(:Unicorn_pid)} ]")
execute :kill, '-s USR2', capture(:cat, fetch(:Unicorn_pid))
else
error 'Unicorn process not running'
end
end
end
desc 'Restart Unicorn'
task :restart
before :restart, :stop
before :restart, :start
end
これをリングに投げるだけです: capistrano 3 Unicorn gem
ただし、gem(およびinit.dスクリプトを使用しないアプローチ)に関する私の問題は、Unicornプロセスを管理する方法が2つある可能性があることです。 1つはこのキャップタスクを使用し、もう1つはinit.dスクリプトを使用します。 Monit/Godのようなものは混乱し、2つのUnicornプロセスを開始しようとしている理由のデバッグに何時間も費やす可能性があり、その後、人生を憎み始める可能性があります。
現在、capistrano3とUnicornで以下を使用しています。
namespace :Unicorn do
desc 'Restart application'
task :restart do
on roles(:app) do
puts "restarting Unicorn..."
execute "Sudo /etc/init.d/Unicorn_#{fetch(:application)} restart"
sleep 5
puts "whats running now, eh unicorn?"
execute "ps aux | grep Unicorn"
end
end
end
上記はpreload_appと組み合わされています:trueと@dredozubovによって言及されたbefore_forkおよびafter_forkステートメント
Init.d/UnicornスクリプトにUnicorn_application_nameという名前を付けたことに注意してください。
開始された新しいワーカーは、古いワーカーを強制終了する必要があります。 ps aux | grep Unicorn
で、古いマスターが消える前に数秒間ぶらぶらしていることがわかります。
書かれているようにネイティブのカピストラーノの方法を使用してみることができます ここ :
Preload_app:trueで、oldbinpidをクリーンアップするためにcapistranoが必要な場合:
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
task :restart do
invoke 'Unicorn:legacy_restart'
end
end