Skip to main content

systemd-client

PyPI Python License Tests 286 tests Beta Docs

The definitive Python library for systemd. Manage services, create units, read journals, analyze security, control resources, and monitor everything — from Python or the terminal.

Documentation: kalexnolasco.github.io/systemd-client

Features

Category What you can do
Unit Management list, status, cat, start, stop, restart, reload, try-restart, reload-or-restart, enable, disable, mask, unmask, reset-failed, kill
Unit File Builder Create .service, .timer, .socket, .path files with a fluent Python API
Install / Uninstall Deploy unit files, create drop-in overrides, uninstall units
Transient Units Run commands as systemd services without creating files (systemd-run)
Journal Query with filters (unit, priority, time range, grep) + real-time follow
Resource Control Set cgroup limits (CPU, memory, IO), monitor usage, list timers/sockets/dependencies
Security Analysis Boot blame, security scoring (0-10 exposure), unit file verification
sd_notify Notify systemd from your Python service (READY, STATUS, WATCHDOG)
Power Management poweroff, reboot, suspend, hibernate
Environment show/set/unset manager environment variables
Sessions List login sessions and users (loginctl)
Interactive TUI Full dashboard powered by Ratatui (Rust rendering engine)
Dual API Async-first + sync wrappers, identical interfaces
Scope User session (--user) or system-wide (--system)
Zero Dependencies Core library needs nothing beyond Python 3.11+ stdlib

Install

pip install systemd-client            # Core (zero deps)
pip install systemd-client[tui]       # + Interactive TUI (ratatui-py)
pip install systemd-client[dbus]      # + D-Bus backend (dasbus)
pip install systemd-client[all]       # Everything

Quick Start

Manage services

from systemd_client import SystemdClient

with SystemdClient() as client:
    # List all running services
    for unit in client.list_units(unit_type="service"):
        print(f"{unit.name}: {unit.active_state} ({unit.sub_state})")

    # Get detailed status
    status = client.status("my-app.service")
    print(f"PID: {status.main_pid}, Since: {status.active_enter_timestamp}")

    # Control services
    client.restart("my-app.service")
    client.restart_units(["app.service", "worker.service"])  # batch

    # Quick checks
    print(f"Active: {client.is_active('my-app.service')}")

Create services from Python

from systemd_client import ServiceBuilder, TimerBuilder, SystemdClient

# Build a .service file with a fluent API
unit = (ServiceBuilder("my-app")
    .description("My FastAPI Application")
    .exec_start("/usr/bin/python3 /opt/app/main.py")
    .working_directory("/opt/app")
    .user("appuser")
    .environment({"PORT": "8080", "ENV": "production"})
    .restart("on-failure")
    .restart_sec(5)
    .wanted_by("default.target")
    .build())

# Deploy in one step
with SystemdClient() as client:
    client.install(unit)
    client.enable("my-app.service")
    client.start("my-app.service")

# Create a timer (cron replacement)
timer = (TimerBuilder("backup")
    .description("Daily backup")
    .on_calendar("*-*-* 02:00:00")
    .persistent(True)
    .wanted_by("timers.target")
    .build())

Run transient units (systemd-run)

with SystemdClient() as client:
    # One-off command as a systemd service
    result = client.run("/usr/bin/python3 /opt/backup.py", name="backup-task")
    print(f"Running: {result.unit_name}")

    # Schedule a recurring timer
    client.run_on_calendar("daily", "/usr/bin/python3 /opt/cleanup.py")

    # With resource limits
    client.run("make -j8", properties={"MemoryMax": "2G", "CPUQuota": "50%"})

Monitor resources

with SystemdClient() as client:
    # Set cgroup limits
    client.set_property("my-app.service", {"MemoryMax": "512M", "CPUQuota": "25%"})

    # Check resource usage
    usage = client.get_resource_usage("my-app.service")
    print(f"CPU: {usage.cpu_usage_nsec / 1e9:.1f}s")
    print(f"Memory: {usage.memory_current / 1024**2:.0f}MB")

    # List timers
    for timer in client.list_timers():
        print(f"{timer.name}: {timer.time_left}")

Security analysis

with SystemdClient() as client:
    # What's slow at boot?
    for entry in client.analyze_blame()[:5]:
        print(f"{entry.time_us / 1e6:.3f}s  {entry.unit}")

    # Security audit (0 = hardened, 10 = exposed)
    sec = client.analyze_security("my-app.service")
    print(f"Exposure: {sec.exposure}/10.0")

    # Verify unit files before deploying
    errors = client.analyze_verify("my-app.service")

sd_notify — from your Python service

# In a Type=notify systemd service:
from systemd_client.notify import SystemdNotifier

notifier = SystemdNotifier()
notifier.ready()                       # Tell systemd we're up
notifier.status("Listening on :8080")  # Update status text
notifier.watchdog()                    # Keep-alive ping
notifier.stopping()                    # Graceful shutdown

Async API

import asyncio
from systemd_client import AsyncSystemdClient

