Skip to content

Instantly share code, notes, and snippets.

@jhjguxin
Last active December 19, 2015 09:29
Show Gist options
  • Save jhjguxin/5932994 to your computer and use it in GitHub Desktop.
Save jhjguxin/5932994 to your computer and use it in GitHub Desktop.
rails deploy with rvm, capistrano, uniron, nginx
# This file is used by Rack-based servers to start the application.
if defined?(ENV) and ENV["RAILS_ENV"].eql?("production")
#if self.class.const_defined?("Unicorn") and self.class.const_defined?("Unicorn::WorkerKiller")
require 'unicorn/oob_gc'
require 'unicorn/worker_killer'
# 每10次请求,才执行一次GC
use Unicorn::OobGC, 10
# 设定最大请求次数后自杀,避免禁止GC带来的内存泄漏(1000~1800之间随机,避免同时多个进程同时自杀,可以和下面的设定任选)
use Unicorn::WorkerKiller::MaxRequests, 1000, 1800
# 设定达到最大内存后自杀,避免禁止GC带来的内存泄漏(192~256MB之间随机,避免同时多个进程同时自杀)
use Unicorn::WorkerKiller::Oom, (192*(1024**2)), (256*(1024**2))
end
require ::File.expand_path('../config/environment', __FILE__)
run GuanxiMeWww::Application
require 'capistrano/ext/multistage'
require "bundler/capistrano"
require "rvm/capistrano"
def run_remote_rake(rake_cmd)
rake_args = ENV['RAKE_ARGS'].to_s.split(',')
cmd = "cd #{deploy_to}/current && #{fetch(:rake, "rake")} RAILS_ENV=#{fetch(:rails_env, "production")} #{rake_cmd}"
cmd += "['#{rake_args.join("','")}']" unless rake_args.empty?
run cmd
set :rakefile, nil if exists?(:rakefile)
end
def remote_file_exists?(full_path)
#result = capture("if [ -e #{full_path} ]; then echo 'true'; fi").strip
result = capture("if [ -e #{full_path} ]; then echo 'true'; fi").strip.split.first
#p result
'true'.eql?(result)
end
############# bootstrap rvm-capistrano
#set :rvm_ruby_string, ENV['GEM_HOME'].gsub(/.*\//,"")
#set :rvm_install_ruby_params, '--1.9' # for jruby/rbx default to 1.9 mode
set :rvm_ruby_string, '1.9.3'
# set :rvm_type, :system
before 'deploy:setup', 'rvm:install_rvm' # install RVM
before 'deploy:setup', 'rvm:install_ruby' # install Ruby and create gemset, or:
before 'deploy:setup', 'rvm:create_gemset' # only create gemset
set :application, "guanxime_www"
# set :repository, "xxxxxxxxxxxxxxxxxx.git"
default_run_options[:pty] = true
set :use_sudo, false
set :scm, :git # You can set :scm explicitly or Capistrano will make an intelligent guess based on known version control directory names
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
set :scm_username, 'git'
# role :web, "nginx" # Your HTTP server, Apache/etc
# role :app, "unicorn" # This may be the same as your `Web` server
# role :db, "your primary db-server here", :primary => true # This is where Rails migrations will run
# role :db, "your slave db-server here"
set :stages, %w(production)
set :default_stage, "production"
###########the golb setting maby alse inside stages file config/deploy/dev.rb
set :branch, "master"
#set :user, 'guanxi'
set :user, 'gxdevelop'
set :port, 40022
set :deploy_via, :remote_cache
set :deploy_env, 'production'
#set :deploy_to "/opt/#{application}"
set :deploy_to, "/var/www/guanxi/deployment/#{application}"
#set :base_path, "/home/#{user}"
#set(:deploy_to) { "#{base_path}/#{application}/#{stage}" }
######################
# if you want to clean up old releases on each deploy uncomment this:
# after "deploy:restart", "deploy:cleanup"
set :keep_releases, 5
# if you're still using the script/reaper helper you will need
# these http://github.com/rails/irs_process_scripts
# unicorn.conf.rb path
set :unicorn_conf, "#{deploy_to}/current/config/unicorn.conf.rb"
set :unicorn_pid, "#{deploy_to}/current/tmp/pids/unicorn.pid"
# If you are using Passenger mod_rails uncomment this:
# namespace :deploy do
# task :start do ; end
# task :stop do ; end
# task :restart, :roles => :app, :except => { :no_release => true } do
# run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
# end
# end
namespace :deploy do
%w[start stop restart].each do |command|
desc "#{command} unicorn server"
task command, roles: :app, except: {no_release: true} do
run "chmod a+x /etc/init.d/unicorn_#{application}"
run "/etc/init.d/unicorn_#{application} #{command}" # Using unicorn as the app server
end
end
task :init_path_and_config, :roles => :web do
#run "mkdir -p #{shared_path}/log"
#run "mkdir -p #{shared_path}/pids"
#run "mkdir -p #{shared_path}/assets"
run "mkdir -p #{shared_path}/config"
run "cp #{current_release}/config/mongoid.yml.example #{shared_path}/config/mongoid.yml" unless remote_file_exists?("#{shared_path}/config/mongoid.yml")
run "cp #{current_release}/config/nginx.conf.example #{shared_path}/config/nginx.conf" unless remote_file_exists?("#{shared_path}/config/nginx.conf")
run "cp #{current_release}/config/unicorn_init.sh.example #{shared_path}/config/unicorn_init.sh" unless remote_file_exists?("#{shared_path}/config/unicorn_init.sh")
run "cp #{current_release}/config/gxserver.yml.example #{shared_path}/config/gxserver.yml" unless remote_file_exists?("#{shared_path}/config/gxserver.yml")
run "cp #{current_release}/config/resque.yml.example #{shared_path}/config/resque.yml" unless remote_file_exists?("#{shared_path}/config/resque.yml")
end
task :link_shared_files, :roles => :web do
%w(*.yml *.conf unicorn_init.sh).each do |file_name|
run "ln -nfs #{shared_path}/config/#{file_name} #{deploy_to}/current/config/"
end
end
task :setup_config, roles: :app do
#http://stackoverflow.com/questions/15459447/rails-deployment-using-nginx-unicorn-403-forbidden-error
#http://stackoverflow.com/questions/15606312/assets-not-loading-in-production-for-rails-app
# 必须在用户根目录 加 执行权限
# https://gist.github.com/jhjguxin/6208474
# chmod 707 -R ~/
# chmod 775 -R public/assets/
# chmod 775 -R public/ampedservice_assets/
sudo "rm /etc/nginx/conf.d/#{application}.conf" if remote_file_exists?("/etc/nginx/conf.d/#{application}.conf")
sudo "ln -nfs #{current_path}/config/nginx.conf /etc/nginx/conf.d/#{application}.conf"
sudo "rm /etc/init.d/unicorn_#{application}" if remote_file_exists?("/etc/init.d/unicorn_#{application}")
sudo "ln -nfs #{current_path}/config/unicorn_init.sh /etc/init.d/unicorn_#{application}"
run "chmod a+x /etc/init.d/unicorn_#{application}"
puts "Now edit the config files in #{shared_path}."
end
end
# task for testing
task :uname do
run "uname -a"
end
after "deploy:finalize_update", "deploy:symlink", "deploy:init_path_and_config", "deploy:link_shared_files", "deploy:setup_config"
platforms :ruby do
# Deploy with Capistrano
gem "capistrano"#, "~> 2.14.2"
gem "rvm-capistrano", "~> 1.2.7"
end
group :production do
gem 'unicorn', :platforms => :ruby
gem "unicorn-worker-killer", :platforms => :ruby
#gem 'newrelic_rpm', :platforms => :ruby
end
upstream guanxime_www_unicorn {
server unix:/tmp/unicorn.guanxime_www.sock fail_timeout=0;
}
server {
listen 80;# default deferred;
server_name www.guanxi.me;
root /var/www/guanxi/deployment/guanxime_www/current/public;
# individual nginx logs for this guanxime_www vhost
access_log /var/log/nginx/guanxime_www_access.log;
error_log /var/log/nginx/guanxime_www_error.log;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri @unicorn;
location @unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://guanxime_www_unicorn;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
# sudo cp config/nginx.conf /etc/nginx/sites-enabled/
# sudo cp config/nginx.conf /etc/nginx/conf.d/
# sudo ln -nfs config/nginx.conf /etc/nginx/conf.d/guanxime_www.conf
# config/deploy/production.rb
set :repository, "xxxxxxxxxxxxxxxxxxxxxxxxxxxx.git"
server "xxxxxxxxxx", :app, :web, :db, :primary => true
# Sample verbose configuration file for Unicorn (not Rack)
#
# This configuration file documents many features of Unicorn
# that may not be needed for some applications. See
# http://unicorn.bogomips.org/examples/unicorn.conf.minimal.rb
# for a much simpler configuration file.
#
# See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
# documentation.
# Use at least one worker per core if you're on a dedicated server,
# more will usually help for _short_ waits on databases/caches.
worker_processes 5
# Since Unicorn is never exposed to outside clients, it does not need to
# run on the standard HTTP port (80), there is no reason to start Unicorn
# as root unless it's from system init scripts.
# If running the master process as root and the workers as an unprivileged
# user, do this to switch euid/egid in the workers (also chowns logs):
# user "unprivileged_user", "unprivileged_group"
module Rails
class << self
def root
File.expand_path("../..", __FILE__)
end
end
end
# Help ensure your application will always spawn in the symlinked
# "current" directory that Capistrano sets up.
# working_directory "/path/to/app/current" # available in 0.94.0+
working_directory Rails.root
# listen on both a Unix domain socket and a TCP port,
# we use a shorter backlog for quicker failover when busy
# listen "/path/to/.unicorn.sock", :backlog => 64
listen "/tmp/unicorn.guanxime_www.sock"
listen 7788, :tcp_nopush => true
# nuke workers after 30 seconds instead of 60 seconds (the default)
timeout 30
# feel free to point this anywhere accessible on the filesystem
# pid "/path/to/app/shared/pids/unicorn.pid"
pid "#{Rails.root}/tmp/pids/unicorn.pid"
# By default, the Unicorn logger will write to stderr.
# Additionally, ome applications/frameworks log to stderr or stdout,
# so prevent them from going to /dev/null when daemonized here:
# stderr_path "/path/to/app/shared/log/unicorn.stderr.log"
# stdout_path "/path/to/app/shared/log/unicorn.stdout.log"
stderr_path "#{Rails.root}/log/unicorn.log"
stdout_path "#{Rails.root}/log/unicorn.log"
# combine Ruby 2.0.0dev or REE with "preload_app true" for memory savings
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
# http://unicorn.bogomips.org/Unicorn/Configurator.html#method-i-preload_app
# preload_app true
GC.respond_to?(:copy_on_write_friendly=) and
GC.copy_on_write_friendly = true
# Enable this flag to have unicorn test client connections by writing the
# beginning of the HTTP headers before calling the application. This
# prevents calling the application for connections that have disconnected
# while queued. This is only guaranteed to detect clients on the same
# host unicorn runs on, and unlikely to detect disconnects even on a
# fast LAN.
check_client_connection false
module Rails
class << self
def root
File.expand_path("../..", __FILE__)
end
end
end
rails_env = ENV["RAILS_ENV"] || "production"
before_exec do |server|
ENV["BUNDLE_GEMFILE"] = "#{Rails.root}/Gemfile"
end
before_fork do |server, worker|
old_pid = "#{Rails.root}/tmp/pids/unicorn.pid.oldbin"
if File.exists?(old_pid) && server.pid != old_pid
begin
Process.kill("QUIT", File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
puts "Send 'QUIT' signal to unicorn error!"
end
end
end
after_fork do |server, worker|
# per-process listener ports for debugging/admin/migrations
# addr = "127.0.0.1:#{9293 + worker.nr}"
# server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
# the following is *required* for Rails + "preload_app true",
# defined?(ActiveRecord::Base) and
# ActiveRecord::Base.establish_connection
# if preload_app is true, then you may also want to check and
# restart any other shared sockets/descriptors such as Memcached,
# and Redis. TokyoCabinet file handles are safe to reuse
# between any number of forked children (assuming your kernel
# correctly implements pread()/pwrite() system calls)
end
#!/bin/sh
### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Manage unicorn server
# Description: Start, stop, restart unicorn server for a specific application.
### END INIT INFO
set -e
# Feel free to change any of the following variables for your app:
TIMEOUT=${TIMEOUT-60}
APP_ROOT=/var/www/guanxi/deployment/guanxime_www/current
PID=$APP_ROOT/tmp/pids/unicorn.pid
CMD="cd $APP_ROOT; RAILS_ENV=production bundle exec unicorn -D -c $APP_ROOT/config/unicorn.conf.rb -E production"
AS_USER=gxdevelop
set -u
OLD_PIN="$PID.oldbin"
sig () {
test -s "$PID" && kill -$1 `cat $PID`
}
oldsig () {
test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
}
run () {
if [ "$(id -un)" = "$AS_USER" ]; then
eval $1
else
su -c "$1" - $AS_USER
fi
}
case "$1" in
start)
sig 0 && echo >&2 "Already running" && exit 0
run "$CMD"
;;
stop)
sig QUIT && exit 0
echo >&2 "Not running"
;;
force-stop)
sig TERM && exit 0
echo >&2 "Not running"
;;
restart|reload)
sig HUP && echo reloaded OK && exit 0
echo >&2 "Couldn't reload, starting '$CMD' instead"
run "$CMD"
;;
upgrade)
if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
then
n=$TIMEOUT
while test -s $OLD_PIN && test $n -ge 0
do
printf '.' && sleep 1 && n=$(( $n - 1 ))
done
echo
if test $n -lt 0 && test -s $OLD_PIN
then
echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds"
exit 1
fi
exit 0
fi
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
run "$CMD"
;;
reopen-logs)
sig USR1
;;
*)
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
exit 1
;;
esac
# sudo ln -nfs config/unicorn_init.sh /etc/init.d/unicorn_gxserver
# chmod a+x /etc/init.d/unicorn_gxserver
# /etc/init.d/unicorn_guanxime_www restart
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment