66

Software

obarun.org

The frontend service file

The s6 and s6-rc programs each handle and use several kinds of services and different files. It is quite complex to understand and manage the relationship between all those files and services. If you're interested in the details you should read the documentation for the s6 servicedir and also about classic, oneshot, longrun (also called atomic services),bundle and module services. The frontend service file of 66 tools allows you to deal with all these different services in a centralized manner and in one single location.

By default 66 tools expects to find service files in /usr/lib/66/service and /etc/66/service for root user. For regular users, $HOME/.66/service will take priority over the previous ones. Although this can be changed at compile time by passing the --with-system-service=DIR, --with-sysadmin-service=DIR and --with-user-service=DIRoption to ./configure.

The frontend service file has a format of INI with a specific syntax on the key field. The name of the file usually corresponds to the name of the daemon and does not have any extension or prefix.

The file is made of sections which can contain one or more key value pairs where the key name can contain special characters like - (hyphen) or _ (low line) except the character @ (commercial at) which is reserved.

You can find a prototype with all valid section and all valid key=value pair at the end of this document.

File names examples

    /usr/lib/66/service/dhcpcd
    /usr/lib/66/service/very_long_name

File content example

    [main]
    @type = classic
    @description = "ntpd daemon"
    @version = 0.1.0
    @user = ( root )

    [start]
    @execute = (
        foreground { mkdir -p  -m 0755 ${RUNDIR} }
        execl-cmdline -s { ntpd ${CMD_ARGS} }
    )

    [environment]
    dir_run=!/run/openntpd
    cmd_args=!-d -s

The parser will not accept an empty value. If a key is set then the value can not be empty. Comments are allowed using the number sign #. Empty lines are also allowed.

Key names are case sensitive and can not be modified. Most names should be specific enough to avoid confusion.

The sections can be declared in any order but as a good practice the [main] section should be declared first. This way the parser can read the file as fast as possible.

Sections

All sections need to be declared with the name written between square brackets [] and must be of lowercase letters only. This means that special characters, uppercase letters and numbers are not allowed in the name of a section. An entire section can be commented out by placing the number sign # in front of the opening square bracket like this:

    #[stop]

The frontend service file allows the following section names:

Although a section can be mandatory not all of its key fields must be necessarily so.


Syntax legend

The value of a key is parsed in a specific format depending on the key. The following is a break down of how to write these syntaxes:


Section: [main]

This section is mandatory. (!)

Valid key names:


Section: [start]

This section is mandatory. (!)

Valid key names:


Section: [stop]

This section is optional.

This section is exactly the same as [start] and shares the same keys. With the exception that it will handle the stop process of the service.


Section: [logger]

This section is optional.

It will only have effects if value log was not prefixed by an exclamation mark to the @options key in the [main] section.

This section extends the @build, @runas, @shebang and @execute key fields from [start] and the @timeout-finish and @timeout-kill key fields from [main] . These are also valid keys for [logger] and behave the same way they do in the other sections but they can not be specified except for the mandatory key @build—see example below. In such case the default behaviour for those key are apply.

Furthermore there are some keys specific to the log.

Valid key names:


Section: [environment]

This section is optional.

The definition of this section automatically adds the value *env” at the @options key in the [main] section.

A file containing the key=value pair(s) will be created by default at /etc/66/conf/name_of_service directory. The default can also be changed at compile-time by passing the --with-sysadmin-service-conf=DIR option to ./configure.

Valid key names:


Section: [regex]

This section is optional.

It will only have an effect when the service is a module type—see the section Module service creation.

You can use the @I string as key field. It will be replaced by the module name as you do for instantiated service before applying the regex section.

Valid key names:


A word about the @execute key

As described above the @execute key can be written in any language as long as you define the key @build as custom and the @shebang key to the language interpreter to use. For example if you want to write your @execute field with bash:

    @build = custom
    @shebang = "/usr/bin/bash"
    @execute = (
        echo "This script displays available services"
        for i in $(ls /usr/lib/66/service); do
            echo "daemon : ${i} is available"
        done
    )

This is an unnecessary example but it shows how to construct this use case. The parser will put your @shebang at the beginning of the script and copy the contents of the @execute field. So, the resulting file will be :

    #!/usr/bin/bash
    echo "This script displays available services"
    for i in $(ls /usr/lib/66/service); do
        echo "daemon : ${i} is available"
    done

When using this sort of custom function @runas has no effect. You must define with care what you want to happen in a custom case.

Furthermore when you set @build to auto the parser will take care about the redirection of the ouput of the service when the logger is activated. When setting @build to custom though the parser will not do this automatically. You need to explicitly tell it to:

    #!/usr/bin/bash
    exec 2>&1
    echo "This script redirects file descriptor 2 to the file descriptor 1"
    echo "Then the logger reads the file descriptor 1 and you have"
    echo "the error of the daemon written into the appropriate file"

Moreover, for oneshot type the @shebang needs to contain the interpreter options as below:

    @build = custom
    @shebang = "/usr/bin/bash -c"
    @execute = ( echo "this is a oneshot service with a correct shebang definition" )

Finally you need to take care about how you define your environment variable in the section [environment]. When setting @build to auto the parser will also take care about the ! character if you use it. This character will have no effect in the case of custom.

This same behavior applies to the [logger] section. The fields @destination, @backup, @maxsize and @timestamp will have no effect in a custom case. You need to explicitly define the program to use the logger and the options for it in your @execute field.


Prototype of a frontend file

The minimal template is:

    [main]
    @type = classic,bundle,longrun,oneshot,module
    @version =
    @description = ""
    @user = ()

    [start]
    @execute = ()

This prototype contain all valid section with all valid key=value pair.

    [main]

    @depends = ()
    @optsdepends = ()
    @extdepends = ()
    @contents = ()
    @options = ( log env pipeline )
    @flags = ( down )
    @notify =
    @user = ()
    @timeout-finish =
    @timeout-kill =
    @timeout-up =
    @timeout-down =
    @maxdeath =
    @down-signal =
    @hiercopy = ()

    [start]
    @build = auto,custom
    @runas =
    @shebang = "/path"
    @execute = ()

    [stop]
    @build = auto,custom
    @runas =
    @shebang = "/path"
    @execute = ()

    [logger]
    @build = auto,custom
    @runas =
    @shebang = "/path"
    @destination = /path
    @backup =
    @maxsize =
    @timestamp =
    @timeout-finish =
    @timeout-kill =
    @execute = ()

    [environment]
    mykey=myvalue
    ANOTHERKEY=!antohervalue

    [regex]
    @configure = "arguments to pass to the configure script"
    @directories = ( key=value key=value )
    @files = ( key=value key=value )
    @infiles = ( :filename:key=value ::key=value )
    @addservices = ()