Skip to main content

Read-only diagnostic CLI for Ubuntu systems, with explained findings and stable JSON output.

Project description

ubuntu-doctor

Read-only diagnostic CLI for Ubuntu systems, with explained findings and stable JSON output.

CI License: MIT

Problem

When an Ubuntu machine slows down or misbehaves, the first diagnosis is always the same sequence of manual commands: df -h, free -h, systemctl --failed, ss -tulpn, scanning /var/log, checking for broken packages. It is repetitive, easy to miss a step, and the results end up scattered across several outputs with no interpretation.

ubuntu-doctor runs those checks for you and returns a prioritized, explained report: what is critical, what is a warning, what is healthy — each finding with a suggested next step. It is read-only by design and never changes the system.

Features

  • Disk usage per mount point (snap/pseudo filesystems excluded)
  • Memory and swap, judged by available memory
  • CPU load average and the heaviest processes (by name, no command lines)
  • Failed systemd units
  • Listening TCP/UDP ports, with owning process where visible
  • Oversized log files under /var/log
  • Broken packages and pending (security) updates
  • Colored text, stable JSON (a documented contract), and sanitized Markdown output
  • Severity-based exit codes and graceful degradation without privileges

Architecture

See docs/architecture.md. The rule is: collectors don't decide, rules don't collect, renderers don't calculate, and the domain core never touches the OS.

flowchart LR
    CLI[cli.py] --> ORCH[orchestrator]
    ORCH --> COL[collectors]
    COL --> RULES[rules]
    RULES --> FIND[Finding / Report]
    FIND --> REND[render: text / json / markdown]

Requirements

  • Ubuntu 22.04 LTS or newer (Debian-family)
  • Python 3.11+

Installation

Once published, the recommended install is with pipx:

pipx install ubuntu-doctor

From a clone, using uv:

uv sync
uv run ubuntu-doctor --help

Usage

ubuntu-doctor full-check          # run every check and aggregate
ubuntu-doctor disk --json         # a single area, machine-readable
ubuntu-doctor cpu --top 10        # ten heaviest processes
ubuntu-doctor export-report -o report.md

Example full-check output (hostname anonymized):

CRITICAL Failed unit: virtualbox.service  [failed]
         LSB: VirtualBox Linux kernel module
         → Inspect each failed unit with: systemctl status <unit> and
           journalctl -u <unit> -b. ubuntu-doctor never restarts services for you.
UNKNOWN  Broken packages
         Could not determine broken packages: dpkg: ... Permission denied
         → Re-run with sufficient privilege to check: sudo dpkg --audit.
OK       Disk usage: /  [14.6%]
         14.6% used (741.7 GB free of 914.8 GB)
OK       Memory usage  [36.9%]
         36.9% used (14.7 GB available of 23.3 GB); swap 0.0% of 19.7 GB
OK       CPU load  [3.41]
         load average 1.96 / 3.41 / 3.66 on 8 core(s)
OK       Listening ports  [26]
         26 listening ports (17 tcp, 9 udp).

Overall: CRITICAL  (myhost)

Commands

Command Purpose
full-check Run every check and aggregate
disk, memory, cpu, services, network, logs, packages Run a single area
export-report Write a sanitized Markdown report
version Print the version

Common options: --json, --verbose, --config PATH. cpu also takes --top N; export-report takes --output/-o PATH and --force.

Exit codes: 0 no problem · 1 at least one CRITICAL · 2 usage/config error · 3 internal error.

Configuration

Thresholds resolve from three layers, each overriding the previous: defaults → TOML file → environment.

TOML file (via --config PATH, or ~/.config/ubuntu-doctor/config.toml if it exists):

[thresholds]
disk_warn_percent = 80
disk_crit_percent = 90
mem_warn_percent = 85
mem_crit_percent = 95
log_warn_bytes = 104857600      # 100 MB
log_crit_bytes = 1073741824     # 1 GB

