Python
Linux
Daemon
Service
Script

How to make a Python script run like a service or daemon in Linux

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Running a Python script as a Linux service is best done with systemd. It provides process supervision, auto-restart, startup ordering, logs, and security controls that ad-hoc background commands cannot match.

This article shows a production-ready systemd unit setup for Python daemons.

Core Sections

1) Create a stable script entrypoint

python
1# /opt/myapp/worker.py
2import time
3
4while True:
5    print("working...")
6    time.sleep(10)

Use absolute paths and deterministic startup behavior.

2) Create systemd unit file

ini
1# /etc/systemd/system/myapp.service
2[Unit]
3Description=My Python Worker
4After=network.target
5
6[Service]
7Type=simple
8User=myapp
9Group=myapp
10WorkingDirectory=/opt/myapp
11ExecStart=/usr/bin/python3 /opt/myapp/worker.py
12Restart=always
13RestartSec=5
14Environment=PYTHONUNBUFFERED=1
15
16[Install]
17WantedBy=multi-user.target

Set non-root user and explicit working directory.

3) Enable and start service

bash
1sudo systemctl daemon-reload
2sudo systemctl enable myapp.service
3sudo systemctl start myapp.service
4sudo systemctl status myapp.service

enable ensures startup on boot.

4) Inspect logs with journalctl

bash
sudo journalctl -u myapp.service -f

This is the fastest way to diagnose startup/import/path errors.

5) Hardening and deployment tips

Add venv interpreter path in ExecStart, set environment variables via EnvironmentFile, and restrict permissions. For networked apps, configure timeouts and graceful SIGTERM handling for clean restarts.

6) Production checklist for Linux Python service deployment

A technically correct snippet is only the start. Before you consider this pattern complete, define operational acceptance criteria that match real usage. Pick one reliability metric, one correctness metric, and one performance metric, then test each with representative input. For example, reliability might be failure rate under retries, correctness might be output agreement with known-good fixtures, and performance might be p95 runtime under expected load. This moves the implementation from tutorial code to maintainable production behavior.

Create a short executable checklist so future contributors can validate changes quickly. Keep the checklist in version control and run it in CI whenever possible. A typical format is: validate environment assumptions, run a minimal happy-path example, run one malformed-input case, and confirm observable logs include enough context for troubleshooting. If external systems are involved, add a dry-run mode that avoids destructive actions while still exercising integration paths.

bash
1# Example validation flow
2make test
3make lint
4./scripts/smoke_check.sh

Operational ownership should also be explicit. Decide who responds when this component fails, what alert threshold should trigger investigation, and what rollback or fallback path is acceptable. Even a simple fallback plan, such as disabling a feature flag or reverting one deployment, can reduce incident duration significantly. For data-oriented workflows, add input and output sampling logs so regressions can be diagnosed without reproducing the full workload locally.

Finally, document constraints and non-goals. Clarify what the current approach handles well and what it does not attempt to solve. This prevents accidental misuse and repeated redesign debates. A concise limitations section plus automated checks is often enough to keep a small utility pattern dependable over time, even as team members and environments change.

Common Pitfalls

  • Running service as root when not required.
  • Using relative paths that fail under systemd execution context.
  • Forgetting daemon-reload after editing unit files.
  • Not enabling service, causing it to disappear after reboot.
  • Ignoring logs and guessing at startup failures.

Summary

Use systemd to run Python scripts as reliable services on Linux. Define a clear unit file, run under least privilege, and use journald logs for troubleshooting. This approach is stable for both simple daemons and production workloads.

In long-lived projects, capture these rules in a short team guideline and back them with one automated smoke test. That combination keeps behavior consistent across refactors and onboarding, and it prevents the same category of errors from recurring when commands, libraries, or infrastructure versions change over time.


Course illustration
Course illustration

All Rights Reserved.