View on GitHub

runit-quickstart

Getting started with the runit - a UNIX init scheme with service supervision

Download this project as a .zip file Download this project as a tar.gz file

Abstract

The purpose of this tutorial is to get you up and running with runit as quickly as possible. According to the official documentaion, runit is "a UNIX init scheme with service supervision". Basically this means that runit provides:

  1. Automatic starting of services when the system starts
  2. Automatic monitoring and restarting of services if they terminate

This tutorial will describe the basic usage of the utilities included in the runit package by providing a template to bootstrap the management of new services as well as providing a simple example service. The purpose of process supervision is to automate the task of keeping your infrastrucutre up and running. If you are serious about creating a robust environment, you should use this tutorial as a starting point to get you over the initial hump associated with learning a new tool and then continue by checking out the official documentation and performing further experimentation.

Official Documentation: http://smarden.org/runit/

What You Will Learn

  1. How to create a runit template used to configure new montitored services
  2. How to setup your first monitored service
  3. How to manage monitored services manually

0. Prerequisites

Make sure that you have runit installed on your system. Most linux distributions should have a runit package available in their repositories. For example, if you are running a Debian based release you can install runit by executing the following command:

# apt-get install runit

Note: Snippets starting with the '#' character represent command you should enter in your shell excluding the '#'.

To verify that you have successfully installed runit and it is up and running, look for a process running the runsvdir command by executing the following:

# ps -ef | grep runsvdir

The output of the command should be similar to this:

root      2783     1  0 15:34 ?        00:00:00 runsvdir -P /etc/service log: ...........................................................................................................................................................................................................................................................................................................................................................................................................

If you see a runsvdir process then continue on. If not ensure that runit was installed properly by checking the documentation for you distro. The runsvdir utility is the first of several that we will encounter in this tutorial. The design of runit takes a very "Unixy" approach by breaking down functionality into several small utilities each responsible for a single task. This approach allows the simple components to be composed in various ways to suit you needs. The core runit utilities are runsvdir, runsv, chpst, svlogd, and sv. Throughout this tutorial we will combine these utilities to configure and run a managed service.

1. Creating a Template

The first thing we need to do is take a closer look at what the runsvdir -P /etc/service log:....... command is doing. Bascially, this command is watching the /etc/service directory for files used to configure a monitored service. A monitored service is configured by adding a subdirecotry to /etc/service with a run script in it. When runsvdir finds a new service configuration, it starts a new runsv process to manage the service. As far as runsvdir is concerned, there really is not much more to it that that. Remember that runit's philosophy is to provide simple utilities with a single responsibility. Check out the man page for further details:

# man runsvdir

Make sure that the /etc/service directory exists and if it does not, create it with the following command:

# mkdir /etc/service

Rather than adding our configuration files directly to the /etc/service directory, let's create a staging directory that we can use to develop and test our configurations. Once we are happy with our service configuration, we can deploy it by creating a symbolic link to it from the /etc/service directory. You can use any directory that you like for staging, but I like to use /etc/runit. Go ahead and create your staging directory now.

# mkdir /etc/runit

Before creating our first real service configuration, let's create a template. This template will illustrate the basics of using runit and can be used to quickly create new configurations in the future. Create a directory for our template by running this command:

# mkdir /etc/runit/template

Next, create a script named run in the template directory with the following contents:

#!/bin/sh -e
exec 2>&1
exec chpst -u USER COMMAND

Make the run script executable by running:

# chmod +x /etc/runit/template/run

This script is quite simple. First it redirects all output from stderr to stdout. Next, it executes some COMMAND as the given USER with the chpst utility. The chpst utility allows us to configure how the command will be executed. Because the run script will be executed as the root user, we can use chpst to change the context to a normal user with limited permissions. chpst has many more options for configuring the context in which to execute a command. Check out the man page for more info.

# man chpst

When the runsvdir process detects a new directory in /etc/service it will start a new runsv process that will be responible for executing and monitoring the run script. Take a look at the runsv man page for more details.

# man runsv

