449 lines
15 KiB
Markdown
449 lines
15 KiB
Markdown
|
Description
|
||
|
===========
|
||
|
|
||
|
Installs runit and provides the `runit_service` service resource for
|
||
|
managing processes (services) under runit.
|
||
|
|
||
|
This cookbook does not use runit to replace system init, nor are there
|
||
|
plans to do so.
|
||
|
|
||
|
For more information about runit:
|
||
|
|
||
|
* http://smarden.org/runit/
|
||
|
|
||
|
About Runit
|
||
|
===========
|
||
|
|
||
|
In brief, Runit is a process supervision suite. It is simple to set
|
||
|
up, and doesn't require complex shell scripts to be written to start
|
||
|
processes running as system services.
|
||
|
|
||
|
To manage a process in runit, create a "service" directory that
|
||
|
contains a "`run`" script. In this cookbook we refer to that directory
|
||
|
as the `sv_dir` (see __Attributes__ and __Resource/Provider__). That
|
||
|
service directory is symbolically linked into runit's own service
|
||
|
directory where its `runsvdir` program looks for processes to manage.
|
||
|
See the [runit documentation](http://smarden.org/runit/) for detailed
|
||
|
information on runit.
|
||
|
|
||
|
Supervised processes are analogous to services under other systems
|
||
|
such as sysvinit or upstart.
|
||
|
|
||
|
Requirements
|
||
|
============
|
||
|
|
||
|
## Platform:
|
||
|
|
||
|
* Debian/Ubuntu
|
||
|
* Gentoo
|
||
|
* RHEL
|
||
|
|
||
|
Attributes
|
||
|
==========
|
||
|
|
||
|
See `attributes/default.rb` for defaults generated per platform.
|
||
|
|
||
|
* `node['runit']['sv_bin']` - Full path to the `sv` binary.
|
||
|
* `node['runit']['chpst_bin']` - Full path to the `chpst` binary.
|
||
|
* `node['runit']['service_dir']` - Full path to the default "services"
|
||
|
directory where enabled services are linked.
|
||
|
* `node['runit']['sv_dir']` - Full path to the directory where
|
||
|
service lives, which gets linked to `service_dir`.
|
||
|
* `node['runit']['start']` - Command to start the runsvdir service
|
||
|
* `node['runit']['stop]` - Command to stop the runsvdir service
|
||
|
* `node['runit']['reload']` - Command to reload the runsvdir service
|
||
|
|
||
|
Recipes
|
||
|
=======
|
||
|
|
||
|
default
|
||
|
-------
|
||
|
|
||
|
The default recipe installs runit and starts `runsvdir` to supervise
|
||
|
the services in runit's service directory (e.g., `/etc/service`).
|
||
|
|
||
|
On RHEL family systems, it will build the runit RPM using [Ian Meyer's
|
||
|
runit RPM SPEC](https://github.com/imeyer/runit-rpm).
|
||
|
|
||
|
On Debian family systems, the runit packages are maintained by the
|
||
|
runit author, Gerrit Pape, and the recipe will use that for
|
||
|
installation.
|
||
|
|
||
|
On Gentoo, the runit ebuild package is installed.
|
||
|
|
||
|
Resource/Provider
|
||
|
=================
|
||
|
|
||
|
This cookbook has a resource, `runit_service`, for managing services
|
||
|
under runit. This service subclasses the Chef `service` resource.
|
||
|
|
||
|
**This resource replaces the runit_service definition. See the
|
||
|
CHANGELOG.md file in this cookbook for breaking change information
|
||
|
and any actions you may need to take to update cookbooks using
|
||
|
runit_service.**
|
||
|
|
||
|
## Actions:
|
||
|
|
||
|
- **enable** - enables the service, creating the required run scripts
|
||
|
and symlinks. This is the default action.
|
||
|
- **start** - starts the service with `sv start`
|
||
|
- **stop** - stops the service with `sv stop`
|
||
|
- **disable** - stops the service with `sv down` and removes the service symlink
|
||
|
- **restart** - restarts the service with `sv restart`
|
||
|
- **reload** - reloads the service with `sv force-reload`
|
||
|
- **once** - starts the service with `sv once`.
|
||
|
- **hup** - sends the `HUP` signal to the service with `sv hup`
|
||
|
- **cont** - sends the `CONT` signal to the service
|
||
|
- **term** - sends the `TERM` signal to the service
|
||
|
- **kill** - sends the `KILL` signal to the service
|
||
|
- **up** - starts the service with `sv up`
|
||
|
- **down** - downs the service with `sv down`
|
||
|
- **usr1** - sends the `USR1` signal to the service with `sv 1`
|
||
|
- **usr2** - sends the `USR2` signal to the service with `sv 2`
|
||
|
|
||
|
Service management actions are taken with runit's "`sv`" program.
|
||
|
|
||
|
Read the `sv(8)` [man page](http://smarden.org/runit/sv.8.html) for
|
||
|
more information on the `sv` program.
|
||
|
|
||
|
## Parameter Attributes
|
||
|
|
||
|
The first three parameters, `sv_dir`, `service_dir`, and `sv_bin` will
|
||
|
attempt to use the corresponding node attributes, and fall back to
|
||
|
hardcoded default values that match the settings used on Debian
|
||
|
platform systems.
|
||
|
|
||
|
Many of these parameters are only used in the `:enable` action.
|
||
|
|
||
|
- **sv_dir** - The base "service directory" for the services managed by
|
||
|
the resource. By default, this will attempt to use the
|
||
|
`node['runit']['sv_dir']` attribute, and falls back to `/etc/sv`.
|
||
|
- **service_dir** - The directory where services are symlinked to be
|
||
|
supervised by `runsvdir`. By default, this will attempt to use the
|
||
|
`node['runit']['service_dir']` attribute, and falls back to
|
||
|
`/etc/service`.
|
||
|
- **sv_bin** - The path to the `sv` program binary. This will attempt
|
||
|
to use the `node['runit']['sv_bin']` attribute, and falls back to
|
||
|
`/usr/bin/sv`.
|
||
|
- **service_name** - *Name attribute*. The name of the service. This
|
||
|
will be used in the directory of the managed service in the
|
||
|
`sv_dir` and `service_dir`.
|
||
|
- **sv_templates** - If true, the `:enable` action will create the
|
||
|
service directory with the appropriate templates. Default is
|
||
|
`true`. Set this to `false` if the service has a package that
|
||
|
provides its own service directory. See __Usage__ examples.
|
||
|
- **options** - Options passed as variables to templates, for
|
||
|
compatibility with legacy runit service definition. Default is an
|
||
|
empty hash.
|
||
|
- **env** - A hash of environment variables with their values as content
|
||
|
used in the service's `env` directory. Default is an empty hash.
|
||
|
- **log** - Whether to start the service's logger with svlogd, requires
|
||
|
a template `sv-service_name-log-run.erb` to configure the log's run
|
||
|
script. Default is true.
|
||
|
- **default_logger** - Whether a default `log/run` script should be set
|
||
|
up. If true, the default content of the run script will use
|
||
|
`svlogd` to write logs to `/var/log/service_name`. Default is false.
|
||
|
- **cookbook** - A cookbook where templates are located instead of
|
||
|
where the resource is used. Applies for all the templates in the
|
||
|
`enable` action.
|
||
|
- **finish** - whether the service has a finish script, requires a
|
||
|
template `sv-service_name-finish.erb`
|
||
|
- **control** - An array of signals to customize control of the service,
|
||
|
see [runsv man page](http://smarden.org/runit/runsv.8.html) on how
|
||
|
to use this. This requires that each template be created with the
|
||
|
name `sv-service_name-signal.erb`.
|
||
|
- **owner** - user that should own the templates created to enable the
|
||
|
service
|
||
|
- **group** - group that should own the templates created to enable the
|
||
|
service
|
||
|
- **run_template_name** - alternate filename of the run run script to
|
||
|
use replacing `service_name`.
|
||
|
- **log_template_name** - alternate filename of the log run script to
|
||
|
use replacing `service_name`.
|
||
|
- **finish_script_template_name** - alternate filename of the finish
|
||
|
script to use, replacing `service_name`.
|
||
|
- **control_template_names** - a hash of control signals (see *control*
|
||
|
above) and their alternate template name(s) replacing
|
||
|
`service_name`.
|
||
|
- **status_command** - The command used to check the status of the
|
||
|
service to see if it is enabled/running (if it's running, it's
|
||
|
enabled). This hardcodes the location of the sv program to
|
||
|
`/usr/bin/sv` due to the aforementioned cookbook load order.
|
||
|
- **restart_on_update** - Whether the service should be restarted when
|
||
|
the run script is updated. Defaults to `true`. Set to `false` if
|
||
|
the service shouldn't be restarted when the run script is updated.
|
||
|
|
||
|
Unlike previous versions of the cookbook using the `runit_service`
|
||
|
definition, the `runit_service` resource can be notified. See
|
||
|
__Usage__ examples below.
|
||
|
|
||
|
Usage
|
||
|
=====
|
||
|
|
||
|
To get runit installed on supported platforms, use `recipe[runit]`.
|
||
|
Once it is installed, use the `runit_service` resource to set up
|
||
|
services to be managed by runit.
|
||
|
|
||
|
In order to use the `runit_service` resource in your cookbook(s), each
|
||
|
service managed will also need to have `sv-service_name-run.erb` and
|
||
|
`sv-service_name-log-run.erb` templates created. If the `log`
|
||
|
parameter is false, the log run script isn't created. If the `log`
|
||
|
parameter is true, and `default_logger` is also true, the log run
|
||
|
script will be created with the default content:
|
||
|
|
||
|
#!/bin/sh
|
||
|
exec svlogd -tt /var/log/service_name
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
|
||
|
These are example use cases of the `runit_service` resource described
|
||
|
above. There are others in the `runit_test` cookbook that is included
|
||
|
in the [git repository](https://github.com/opscode-cookbooks/runit).
|
||
|
|
||
|
**Default Example**
|
||
|
|
||
|
This example uses all the defaults in the `:enable` action to set up
|
||
|
the service.
|
||
|
|
||
|
We'll set up `chef-client` to run as a service under runit, such as is
|
||
|
done in the `chef-client` cookbook. This example will be more simple
|
||
|
than in that cookbook. First, create the required run template,
|
||
|
`chef-client/templates/default/sv-chef-client-run.erb`.
|
||
|
|
||
|
#!/bin/sh
|
||
|
exec 2>&1
|
||
|
exec /usr/bin/env chef-client -i 1800 -s 30
|
||
|
|
||
|
Then create the required log/run template,
|
||
|
`chef-client/templates/default/sv-chef-client-log-run.erb`.
|
||
|
|
||
|
#!/bin/sh
|
||
|
exec svlogd -tt ./main
|
||
|
|
||
|
__Note__ This will cause output of the running process to go to
|
||
|
`/etc/sv/chef-client/log/main/current`. Some people may not like this,
|
||
|
see the following example. This is preserved for compatibility reasons.
|
||
|
|
||
|
Finally, set up the service in the recipe with:
|
||
|
|
||
|
runit_service "chef-client"
|
||
|
|
||
|
**Default Logger Example**
|
||
|
|
||
|
To use a default logger with svlogd which will log to
|
||
|
`/var/log/chef-client/current`, instead, use the `default_logger` option.
|
||
|
|
||
|
runit_service "chef-client" do
|
||
|
default_logger true
|
||
|
end
|
||
|
|
||
|
**No Log Service**
|
||
|
|
||
|
If there isn't an appendant log service, set `log` to false, and the
|
||
|
log/run script won't be created.
|
||
|
|
||
|
runit_service "no-svlog" do
|
||
|
log false
|
||
|
end
|
||
|
|
||
|
**Finish Script**
|
||
|
|
||
|
To create a service that has a finish script in its service directory,
|
||
|
set the `finish` parameter to `true`, and create a
|
||
|
`sv-finisher-finish.erb` template.
|
||
|
|
||
|
runit_service "finisher" do
|
||
|
finish true
|
||
|
end
|
||
|
|
||
|
This will create `/etc/sv/finisher/finish`.
|
||
|
|
||
|
**Alternate service directory**
|
||
|
|
||
|
If the service directory for the managed service isn't the `sv_dir`
|
||
|
(`/etc/sv`), then specify it:
|
||
|
|
||
|
runit_service "custom_service" do
|
||
|
sv_dir "/etc/custom_service/runit"
|
||
|
end
|
||
|
|
||
|
**No Service Directory**
|
||
|
|
||
|
If the service to manage has a package that provides its service
|
||
|
directory, such as `git-daemon` on Debian systems, set `sv_templates`
|
||
|
to false.
|
||
|
|
||
|
package "git-daemon-run"
|
||
|
|
||
|
runit_service "git-daemon" do
|
||
|
sv_templates false
|
||
|
end
|
||
|
|
||
|
This will create the service symlink in `/etc/service`, but it will
|
||
|
not manage any templates in the service directory.
|
||
|
|
||
|
**User Controlled Services**
|
||
|
|
||
|
To set up services controlled by a non-privileged user, we follow the
|
||
|
recommended configuration in the
|
||
|
[runit documentation](http://smarden.org/runit/faq.html#user) (Is it
|
||
|
possible to allow a user other than root to control a service?).
|
||
|
|
||
|
Suppose the user's name is floyd, and floyd wants to run floyds-app.
|
||
|
Assuming that the floyd user and group are already managed with Chef,
|
||
|
create a `runsvdir-floyd` runit_service.
|
||
|
|
||
|
runit_service "runsvdir-floyd"
|
||
|
|
||
|
Create the `sv-runsvdir-floyd-log-run.erb` template, or add `log
|
||
|
false`. Also create the `sv-runsvdir-floyd-run.erb` with the following
|
||
|
content:
|
||
|
|
||
|
#!/bin/sh
|
||
|
exec 2>&1
|
||
|
exec chpst -ufloyd runsvdir /home/floyd/service
|
||
|
|
||
|
Next, create the `runit_service` resource for floyd's app:
|
||
|
|
||
|
runit_service "floyds-app" do
|
||
|
sv_dir "/home/floyd/sv"
|
||
|
service_dir "/home/floyd/service"
|
||
|
owner "floyd"
|
||
|
group "floyd"
|
||
|
end
|
||
|
|
||
|
And now floyd can manage the service with sv:
|
||
|
|
||
|
$ id
|
||
|
uid=1000(floyd) gid=1001(floyd) groups=1001(floyd)
|
||
|
$ sv stop /home/floyd/service/floyds-app/
|
||
|
ok: down: /home/floyd/service/floyds-app/: 0s, normally up
|
||
|
$ sv start /home/floyd/service/floyds-app/
|
||
|
ok: run: /home/floyd/service/floyds-app/: (pid 5287) 0s
|
||
|
$ sv status /home/floyd/service/floyds-app/
|
||
|
run: /home/floyd/service/floyds-app/: (pid 5287) 13s; run: log: (pid 4691) 726s
|
||
|
|
||
|
**Options**
|
||
|
|
||
|
Next, let's set up memcached under runit with some additional options
|
||
|
using the `options` parameter. First, the
|
||
|
`memcached/templates/default/sv-memcached-run.erb` template:
|
||
|
|
||
|
#!/bin/sh
|
||
|
exec 2>&1
|
||
|
exec chpst -u <%= @options[:user] %> /usr/bin/memcached -v -m <%= @options[:memory] %> -p <%= @options[:port] %>
|
||
|
|
||
|
Note that the script uses `chpst` (which comes with runit) to set the
|
||
|
user option, then starts memcached on the specified memory and port
|
||
|
(see below).
|
||
|
|
||
|
The log/run template,
|
||
|
`memcached/templates/default/sv-memcached-log-run.erb`:
|
||
|
|
||
|
#!/bin/sh
|
||
|
exec svlogd -tt ./main
|
||
|
|
||
|
Finally, the `runit_service` in our recipe:
|
||
|
|
||
|
runit_service "memcached" do
|
||
|
options({
|
||
|
:memory => node[:memcached][:memory],
|
||
|
:port => node[:memcached][:port],
|
||
|
:user => node[:memcached][:user]}.merge(params)
|
||
|
)
|
||
|
end
|
||
|
|
||
|
This is where the user, port and memory options used in the run
|
||
|
template are used.
|
||
|
|
||
|
**Notifying Runit Services**
|
||
|
|
||
|
In previous versions of this cookbook where the definition was used,
|
||
|
it created a `service` resource that could be notified. With the
|
||
|
`runit_service` resource, recipes need to use the full resource name.
|
||
|
For example:
|
||
|
|
||
|
runit_service "my-service"
|
||
|
|
||
|
template "/etc/my-service.conf" do
|
||
|
notifies :restart, "runit_service[my-service]"
|
||
|
end
|
||
|
|
||
|
Because the resource implements actions for various commands that `sv`
|
||
|
can send to the service, any of those actions could be used for
|
||
|
notification. For example, `chef-client` supports triggering a Chef
|
||
|
run with a USR1 signal.
|
||
|
|
||
|
template "/tmp/chef-notifier" do
|
||
|
notifies :usr1, "runit_service[chef-client]"
|
||
|
end
|
||
|
|
||
|
For older implementations of services that used `runit_service` as a
|
||
|
definition, but may support alternate service styles, use a
|
||
|
conditional, such as based on an attribute:
|
||
|
|
||
|
service_to_notify = case node['nginx']['init_style']
|
||
|
when "runit"
|
||
|
"runit_service[nginx]"
|
||
|
else
|
||
|
"service[nginx]"
|
||
|
end
|
||
|
|
||
|
template "/etc/nginx/nginx.conf" do
|
||
|
notifies :restart, service_to_notify
|
||
|
end
|
||
|
|
||
|
**More Examples**
|
||
|
|
||
|
For more examples, see the `runit_test` cookbook's `service` recipe in
|
||
|
the [git repository](https://github.com/opscode-cookbooks/runit).
|
||
|
|
||
|
Testing
|
||
|
=======
|
||
|
|
||
|
This cookbook has tests in the GitHub repository. To run the tests:
|
||
|
|
||
|
git clone git://github.com/opscode-cookbooks/runit.git
|
||
|
cd runit
|
||
|
bundle install
|
||
|
|
||
|
There are two kinds of tests, unit tests and integration tests.
|
||
|
|
||
|
## Unit Tests
|
||
|
|
||
|
The resource/provider code is unit tested with rspec. To run these
|
||
|
tests, use rake:
|
||
|
|
||
|
bundle exec rake spec
|
||
|
|
||
|
## Integration Tests
|
||
|
|
||
|
Integration tests are setup to run under minitest-chef. They are
|
||
|
automatically run under test kitchen.
|
||
|
|
||
|
bundle exec kitchen test
|
||
|
|
||
|
This tests the default recipe ("default" configuration), and various
|
||
|
uses of the `runit_service` resource ("service" configuration).
|
||
|
|
||
|
License and Author
|
||
|
==================
|
||
|
|
||
|
Author:: Adam Jacob <adam@opscode.com>
|
||
|
Author:: Joshua Timberman <joshua@opscode.com>
|
||
|
|
||
|
Copyright:: 2008-2013, Opscode, Inc
|
||
|
|
||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
you may not use this file except in compliance with the License.
|
||
|
You may obtain a copy of the License at
|
||
|
|
||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
||
|
Unless required by applicable law or agreed to in writing, software
|
||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
See the License for the specific language governing permissions and
|
||
|
limitations under the License.
|