A lightweight, cross-platform daemon manager that runs any command — called a task — as a background process. It also supports logging and log rotation out of the box. No Docker or extra dependencies required.
Shipped as the CLI tool dmon
.
It is a Python-based and more powerful successor to the handy-backend shell scripts.
- 🖥️ Cross-platform: Works on Linux, macOS, and Windows.
- ⚡ Lightweight: Pure Python, no Docker or external dependencies needed.
- 🧩 Flexible tasks: Tasks can be configured in
pyproject.toml
ordmon.yaml
; or run ad-hoc commands directly. - 🪵 Logging & log rotation: Automatically manage log files to prevent uncontrolled growth.
pip install python-dmon
To get the latest features, install from source:
pip install git+https://github.com/atomiechen/python-dmon.git
Create a dmon.yaml
file:
tasks:
app: ["python", "-u", "server.py"]
Or add to your pyproject.toml
:
[tool.dmon.tasks]
app = ["python", "-u", "server.py"]
Commands can be a single string (run in shell), or list of strings (exec form). See Example Task Configuration for more configuration options.
Run a configured task by its name:
# Start a task
dmon start app
# Stop a running task
dmon stop app
# Check task status
dmon status app
# Execute a task in the foreground (useful for debugging)
dmon exec app
If only one task is defined in the config file, you can omit the task name:
dmon start
dmon stop
dmon status
dmon exec
You can use --config
to specify a custom config file:
dmon start --config /path/to/dmon.yaml app # YAML
dmon start --config /path/to/pyproject.toml app # or TOML
And yes, you can use dmon
to run in a nested manner:
tasks:
app: ["python", "-u", "server.py"]
nested: pwd && dmon exec app # nest `dmon exec`
subdir_task1:
cwd: /path/to/dir
cmd: ["dmon", "exec", "app"] # run task defined in another folder
subdir_task2: dmon exec app --config /path/to/dir/dmon.yaml # like above
# Run a command with arguments in the background
dmon run --name myserver python -u server.py
# Run a shell command in the background
dmon run --shell echo "Hello World"
# Run a shell script in the background
dmon run --cwd /path/to/script bash myscript.sh
Note
If no name is provided, dmon
automatically assigns a fixed task name default_run
to prevent duplicate runs.
dmon list
A task can be a string, list, or dictionary.
Here is a more complete example with default values:
tasks:
your_task_name:
# Command to run; can be a string (run in shell) or list of strings (exec form)
cmd: ["python", "server.py"] # required
cwd: "/path/to/working/dir" # (default: current dir)
env: # (default: inherit from parent process)
PYTHONUNBUFFERED: "1"
override_env: false # override parent env and only use env defined here
log_path: "logs/<task>.log" # path to log file
log_rotate: false # enable log rotation
log_max_size: 5 # max log file size before rotation in MB
rotate_log_path: "logs/<task>.rotate.log" # path to rotation log
rotate_log_max_size: 5 # max rotation log file size in MB
meta_path: ".dmon/<task>.meta.json" # path to meta file
Each task is associated with a meta file (e.g. .dmon/<task>.meta.json
) stored in the current working directory.
The file contains details such as the command, PID, log path, and more.
Do not modify or delete these files manually.
python-dmon © 2025 by Atomie CHEN is licensed under the MIT License.