capistrano-runit-tasks 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +171 -0
- data/lib/capistrano-runit-tasks.rb +64 -0
- data/lib/runit_runner_helper.rb +32 -0
- metadata +56 -0
data/README
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
= Capistrano runit tasks
|
2
|
+
|
3
|
+
Adds tasks to Capistrano for use with the runit supervision scheme.
|
4
|
+
|
5
|
+
This library extends Capistrano to allow processes to be supervised using the
|
6
|
+
runit package. It replaces some of the standard tasks with runit versions and
|
7
|
+
includes tasks and helpers to create the service directory layout and populate
|
8
|
+
it with run scripts. It currently only supports fcgi listeners, but tries to
|
9
|
+
make it easy to add other services in your deploy.rb.
|
10
|
+
|
11
|
+
== Status
|
12
|
+
|
13
|
+
capistrano-runit-tests 0.1.0 (known as cap-runit from now on) is the first
|
14
|
+
release of the library. It will need more work to be useful to everybody who
|
15
|
+
uses runit. The intention of releasing it now is to find out which areas need
|
16
|
+
improvement first and get working on them. It's was developed and tested with
|
17
|
+
the Debian sarge version of runit, 1.0.5 so currently uses runsvctrl rather
|
18
|
+
than sv.
|
19
|
+
|
20
|
+
The current version assumes you have a runit setup similar to the one created
|
21
|
+
in http://www.defendem.com/read/chapter/5#page6, i.e. a supervised directory
|
22
|
+
where links can be created to get tasks monitored.
|
23
|
+
|
24
|
+
== Quick Start
|
25
|
+
|
26
|
+
This assumes you're creating a fresh install, not migrating an app from
|
27
|
+
spinner/spawner/reaper.
|
28
|
+
|
29
|
+
Install the package via gems or .tgz / .zip and setup.rb.
|
30
|
+
|
31
|
+
Include it in your deploy.rb with:
|
32
|
+
|
33
|
+
require 'capistrano-runit-tasks'
|
34
|
+
|
35
|
+
Then run:
|
36
|
+
|
37
|
+
* cap setup
|
38
|
+
* cap cold_deploy
|
39
|
+
|
40
|
+
This sets up one fcgi listener on port 8000. Make sure your database is setup
|
41
|
+
and point your webserver at the new listener.
|
42
|
+
|
43
|
+
== Usage
|
44
|
+
|
45
|
+
When you require 'runit-tasks' it replaces the following cap tasks with runit
|
46
|
+
versions:
|
47
|
+
|
48
|
+
* cold_deploy
|
49
|
+
* restart
|
50
|
+
* spinner
|
51
|
+
|
52
|
+
Then adds the following tasks, helpers and variables:
|
53
|
+
|
54
|
+
=== Tasks
|
55
|
+
|
56
|
+
[setup_service_dirs] Creates the skeleton directory structure for the services
|
57
|
+
|
58
|
+
[after_setup] Calls setup_service_dirs so they're created as part of
|
59
|
+
the standard cap setup
|
60
|
+
|
61
|
+
=== Variables
|
62
|
+
|
63
|
+
[service_dir] Change this if you want to change the name
|
64
|
+
of the service directory in the app on the server(s).
|
65
|
+
(Default: service)
|
66
|
+
|
67
|
+
[master_service_dir] Supervised directory where cap-runit will link the
|
68
|
+
service directories to to start the service.
|
69
|
+
(Default: ~/services)
|
70
|
+
|
71
|
+
[fcgi_count] Number of fcgi listener service dirs to create.
|
72
|
+
(Default: 1)
|
73
|
+
|
74
|
+
[fcgi_listener_base_port] The base port number to use for the fcgi listeners.
|
75
|
+
(Default: 8000)
|
76
|
+
|
77
|
+
cap-runit creates a directory for each listener you ask for. At the moment the
|
78
|
+
directories are created by setup_service_dirs. Later versions should allow for
|
79
|
+
dynamic creation / deletion.
|
80
|
+
|
81
|
+
The directories are named after the port number the fcgi listener will run on.
|
82
|
+
If you specified 8500 for the base port and 3 for the fcgi_count then
|
83
|
+
service/8500, service/8501 and service/8502 directories will be created and
|
84
|
+
populated with run scripts that launch the fcgis on the corresponding port.
|
85
|
+
|
86
|
+
When the service directories are linked into the master service dir to run,
|
87
|
+
they are named <application>-<port number>. So if :application is set to "foo"
|
88
|
+
in deploy.rb you'll get foo-8500, foo-8501 etc.
|
89
|
+
|
90
|
+
=== Helpers
|
91
|
+
|
92
|
+
[each_fcgi_listener] Uses the values for fcgi_listener_base_port and
|
93
|
+
fcgi_count to yield each of the fcgi port numbers back to
|
94
|
+
the calling block
|
95
|
+
|
96
|
+
[runner.create] Creates runner scripts, see the rdoc or comments above
|
97
|
+
the method for how it's used.
|
98
|
+
|
99
|
+
== Logging
|
100
|
+
|
101
|
+
The default tasks create a log directory under each service directory. For
|
102
|
+
your own services, this has do be done manually for now. The intention
|
103
|
+
is to make it automatic and then allow the generic template to be overridden
|
104
|
+
easily.
|
105
|
+
|
106
|
+
== Adding your own services
|
107
|
+
|
108
|
+
To add your own service directories and run scripts, add
|
109
|
+
after_setup_service_dirs, after_spinner and after_restart tasks to your
|
110
|
+
deploy.rb that look something like these:
|
111
|
+
|
112
|
+
task :after_setup_service_dirs do
|
113
|
+
puts 'Creating mailer service directory'
|
114
|
+
mailer_service_dir = "#{deploy_to}/#{service_dir}/mailer"
|
115
|
+
run "mkdir -p #{mailer_service_dir}/log/main"
|
116
|
+
|
117
|
+
mailer_run_template = <<-TEMPLATE
|
118
|
+
#!/bin/sh -e
|
119
|
+
export RAILS_ENV=production
|
120
|
+
exec 2>&1 /usr/bin/env ruby <%= application_dir %>/current/script/mailer
|
121
|
+
TEMPLATE
|
122
|
+
|
123
|
+
runner.create :runner, mailer_service_dir,
|
124
|
+
mailer_run_template, :application_dir => deploy_to
|
125
|
+
runner.create :log, mailer_service_dir
|
126
|
+
end
|
127
|
+
|
128
|
+
task :after_spinner do
|
129
|
+
mailer_service_dir = "#{deploy_to}/#{service_dir}/mailer"
|
130
|
+
run "ln -sf #{mailer_service_dir} #{master_service_dir}/#{application}-mailer"
|
131
|
+
end
|
132
|
+
|
133
|
+
task :after_restart do
|
134
|
+
mailer_service_dir = "#{deploy_to}/#{service_dir}/mailer"
|
135
|
+
run "runsvctrl down #{mailer_service_dir}"
|
136
|
+
run "runsvctrl up #{mailer_service_dir}"
|
137
|
+
end
|
138
|
+
|
139
|
+
So the process is:
|
140
|
+
|
141
|
+
* make the service directory
|
142
|
+
* create a rhtml template for your runner (string only for now, sorry)
|
143
|
+
* create a runner from the template
|
144
|
+
* create the logger
|
145
|
+
|
146
|
+
This is will be wrapped in a helper function at the earliest opportunity.
|
147
|
+
|
148
|
+
== Switching from spinner/spawner/reaper
|
149
|
+
|
150
|
+
This again should be automated, the manual steps I used were:
|
151
|
+
|
152
|
+
* Modify deploy.rb and do a test deploy to a new directory on a different port
|
153
|
+
* Check the deploy worked ok
|
154
|
+
* Revert deploy.rb
|
155
|
+
* cap setup_service_dirs to create the structure (Won't touch what's running)
|
156
|
+
* Kill the spinner process
|
157
|
+
* use script/process/reaper to kill the running fcgis
|
158
|
+
* cap cold_deploy to start the service
|
159
|
+
* Check everything is running OK
|
160
|
+
|
161
|
+
== TODO
|
162
|
+
|
163
|
+
* Make runner.create use file based templates
|
164
|
+
* Intead of run "runsvctrl ..." have an sv helper method like sv :up, svc_dir
|
165
|
+
* Setting for sv program to use, runsvctrl or sv
|
166
|
+
* Automatically create log directories with custom templates
|
167
|
+
* add_service(path, runner, logger = nil) helper function
|
168
|
+
e.g. add_service(path, {:template => 'my_runner', :port => 1234})
|
169
|
+
Which would set a custom runner and a standard logger
|
170
|
+
* Allow add_service to create more than one directory to be supervised
|
171
|
+
* Add task to automate switching from spinner
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'runit_runner_helper'
|
2
|
+
|
3
|
+
Capistrano.configuration(:must_exist).load do
|
4
|
+
set :service_dir, 'service'
|
5
|
+
set :fcgi_count, 1
|
6
|
+
set :master_service_dir, '~/services'
|
7
|
+
set :fcgi_listener_base_port, 8000
|
8
|
+
|
9
|
+
# We need our own task for this as the default cold_deploy
|
10
|
+
# calls restart, which won't work until we've setup the
|
11
|
+
# symlink, perhaps we could add a test to restart to check if the
|
12
|
+
# link exists, but that's beyond my current (very bad) shell-foo
|
13
|
+
desc "Used only for deploying when the services haven't been setup"
|
14
|
+
task :cold_deploy do
|
15
|
+
transaction do
|
16
|
+
update_code
|
17
|
+
symlink
|
18
|
+
end
|
19
|
+
spinner
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Sets up services directories for supervising fcgi using runit"
|
23
|
+
task :setup_service_dirs do
|
24
|
+
puts 'Creating service directories'
|
25
|
+
application_service_dir = "#{deploy_to}/#{service_dir}"
|
26
|
+
run "mkdir -p #{application_service_dir}"
|
27
|
+
|
28
|
+
each_fcgi_listener do |fcgi_listener_port|
|
29
|
+
fcgi_service_dir = "#{application_service_dir}/#{fcgi_listener_port}"
|
30
|
+
run "mkdir -p #{fcgi_service_dir}/log/main"
|
31
|
+
runner.create :runner, fcgi_service_dir, :fcgi, :application_dir => deploy_to, :fcgi_port => fcgi_listener_port
|
32
|
+
runner.create :log, fcgi_service_dir
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "Links created service dir into master service dir so runit starts the fcgi"
|
37
|
+
task :spinner do
|
38
|
+
each_fcgi_listener do |fcgi_listener_port|
|
39
|
+
fcgi_service_dir = "#{deploy_to}/#{service_dir}/#{fcgi_listener_port}"
|
40
|
+
run "ln -sf #{fcgi_service_dir} #{master_service_dir}/#{application}-#{fcgi_listener_port}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "restart task for runit supervised fcgis"
|
45
|
+
task :restart do
|
46
|
+
each_fcgi_listener do |fcgi_listener_port|
|
47
|
+
fcgi_service_dir = "#{deploy_to}/#{service_dir}/#{fcgi_listener_port}"
|
48
|
+
|
49
|
+
# Signal USR2 is what reaper does
|
50
|
+
run "runsvctrl 2 #{fcgi_service_dir}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "Hook into after setup to create the runit service directory"
|
55
|
+
task :after_setup do
|
56
|
+
setup_service_dirs
|
57
|
+
end
|
58
|
+
|
59
|
+
def each_fcgi_listener
|
60
|
+
fcgi_listener_base_port.upto(fcgi_listener_base_port + fcgi_count - 1) do |fcgi_listener_port|
|
61
|
+
yield fcgi_listener_port
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'capistrano'
|
2
|
+
|
3
|
+
module RunitRunnerHelper
|
4
|
+
FCGI_TEMPLATE = <<-TEMPLATE
|
5
|
+
#!/bin/sh -e
|
6
|
+
export RAILS_ENV=production
|
7
|
+
exec 2>&1 /usr/bin/env spawn-fcgi -n -f <%= application_dir %>/current/public/dispatch.fcgi -p <%= fcgi_port %>
|
8
|
+
TEMPLATE
|
9
|
+
|
10
|
+
LOG_TEMPLATE = <<-TEMPLATE
|
11
|
+
#!/bin/sh -e
|
12
|
+
exec svlogd -t ./main
|
13
|
+
TEMPLATE
|
14
|
+
|
15
|
+
# Wrapper to render a file from a string template (file template not supported yet)
|
16
|
+
# and put it on the server at the given path. The file permissions are set to 0700.
|
17
|
+
# options are passed through to the call to render.
|
18
|
+
# runner_type can be :log or :runner
|
19
|
+
def create(runner_type, path, template = nil, options = {})
|
20
|
+
runner_path = "#{path}#{runner_type == :log ? '/log/run' : '/run'}"
|
21
|
+
case runner_type
|
22
|
+
when :log
|
23
|
+
template = LOG_TEMPLATE
|
24
|
+
else
|
25
|
+
template = FCGI_TEMPLATE if template == :fcgi
|
26
|
+
end
|
27
|
+
|
28
|
+
put render(options.merge(:template => template)), runner_path, :mode => 0700
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Capistrano.plugin :runner, RunitRunnerHelper
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: capistrano-runit-tasks
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2006-03-18 00:00:00 +00:00
|
8
|
+
summary: Adds tasks to capistrano for use with the runit supervision scheme.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: chris@octopod.info
|
12
|
+
homepage: http://cappy-runit.rubyforge.org
|
13
|
+
rubyforge_project: cappy-runit
|
14
|
+
description:
|
15
|
+
autorequire: capistrano-runit-tasks
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
29
|
+
authors:
|
30
|
+
- Chris McGrath
|
31
|
+
files:
|
32
|
+
- lib/capistrano-runit-tasks.rb
|
33
|
+
- lib/runit_runner_helper.rb
|
34
|
+
- README
|
35
|
+
test_files: []
|
36
|
+
rdoc_options:
|
37
|
+
- "--title"
|
38
|
+
- Capistrano runit tasks documentation
|
39
|
+
- "--main"
|
40
|
+
- README
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
requirements: []
|
46
|
+
dependencies:
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: capistrano
|
49
|
+
version_requirement:
|
50
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
51
|
+
requirements:
|
52
|
+
-
|
53
|
+
- ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.1.0
|
56
|
+
version:
|