# Daemon

## Introduction

The Daemon Extension enables applications to easily perform standard daemonization operations.

**Features**

* Configurable runtime user and group
* Adds the `--daemon` command line option
* Add `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()`

**API References:**

* [Cement Daemon Extension](https://cement.readthedocs.io/en/3.0/api/ext/ext_daemon/)

## Requirements

* No external dependencies

## Platform Support

* Unix/Linux
* macOS

## Configuration

The daemon extension is configurable with the following settings under a `[daemon]` section in the application configuration:

| Setting       | **Description**                                                              |
| ------------- | ---------------------------------------------------------------------------- |
| **user**      | The user name the process runs as.  Default: `os.getlogin()`                 |
| **group**     | The group name the process runs as. Default: *the primary group of the user* |
| **dir**       | The directory that the process runs 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 `App`:

```python
from cement import App, 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

class MyApp(App):
    class Meta:
        label = '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.

```python
from time import sleep
from cement import App

class MyApp(App):
    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)
```

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

```python
from cement import App, Controller, ex

class Base(Controller):
    class Meta:
        label = 'base'

    @ex(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(App):
    class Meta:
        label = 'myapp'
        handlers = [Base]
        extensions = ['daemon']

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

{% hint style="warning" %}
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.
{% endhint %}

```
$ python example.py --daemon

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

### Daemonizing Without Commandline Option

Some use cases might require daemonizing the process without having to always pass the `--daemon` option, or where passing the option might be redundant. You can work around that programatically by simply overriding the `daemon` argument value in order to force daemonization even if `--daemon` wasn’t passed.

```python
app.pargs.daemon = True
app.daemonize()
```

Note that this would only work **after** arguments have been parsed (i.e. after `app.run()` is called).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.builtoncement.com/extensions/daemon.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
