capistrano-runit 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/README.markdown ADDED
@@ -0,0 +1 @@
1
+ TODO: Write README!
@@ -0,0 +1,12 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "capistrano-runit"
3
+ s.version = "1.0.0"
4
+ s.summary = "Useful deployment recipes."
5
+ s.homepage = "http://github.com/antage/capistrano-runit"
6
+ s.author = "Anton Ageev"
7
+ s.email = "antage@gmail.com"
8
+ s.files = `git ls-files`.split
9
+ s.add_dependency "capistrano", ">= 2.0.0"
10
+ end
11
+
12
+ # vim:ts=2 sw=2 ft=ruby
@@ -0,0 +1,13 @@
1
+ Capistrano::Configuration.instance(true).load do
2
+ _cset :runit_dir, defer { "#{deploy_to}/runit" }
3
+
4
+ namespace :runit do
5
+ desc "Setup runit directories"
6
+ task :setup, :roles => :app do
7
+ run "[ -d #{runit_dir}/.env ] || mkdir -p #{runit_dir}/.env"
8
+ run "echo $HOME > #{runit_dir}/.env/HOME"
9
+ run "[ -d #{runit_dir}/available ] || mkdir -p #{runit_dir}/available"
10
+ run "[ -d #{runit_dir}/enabled ] || mkdir -p #{runit_dir}/enabled"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,36 @@
1
+ Capistrano::Configuration.instance(true).load do
2
+ _cset :runit_delayed_job_service_name, "delayed_job"
3
+ _cset :runit_delayed_job_template, File.expand_path(File.join(File.dirname(__FILE__), "../templates/run-delayed_job.erb"))
4
+ _cset :runit_delayed_job_command, "./script/delayed_job"
5
+
6
+ namespace :runit do
7
+ namespace :delayed_job do
8
+ desc "Setup delayed_job runit-service"
9
+ task :setup, :roles => :app do
10
+ run "[ -d #{runit_dir}/available/#{runit_delayed_job_service_name} ] || mkdir -p #{runit_dir}/available/#{runit_delayed_job_service_name}"
11
+ template = File.read(runit_delayed_job_template)
12
+ erb_template = ERB.new(template)
13
+ servers = find_servers_for_task(current_task)
14
+ servers.each do |server|
15
+ put erb_template.result(binding), "#{runit_dir}/available/#{runit_delayed_job_service_name}/run", :mode => 0755, :hosts => server.host
16
+ end
17
+ find_and_execute_task "runit:delayed_job:enable"
18
+ end
19
+
20
+ desc "Enable delayed_job runit-service"
21
+ task :enable, :roles => :app do
22
+ run "cd #{runit_dir}/enabled && [ -h ./#{runit_delayed_job_service_name} ] || ln -sf ../available/#{runit_delayed_job_service_name} ."
23
+ end
24
+
25
+ desc "Disable delayed_job runit-service"
26
+ task :disable, :roles => :app do
27
+ run "[ ! -h #{runit_dir}/enabled/#{runit_delayed_job_service_name} ] || sv stop #{runit_dir}/enabled/#{runit_delayed_job_service_name}/ && rm -f #{runit_dir}/enabled/#{runit_delayed_job_service_name}"
28
+ end
29
+
30
+ desc "Restart delayed_job runit-service"
31
+ task :restart, :roles => :app do
32
+ run "[ ! -h #{runit_dir}/enabled/#{runit_delayed_job_service_name} ] || sv restart #{runit_dir}/enabled/#{runit_delayed_job_service_name}/"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,58 @@
1
+ Capistrano::Configuration.instance(true).load do
2
+ _cset :runit_unicorn_service_name, "unicorn"
3
+ _cset :runit_unicorn_template, File.expand_path(File.join(File.dirname(__FILE__), "../templates/run-unicorn.erb"))
4
+ _cset :runit_unicorn_command, "unicorn"
5
+ _cset :runit_unicorn_workers, 4
6
+ _cset :runit_unicorn_listen, "127.0.0.1"
7
+ _cset :runit_unicorn_port, 8080
8
+ _cset :runit_unicorn_after_fork_code, ""
9
+
10
+ namespace :runit do
11
+ namespace :unicorn do
12
+ desc "Setup Unicorn runit-service"
13
+ task :setup, :roles => :app do
14
+ run "[ -d #{runit_dir}/available/#{runit_unicorn_service_name} ] || mkdir -p #{runit_dir}/available/#{runit_unicorn_service_name}"
15
+ template = File.read(runit_unicorn_template)
16
+ erb_template = ERB.new(template)
17
+ servers = find_servers_for_task(current_task)
18
+ servers.each do |server|
19
+ runit_unicorn_listen_current =
20
+ if runit_unicorn_listen.is_a?(Hash)
21
+ runit_unicorn_listen[server.host]
22
+ else
23
+ runit_unicorn_listen
24
+ end
25
+ runit_unicorn_port_current =
26
+ if runit_unicorn_port.is_a?(Hash)
27
+ runit_unicorn_port[server.host]
28
+ else
29
+ runit_unicorn_port
30
+ end
31
+ runit_unicorn_workers_current =
32
+ if runit_unicorn_workers.is_a?(Hash)
33
+ runit_unicorn_workers[server.host]
34
+ else
35
+ runit_unicorn_workers
36
+ end
37
+ put erb_template.result(binding), "#{runit_dir}/available/#{runit_unicorn_service_name}/run", :mode => 0755, :hosts => server.host
38
+ end
39
+ find_and_execute_task "runit:unicorn:enable"
40
+ end
41
+
42
+ desc "Enable Unicorn runit-service"
43
+ task :enable, :roles => :app do
44
+ run "cd #{runit_dir}/enabled && [ -h ./#{runit_unicorn_service_name} ] || ln -sf ../available/#{runit_unicorn_service_name} ."
45
+ end
46
+
47
+ desc "Enable Unicorn runit-service"
48
+ task :disable, :roles => :app do
49
+ run "[ ! -h #{runit_dir}/enabled/#{runit_unicorn_service_name} ] || sv stop #{runit_dir}/enabled/#{runit_unicorn_service_name}/ && rm -f #{runit_dir}/enabled/#{runit_unicorn_service_name}"
50
+ end
51
+
52
+ desc "Restart Unicorn runit-service"
53
+ task :restart, :roles => :app do
54
+ run "[ ! -h #{runit_dir}/enabled/#{runit_unicorn_service_name} ] || sv restart #{runit_dir}/enabled/#{runit_unicorn_service_name}/"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ require "capistrano-runit/recipes/base"
2
+ require "capistrano-runit/recipes/unicorn"
3
+ require "capistrano-runit/recipes/delayed_job"
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ cd <%= current_path %>
3
+ <%= runit_delayed_job_command %> run
@@ -0,0 +1,157 @@
1
+ #!/bin/bash -e
2
+
3
+ #
4
+ # Supervises unicorn; stopping this service prompts a graceful shutdown of the
5
+ # current unicorn instance. Sending HUP to this service causes unicorn to re-exec
6
+ # itself for upgrades etc.
7
+ #
8
+
9
+ ADDR=<%= runit_unicorn_listen_current %>
10
+ PORT=<%= runit_unicorn_port_current %>
11
+ APP_DIR="<%= current_path %>"
12
+ THIS_DIR=$(pwd)
13
+ CUR_PID_FILE=$APP_DIR/tmp/pids/unicorn.pid
14
+ OLD_PID_FILE=$CUR_PID_FILE.oldbin
15
+
16
+
17
+ if [ ! -d "$APP_DIR" ]; then
18
+ echo "no such app dir: $APP_DIR" 1>&2;
19
+ exit 2
20
+ fi
21
+
22
+ cat <<EOF > unicorn.rb
23
+ working_directory "$APP_DIR"
24
+ pid "$CUR_PID_FILE"
25
+
26
+ worker_processes <%= runit_unicorn_workers_current %>
27
+
28
+ preload_app true
29
+
30
+ # Restart any workers that haven't responded in 30 seconds
31
+ timeout 60
32
+
33
+ # listen on both a Unix domain socket and a TCP port,
34
+ #listen '$THIS_DIR/socket', :backlog => 64
35
+ listen '$ADDR:$PORT', :tcp_nopush => true
36
+
37
+ stderr_path "log/unicorn.stderr.log"
38
+ stdout_path "log/unicorn.stdout.log"
39
+
40
+ # http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
41
+ if GC.respond_to?(:copy_on_write_friendly=)
42
+ GC.copy_on_write_friendly = true
43
+ end
44
+
45
+
46
+ before_fork do |server, worker|
47
+ # the following is highly recomended for Rails + "preload_app true"
48
+ # as there's no need for the master process to hold a connection
49
+ if defined?(::ActiveRecord::Base)
50
+ ::ActiveRecord::Base.connection.disconnect!
51
+ end
52
+
53
+ ##
54
+ # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
55
+ # immediately start loading up a new version of itself (loaded with a new
56
+ # version of our app). When this new Unicorn is completely loaded
57
+ # it will begin spawning workers. The first worker spawned will check to
58
+ # see if an .oldbin pidfile exists. If so, this means we've just booted up
59
+ # a new Unicorn and need to tell the old one that it can now die. To do so
60
+ # we send it a QUIT.
61
+ #
62
+ # Using this method we get 0 downtime deploys.
63
+
64
+ old_pid = "$APP_DIR/tmp/pids/unicorn.pid.oldbin"
65
+ if File.exists?(old_pid) && server.pid != old_pid
66
+ begin
67
+ puts "Shutting down old process"
68
+ Process.kill("QUIT", File.read(old_pid).to_i)
69
+ rescue Errno::ENOENT, Errno::ESRCH
70
+ # someone else did our job for us
71
+ end
72
+ end
73
+ end
74
+
75
+
76
+ after_fork do |server, worker|
77
+ ##
78
+ # Unicorn master loads the app then forks off workers - because of the way
79
+ # Unix forking works, we need to make sure we aren't using any of the parent's
80
+ # sockets, e.g. db connection
81
+
82
+ if defined?(::ActiveRecord::Base)
83
+ ::ActiveRecord::Base.establish_connection
84
+ end
85
+
86
+ # Redis and Memcached would go here but their connections are established
87
+ # on demand, so the master never opens a socket
88
+ <% unless fetch(:runit_unicorn_after_fork_code, nil).nil? %>
89
+ <%= runit_unicorn_after_fork_code %>
90
+ <% end %>
91
+ end
92
+ EOF
93
+
94
+ function is_pid_running() {
95
+ set +e
96
+ if [ -n $1 ] && kill -0 $1 >/dev/null 2>&1; then
97
+ echo "yes"
98
+ fi
99
+ set -e
100
+ }
101
+
102
+ echo "My pid: $$"
103
+
104
+ if [ -e $OLD_PID_FILE ]; then
105
+ OLD_PID=$(cat $OLD_PID_FILE)
106
+ echo "Unicorn appears to be restarting: waiting for old master ($OLD_PID) to exit"
107
+ while [ -n "$(is_pid_running $OLD_PID)" ]; do
108
+ /bin/echo -n '.'
109
+ sleep 2
110
+ done
111
+ fi
112
+
113
+ if [ -e $CUR_PID_FILE ]; then
114
+ CUR_PID=$(cat $CUR_PID_FILE)
115
+ if [ -n "$(is_pid_running $CUR_PID)" ]; then
116
+ echo "Already running as $CUR_PID"
117
+ RUNNING=true
118
+ fi
119
+ fi
120
+
121
+ if [ ! $RUNNING ]; then
122
+ echo "Starting unicorn"
123
+ old=$(pwd)
124
+ cd $APP_DIR
125
+ <%= runit_unicorn_command %> -E production -c $THIS_DIR/unicorn.rb -D
126
+ cd $old
127
+ sleep 2
128
+ CUR_PID=$(cat $CUR_PID_FILE)
129
+ fi
130
+
131
+ function restart() {
132
+ # TODO: regenerate config if this file has changed
133
+
134
+ # Tell unicorn to re-exec itself
135
+ echo "Asking unicorn to re-exec itself with USR2"
136
+ kill -USR2 $CUR_PID
137
+ # Wait and then exit -- after runit restarts the script, we'll
138
+ # wait for the re-exec'd process
139
+ sleep 2
140
+ echo "Restarting to supervise new unicorn"
141
+ exit
142
+ }
143
+
144
+ function graceful_shutdown() {
145
+ echo "Requesting graceful shutdown"
146
+ kill -QUIT $CUR_PID
147
+ }
148
+
149
+ trap restart HUP QUIT
150
+ trap graceful_shutdown INT TERM
151
+
152
+ echo "Watching for unicorn ($CUR_PID) exiting"
153
+ while [ -n "$(is_pid_running $CUR_PID)" ]; do
154
+ /bin/echo -n '.'
155
+ sleep 2
156
+ done
157
+ echo "Unicorn has exited."
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-runit
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Anton Ageev
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-15 00:00:00 +04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: capistrano
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 2
32
+ - 0
33
+ - 0
34
+ version: 2.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description:
38
+ email: antage@gmail.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - .gitignore
47
+ - Gemfile
48
+ - README.markdown
49
+ - capistrano-runit.gemspec
50
+ - lib/capistrano-runit/recipes.rb
51
+ - lib/capistrano-runit/recipes/base.rb
52
+ - lib/capistrano-runit/recipes/delayed_job.rb
53
+ - lib/capistrano-runit/recipes/unicorn.rb
54
+ - lib/capistrano-runit/templates/run-delayed_job.erb
55
+ - lib/capistrano-runit/templates/run-unicorn.erb
56
+ has_rdoc: true
57
+ homepage: http://github.com/antage/capistrano-runit
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options: []
62
+
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ hash: 3
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.6.2
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Useful deployment recipes.
90
+ test_files: []
91
+