async def main():
    async with AsyncSystemdClient() as client:
        # Concurrent health check
        services = ["app.service", "worker.service", "scheduler.service"]
        results = await asyncio.gather(
            *(client.is_active(svc) for svc in services)
        )
        for svc, active in zip(services, results):
            print(f"{svc}: {'UP' if active else 'DOWN'}")

asyncio.run(main())

System scope

from systemd_client import SystemdClient, SystemdScope

# Manage system-wide services (requires root)
with SystemdClient(scope=SystemdScope.SYSTEM) as client:
    units = client.list_units(unit_type="service")

CLI

# Unit management
systemd-client list --type service
systemd-client list-unit-files --state enabled
systemd-client status my-app.service
systemd-client cat my-app.service
systemd-client start my-app.service
systemd-client stop my-app.service
systemd-client restart a.service b.service c.service  # batch
systemd-client restart --no-block my-app.service
systemd-client try-restart my-app.service
systemd-client reload-or-restart my-app.service
systemd-client enable my-app.service
systemd-client reset-failed my-app.service
systemd-client kill my-app.service --signal SIGHUP

# Create and deploy unit files
systemd-client create-service --name my-app --exec-start /bin/app --restart on-failure --install
systemd-client create-timer --name backup --on-calendar daily --install
systemd-client install my-app.service --from-file ./my-app.service
systemd-client uninstall my-app.service

# Transient units (systemd-run)
systemd-client run /bin/echo hello --name my-task --wait
systemd-client run /opt/backup.py --on-calendar daily

# Resource monitoring
systemd-client resources my-app.service
systemd-client list-timers
systemd-client list-sockets
systemd-client list-dependencies my-app.service

# Analysis
systemd-client analyze-blame
systemd-client analyze-security my-app.service
systemd-client analyze-verify my-app.service

# Environment and sessions
systemd-client show-environment
systemd-client set-environment MY_VAR=hello
systemd-client list-sessions
systemd-client list-users

# Power management
systemd-client poweroff
systemd-client reboot
systemd-client suspend

# System scope
systemd-client --scope system list --type service
systemd-client --scope system restart nginx.service

# Interactive TUI dashboard
systemd-client tui
systemd-client --scope system tui

# Output formats
systemd-client --json list
systemd-client --no-color status my-app.service

Interactive TUI

Launch the full interactive dashboard:

systemd-client tui

Features:

  • Real-time unit list with color-coded states (green=active, red=failed)
  • Mouse support: click to select, scroll wheel, tab clicks
  • Keyboard: s=start, S=stop, r=restart, e=enable, d=disable, j=journal
  • Type filters: F1=All, F2=Services, F3=Timers, F4=Sockets, F5=Failed
  • Search: / to filter by name
  • Journal panel at bottom with auto-refresh
  • Scope toggle with Tab, 3 tabs: Dashboard, Timers, Help
  • Powered by Ratatui (Rust rendering engine, 30-60 FPS)

Requires: pip install systemd-client[tui]

Architecture

Your Application
    |
    +-- SystemdClient (sync)
    |       |
    +-- AsyncSystemdClient (async)
            |
            +-- SubprocessBackend ---- systemctl --user/--system ----> systemd
            |     (default, zero deps)
            +-- DBusBackend ---------- D-Bus session/system bus ----> systemd
            |     (optional, dasbus)
            +-- AsyncJournalReader --- journalctl --output=json -----> journal
            +-- Builders ------------- .service/.timer/.socket/.path -> unit files
            +-- Analyze -------------- systemd-analyze ----------------> boot/security
            +-- Notify --------------- $NOTIFY_SOCKET -----------------> sd_notify

Requirements

  • Python >= 3.11
  • Linux with systemd
  • systemctl and journalctl on PATH

License

LGPL-2.1-or-later


systemd-client · Documentation · GitHub · PyPI

Metadata

Release files for systemd-client 0.9.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for systemd-client 0.9.2
File Size Uploaded Provenance Actions
systemd_client-0.9.2.tar.gz 113.4 kB With provenance Details for systemd_client-0.9.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for systemd-client 0.9.2
File Interpreter ABI Platform Actions
systemd_client-0.9.2-py3-none-any.whl Python 3 none any Details for systemd_client-0.9.2-py3-none-any.whl

Total release size: 169.3 kB

Release files / systemd_client-0.9.2.tar.gz

Download URL systemd_client-0.9.2.tar.gz
Size 113.4 kB
Tags Source
SHA-256 checksum
How to use checksums
7cce76656301da38d57fe81e2725ab2ea3049306612dfa0c2d894ff4e998df37
BLAKE2b-256 checksum
How to use checksums
51ec52b26dbd593072bff22ea1a26a615fce1061bec4abdcecd8c51d58592f09
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 7, 2026.

Transparency log

Release files / systemd_client-0.9.2-py3-none-any.whl

Download URL systemd_client-0.9.2-py3-none-any.whl
Size 55.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5545466cb6298f61f178bcc5e4b86eafa95e3e774770ec7cede232a87847fc0d
BLAKE2b-256 checksum
How to use checksums
595f133e67c3b7178f5722b03cbe9958007011d27e6a1ae99a3c52d1fd4b1a75
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 7, 2026.

Transparency log

Security for systemd-client 0.9.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for systemd_client-0.9.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 7, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page