Environment variables override the file:

Variable Overrides
UBUNTU_DOCTOR_DISK_WARN / UBUNTU_DOCTOR_DISK_CRIT Disk usage %
UBUNTU_DOCTOR_MEM_WARN / UBUNTU_DOCTOR_MEM_CRIT Memory usage %
UBUNTU_DOCTOR_LOG_WARN / UBUNTU_DOCTOR_LOG_CRIT Log size (bytes)

There are deliberately no --threshold-* flags: the file and environment already cover per-threshold overrides without cluttering every command.

The JSON contract

--json emits a stable object with a schema_version (currently 1). Consumers can rely on the shape; any breaking change bumps schema_version and the package's major version.

Testing

uv run pytest          # 149 tests, 100% coverage, fully offline
uv run ruff check .
uv run mypy

Every test runs offline and deterministically. Command-based checks are tested against real output captured once into tests/fixtures/.

Design decisions

Recorded as ADRs in docs/adr/: pure collectors for testability, psutil over /proc parsing, read-only by design, and threshold/UNKNOWN semantics.

Troubleshooting

  • "Could not determine broken packages: ... Permission denied"dpkg --audit needs the dpkg lock, which requires privilege. This is expected: the check degrades to UNKNOWN rather than failing. Run sudo dpkg --audit yourself to check.
  • Listening ports show no processss cannot name processes owned by other users without privilege. The port is still listed; only the owner is hidden.
  • command not found for a check — on a minimal system systemctl, ss or apt may be absent; that check reports UNKNOWN and the rest still run.

Limitations

  • Ubuntu/Debian only.
  • Read-only: it diagnoses, it never fixes.
  • No history and no continuous monitoring in v1 (each run is a snapshot).
  • File-permission auditing is deliberately omitted (too prone to false positives).
  • Behavior inside containers can differ (cgroup-reported limits).

Roadmap

  • v1.1: Docker container check; snap packaging.
  • v1.2: optional history in SQLite with run-to-run comparison.
  • v2.0: extract the collection layer into a reusable linuxfacts library.

Contributing

Issues and PRs welcome. Please keep the tool read-only, keep tests offline, and run ruff, mypy and pytest before opening a PR. See the issue and PR templates.

License

MIT — see LICENSE.

Contact

David Oliveira · davidoliveira.devbr@gmail.com

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ubuntu_doctor-1.0.0.tar.gz (100.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ubuntu_doctor-1.0.0-py3-none-any.whl (32.2 kB view details)

Uploaded Python 3

File details

Details for the file ubuntu_doctor-1.0.0.tar.gz.

File metadata

  • Download URL: ubuntu_doctor-1.0.0.tar.gz
  • Upload date:
  • Size: 100.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for ubuntu_doctor-1.0.0.tar.gz
Algorithm Hash digest
SHA256 cddca0f8931f4657372e903785780caf0b0f55716a0f589124c6d6d1787958b1
MD5 d5d8364e04ccfcde7a64676c73bd03c9
BLAKE2b-256 f6fc62dfc130751304d5ae2548a1eed509ad3919054517b4baf6e6067b412519

See more details on using hashes here.

Provenance

The following attestation bundles were made for ubuntu_doctor-1.0.0.tar.gz:

Publisher: release.yml on david-oliveira-dev/ubuntu-doctor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ubuntu_doctor-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: ubuntu_doctor-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 32.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for ubuntu_doctor-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a4268e1e4db72e0421bf4e3a261310c992acbcaad6e840c519bfb75f56c57e7b
MD5 3226a28ec7c61f5160638e0202b4f0d2
BLAKE2b-256 88fde36a2837528bea53d4c2e5a1ef5f3eab868837321b2188801b6ba7083997

See more details on using hashes here.

Provenance

The following attestation bundles were made for ubuntu_doctor-1.0.0-py3-none-any.whl:

Publisher: release.yml on david-oliveira-dev/ubuntu-doctor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page