You may have noticed that the man page for runsv mentions that it can optionally start an appendant log service. Because logging is such a critical part of monitoring an environment, let's create a template script for logging the output of our monitored process.

To setup logging for our service, create a new log directory by running the following command:

# mkdir /etc/runit/template/log

In the new directory create a script named run with the following contets:

#!/bin/sh
exec chpst -u USER svlogd -tt LOGDIR

Make the run script executable by running the following command:

# chmod +x /etc/runit/template/log/run

This script uses chpst to start a svlogd daemon as the given USER wirting logs to the LOGDIR directory. For details on logging configuration, check out the svlogd man page.

# man svlogd

When runsvdir notices a monitor configuration in a new directory under /etc/service, it looks for a sub directory named log. If it finds one it starts a new runsv process that will execute and monitor the run script in the log directory.

2. An Example Service

Let's take our template and create a simple example service configuration. First, create a new user that will be used by chpst in the run script. You can name the user anything you want.

# adduser foo

Next, let's create a directory to host the service and change its ownership to our new user. You can choose any directory that you like. I like to setup applications in the opt directory.

# mkdir /opt/example
# chown foo:foo /opt/example

Now that we have a home for our service, let's create a simple script that will stand in for a real service. Change to the new foo user:

# su foo

Create a new file in /opt/example called foo-service.sh and add the following contents:

#!/bin/bash

echo "Started service..."

for i in {1..30}
do
    echo "Doing stuff..."
    sleep 1
done

echo "Oh no I crashed..." >&2
exit 1

Make this script executable by executing this command:

# chmod +x /opt/example/foo-service.sh

This script will simulate a real application that crashes periodically by logging some information for 30 seconds, logging an error to stderr, and then exiting with a non zero status. Try it out by executing:

# /opt/example/foo-service.sh

Next, create a directory that will contain the logs for the service.

# mkdir /opt/example/logs

That's everthing we need to do as the foo user, so switch back to root by executing:

# exit

Now we are ready to use the template we defined to configure runit to monitor our example service. Create the configuration in our staging directory by copying the template to a new directory named example.

# cp -R /etc/runit/template /etc/runit/example

Update the /etc/runit/example/run script to execute the foo-service.sh script as the foo user.

#!/bin/sh -e
exec 2>&1
exec chpst -u foo /opt/example/foo-service.sh

Update the /etc/runit/example/log/run log script log to the /etc/example/logs directory as the foo user.

#!/bin/sh
exec chpst -u foo svlogd -tt /opt/example/logs

Before we deploy the service to /etc/service, let's test it to make sure everything is setup properly.

# /etc/runit/example/run

If everything is ok, you should see the script log output for 30 seconds, log an error and then terminate.

Finally, we are ready to deploy the service. Create a symbolic link in /etc/service to our staging location.

# ln -s /etc/runit/example /etc/service/example

The runsvdir process should have noticed our new monitor configuration and started two runsv processes to execute the service and run the log daemon. To verify that everything is working, check the status of our service.

# sv status example

You should see output similar to what is shown below to indicate the service and logger are running.

run: example: (pid 3483) 3s; run: log: (pid 3324) 154s

You can watch the output of the service by tailing the log.

# tail -f /opt/example/logs/current

You should see the service logging output, logging an error, and then starting over as the runsv process notices the process terminate and restarts it.

3. Managing Services

Finally, let's take a look at the sv utility. sv is used to manually manage your services.

To check the status of the example service run:

# sv status example

To stop the example service run:

# sv stop example

You will notice if you watch the logs that the service is no longer writing any output. Once you stop a service with sv, it will not be restarted automatically until you explicitly restart it.

To start the service again run:

# sv start example

To stop and then start a service run:

# sv restart example

Make sure to check out the sv man page to see additional options.

# man sv

Start Your Monitors!!!

With what you have learned in this tutorial, you should now be able to configure services to be monitored with runit. Try using the template to monitor a web application, some web services, or your CI server.

Contact Me

If you have any questions or would like further clarification, please feel free to shoot me an email. I would be glad to help.

Kevin

krchard@gmail.com