# `cement.ext.ext_daemon`

The Daemon Extension enables applications Built on Cement (tm) to easily perform standard daemonization functions.

## Requirements

> - Python 2.6+, Python 3+
> - Available on Unix/Linux only

## Features

> - Configurable runtime user and group
> - Adds the `--daemon` command line option
> - Adds `app.daemonize()` function to trigger daemon functionality where necessary (either in a cement `pre_run` hook or an application controller sub-command, etc)
> - Manages a pid file including cleanup on `app.close()`

## Configuration

The daemon extension is configurable with the following settings under the [daemon] section.

> - user - The user name to run the process as. Default: os.getlogin()
> - group - The group name to run the process as. Default: The primary group of the ‘user’.
> - dir - The directory to run the process in. Default: /
> - pid_file - The filesystem path to store the PID (Process ID) file. Default: None
> - umask - The umask value to pass to os.umask(). Default: 0

Configurations can be passed as defaults to a CementApp:

    from cement.core.foundation import CementApp
    from cement.utils.misc import init_defaults

    defaults = init_defaults('myapp', 'daemon')
    defaults['daemon']['user'] = 'myuser'
    defaults['daemon']['group'] = 'mygroup'
    defaults['daemon']['dir'] = '/var/lib/myapp/'
    defaults['daemon']['pid_file'] = '/var/run/myapp/myapp.pid'
    defaults['daemon']['umask'] = 0

    app = CementApp('myapp', config_defaults=defaults)

Application defaults are then overridden by configurations parsed via a `[demon]` config section in any of the applications configuration paths. An example configuration block would look like:

    [daemon]
    user = myuser
    group = mygroup
    dir = /var/lib/myapp/
    pid_file = /var/run/myapp/myapp.pid
    umask = 0

## Usage

The following example shows how to add the daemon extension, as well as trigger daemon functionality before `app.run()` is called.

    from time import sleep
    from cement.core.foundation import CementApp

    class MyApp(CementApp):
        class Meta:
            label = 'myapp'
            extensions = ['daemon']

    with MyApp() as app:
        app.daemonize()
        app.run()

        count = 0
        while True:
            count = count + 1
            print('Iteration: %s' % count)
            sleep(10)

An alternative to the above is to put the `daemonize()` call within a framework hook:

    def make_daemon(app):
        app.daemonize()

    def load(app):
        app.hook.register('pre_run', make_daemon)

Finally, some applications may prefer to only daemonize certain sub-commands rather than the entire parent application. For example:

    from cement.core.foundation import CementApp
    from cement.core.controller import CementBaseController, expose

    class MyBaseController(CementBaseController):
        class Meta:
            label = 'base'

        @expose(help="run the daemon command.")
        def run_forever(self):
            from time import sleep
            self.app.daemonize()

            count = 0
            while True:
                count = count + 1
                print(count)
                sleep(10)

    class MyApp(CementApp):
        class Meta:
            label = 'myapp'
            base_controller = MyBaseController
            extensions = ['daemon']

    with MyApp() as app:
        app.run()

By default, even after `app.daemonize()` is called... the application will continue to run in the foreground, but will still manage the pid and user/group switching. To detach a process and send it to the background you simply pass the `--daemon` option at command line.

    $ python example.py --daemon

    $ ps -x | grep example
    37421 ??         0:00.01 python example2.py --daemon
    37452 ttys000    0:00.00 grep example

class `cement.ext.ext_daemon.``Environment`(**kw)

  Bases: `object`

  This class provides a mechanism for altering the running processes environment.

  Optional Arguments:

  Parameters:

  - stdin – A file to read STDIN from. Default: `/dev/null`
  - stdout – A file to write STDOUT to. Default: `/dev/null`
  - stderr – A file to write STDERR to. Default: `/dev/null`
  - dir – The directory to run the process in.
  - pid_file – The filesystem path to where the PID (Process ID) should be written to. Default: None
  - user – The user name to run the process as. Default: `os.getlogin()`
  - group – The group name to run the process as. Default: The primary group of `os.getlogin()`.
  - umask – The umask to pass to os.umask(). Default: `0`

  `_write_pid_file`()

    Writes `os.getpid()` out to `self.pid_file`.

  `daemonize`()

    Fork the current process into a daemon.

    References:

    UNIX Programming FAQ:
      1.7 How do I get my program to act like a daemon? http://www.unixguide.net/unix/programming/1.7.shtml http://www.faqs.org/faqs/unix-faq/programmer/faq/
    Advanced Programming in the Unix Environment
      23. Richard Stevens, 1992, Addison-Wesley, ISBN 0-201-56317-7.
  `switch`()

    Switch the current process’s user/group to `self.user`, and `self.group`. Change directory to `self.dir`, and write the current pid out to `self.pid_file`.

`cement.ext.ext_daemon.``cleanup`(app)

  After application run time, this hook just attempts to clean up the pid_file if one was set, and exists.

`cement.ext.ext_daemon.``daemonize`()

  This function switches the running user/group to that configured in `config['daemon']['user']` and `config['daemon']['group']`. The default user is `os.getlogin()` and the default group is that user’s primary group. A pid_file and directory to run in is also passed to the environment.

  It is important to note that with the daemon extension enabled, the environment will switch user/group/set pid/etc regardless of whether the `--daemon` option was passed at command line or not. However, the process will only ‘daemonize’ if the option is passed to do so. This allows the program to run exactly the same in forground or background.

`cement.ext.ext_daemon.``extend_app`(app)

  Adds the `--daemon` argument to the argument object, and sets the default `[daemon]` config section options.