Skip to content
/ serv Public

An abstraction over the most common init systems out there and the answer for: "Why the hell do I have to know init systems? I just want to run this forever, damnit!"

License

Notifications You must be signed in to change notification settings

nir0s/serv

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Serv

Travis Build Status AppVeyor Build Status PyPI Version Supported Python Versions Requirements Status Code Coverage Code Quality Is Wheel

Serv creates, removes and manages services on multiple init systems (process managers? service managers? can someone come up with a normal name for this? jeez.)

Serv is a Pythonic spinoff of Jordan Sissel's brilliant pleaserun. The question that Serv tries to answer is: "Why the hell do I have to know init systems? I just want this to run forever."

Features

  • Abstracts away the platform (systemd, upstart, etc..) - Serv identifies it by itself though it can be explicitly provided.
  • Creates service configuration files on different platforms so that you don't have to.
  • Allows to deploy services after generating the config on the local machine.
  • Allows to start, stop, restart and remove services.
  • Provides both an API and CLI for those purposes.
  • Provides an API for retrieving service related information.
  • Controls services not generated by Serv.

NOTE: Serv requires sudo/Administrator privileges! (you can't write to /etc/init.d, /lib/systemd/system and the others without root can ya?)

Supported Init Systems

systemd, Upstart, nssm (Non-Sucking Service Manager for Windows) and SysVinit are mostly supported now though SysV doesn't yet support retrieving a service's status.

I intend to add:

  • launchd
  • runit
  • supervisord
  • Whichever other system that's giving you (or me) a headache.

Note: On Linux, Serv uses distro to identify the distribution.

Compatibility

Currently, tested on Python 2.6, 2.7, 3.4 and 3.5

Installation

sudo pip install serv

For dev:

sudo pip install https://github.com/nir0s/serv/archive/master.tar.gz

Usage

Before using, please read the caveats section!

$ sudo serv
Usage: serv [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  generate  Creates a service.
  remove    Stops and Removes a service
  restart   Restarts a service
  start     Starts a service
  status    WIP! Try at your own expense
  stop      Stops a service

...

Creating a service

$ sudo serv generate /usr/bin/python2 --name MySimpleHTTPServer --args '-m SimpleHTTPServer' --var KEY1=VALUE1 --var KEY2=VALUE2 --deploy --start
...

INFO - Generating files for systemd...
INFO - Generated /tmp/SimpleHTTPServer.service
INFO - Generated /tmp/SimpleHTTPServer
INFO - Deploying systemd service SimpleHTTPServer...
INFO - Deploying /tmp/SimpleHTTPServer.service to /lib/systemd/system/SimpleHTTPServer.service...
INFO - Deploying /tmp/SimpleHTTPServer to /etc/sysconfig/SimpleHTTPServer...
INFO - Starting systemd service SimpleHTTPServer...
INFO - Service created.


...

$ ss -lntp | grep 8000
LISTEN     0      5            *:8000                     *:*

If name is omitted, the name of the service (and therefore, the names of the files) will be deduced from the executable's name.

Generating only

If the --deploy flag isn't provided, files for the service will be generated and saved under a temp folder for you to use. This is useful when generating service files for using elsewhere.

Controlling a service

NOTE: Existing services which were not created by Serv can also be controlled as long as they've served by an init system supported by serv and are in serv-controlled folders.

$ sudo serv stop MySimpleHTTPServer
INFO - Stopping service: MySimpleHTTPServer...
$ ss -lntp | grep 8000
...

$ sudo serv start MySimpleHTTPServer
INFO - Starting service: MySimpleHTTPServer...
$ ss -lntp | grep 8000
LISTEN     0      5            *:8000                     *:*

$ sudo serv restart MySimpleHTTPServer
INFO - Restarting service: MySimpleHTTPServer...
$ ss -lntp | grep 8000
LISTEN     0      5            *:8000                     *:*
...

Retrieving a service's status

IMPORTANT NOTE: serv status is current very buggy. Expect it to break and please submit issues.

$ sudo serv status MySimpleHTTPServer
...

{
    "init_system": "systemd",
    "init_system_version": "default",
    "services": [
        {
            "active": "active",
            "description": "no",
            "load": "loaded",
            "name": "MySimpleHTTPServer.service",
            "sub": "running"
        }
    ]
}

...

or for all services of the same init system

$ sudo serv status
...

Removing a service

$ sudo serv remove MySimpleHTTPServer
...

INFO - Removing Service: SimpleHTTPServer...
INFO - Service removed.
...

$ ss -lntp | grep 8000

nssm-specific usage pattern

Windows support is provided via the Non-Sucking Service Manager (nssm).

There are some differences between Windows and Linux support. While the API is practically the same, it still requires the user to be a bit more cautious. For instance, when providing the --args flag, single quotes won't do (e.g. '-m SimpleHTTPServer') but rather doubles must be used and cmd must be loaded as Administrator to be able to install the service as it requires elevated privileges.

It's important to note that deploying a Windows service also deploys nssm itself and will not clean it up if a service is removed as it might be used by other services.

Python API

raise NotImplementedError()

Kidding.. it's there, it's easy and it requires documentation.

How does it work

Serv, unless explicitly specified by the user, looks up the platform you're running on (Namely, linux distro and release unless running on Windows or OS X) and deduces which init system is running on it by checking a static mapping table or an auto-lookup mechanism.

Once an init-system matching an existing implementation (i.e supported by Serv) is found, Serv renders template files based on a set of parameters; (optionally) deploys them to the relevant directories and (optionally) starts the service.

Since Serv is aware of the init system being used, it also knows which files it needs to deploy and to where and which commands it needs to run.

Caveats and limitations

  • Init system identification is not robust. It relies on some assumptions (and as we all know, assumption is the mother of all fuckups). Some OS distributions have multiple init systems (Ubuntu 14.04 has Upstart, SysV and half (HALF!?) of systemd). Thus, the implementation is based on best effort where static mapping takes precedence over auto-detection. This doesn't mean that auto-detection will not work most of the time.
  • Stupidly enough, I have yet to standardize the status JSON returned and it is different for each init system.
  • If anything fails during service creation, cleanup is not performed. This will be added in future versions.
  • Currently, all errors exit with the same error level. This will be changed soon.

Missing directories

In some situations, directories related to the specific init system do not exist and should be created. For instance, even if systemd (systemctl) is available, /etc/sysconfig might not exist. IT IS UP TO THE USER to create those directories if they don't exist as Serv should not modify the system on such level. The exception to the rule is with nssm, which will create the required dir (c:\nssm) for it to operate.

The user will be notified of which directory is missing.

Required dirs are:

Systemd

  • /lib/systemd/system
  • /etc/sysconfig

SysV

  • /etc/init.d
  • /etc/default

Upstart

  • /etc/init

Nssm

The directory (c:\nssm) will be created for the user in case it doesn't exist.

Testing

Important note! While you can queitly run unittests on your laptop, running the deploy (integration) tests on your machine requires sudo privileges and may alter your machine. The deploy tests are not meant to run on your laptop but rather in a clear CI environment.

That being said, if you do decide to run them locally, a service will be created according to the init system available on your machine (assuming it's supported) and will be removed when the test is done. For that sole purpose, tox must be run using sudo as seen below.

git clone git@github.com:nir0s/serv.git
cd serv
pip install tox
tox -e py26,py27,py34,py35,flake8
sudo tox -e deploy

Contributions..

Pull requests are always welcome to deal with specific distributions or for general merriment.

Adding support for additional init-systems.

  • Under serv/init, add a file named <init_system_name>.py (e.g. runit.py).
  • Implement a class named <init_system_name> (e.g. Runit). See systemd as a reference implementation.
  • Pass the Base class which contains some basic parameter declarations and provides a method for generating files from templates to your class (e.g. from .base import Base).
  • Add the relevant template files to serv/init/templates. The file names should be formatted as: <init_system_name>.* (e.g. runit.conf).
  • In serv.py, import your implementation and add a name mapping to the INIT_SYSTEM_MAPPING global with the relevant class.

About

An abstraction over the most common init systems out there and the answer for: "Why the hell do I have to know init systems? I just want to run this forever, damnit!"

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published