Skip to main content

A polite, daemon-less batch distributor for opportunistic SSH targets.

Project description

yuj

CI Docs PyPI License: MIT

Full documentation →

yuj scatters work across idle lab desktops over SSH and pulls the results back. A self-healing watchdog on each host keeps the batch running through crashes and reboots, so you don't need root on the machines or a scheduler watching over them.

If you have a 'batch of jobs' that can be split into independent items, you can use yuj to achieve effective and fast parallelisation. Each item runs on one host on its own, with no communication between items and no shared memory.

yuj will not work if your job needs nodes to talk to each other mid-run (MPI, a shared address space).

Quickstart

# Python job
pipx install yuj
mkdir my-job && cd my-job
yuj init --template python    # scaffold worker.py + config
$EDITOR fleet.csv             # add hosts (username, IP, password or key)
yuj bootstrap                 # install Python (uv) on each host, no root
yuj deploy && yuj submit      # push code, start watchdog + cron
yuj status --watch 30         # live dashboard
yuj pull --loop 60
yuj decommission lab-desk-1 --at "9am tomorrow"
# R job
pipx install yuj
mkdir my-r-job && cd my-r-job
yuj init --template r         # scaffold worker.R + environment.yaml
$EDITOR fleet.csv
yuj bootstrap                 # install R via micromamba, no root or compiler
yuj deploy && yuj submit
yuj status --watch 30
yuj pull --loop 60

See the full quickstart and R users guide in the docs.

How it works

  1. provision (optional): if you only have an admin/sudo login, yuj provision creates a dedicated worker user with key-only auth and writes a provisioned-fleet.csv you can hand to the rest of the commands. This is the one step that needs privilege.
  2. deploy: rsync your code + data to $HOME on each host. Aborts up front if a configured path is missing locally.
  3. submit: dry-run the work command on one host first (a canary), so a broken job aborts before it installs a watchdog everywhere. Then install a watchdog and a cron entry that restarts it every 15 min. The watchdog runs your work loop, detects stalls (no new output in N min), and relaunches.
  4. resume: the work loop skips any item whose output file already exists. This is the only reliable checkpoint when a worker crashes mid-write.
  5. pull: parallel rsync of outputs back to a central directory, tolerant of hosts being down.
  6. survive: supervision lives in cron on each host, so a rebooted host resumes within 15 min with no controller involved.

Caveats

  • Passwords work but trigger fail2ban on repeated auth failures. Pass key_path in fleet.csv to avoid this.
  • A few failed auths can get your IP banned for hours. yuj diagnose classifies what's wrong (net down / sshd down / banner drop / auth refused); it won't hammer a banned host.
  • Passwords are stored as plain text in fleet.csv. The .gitignore excludes it by default, but double-check before pushing.
  • yuj status shows a warning when someone is at the console. Use yuj decommission --at "9am tomorrow" to hand machines back at a civilised time.

Development

uv sync --locked              # create the venv and install dev deps
uv run pytest                 # tests
uv run ruff check .           # lint
uv run ruff format .          # format
uv run mypy src               # strict type-check

License

MIT

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

yuj-0.1.0.tar.gz (205.7 kB view details)

Uploaded Source

Built Distribution

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

yuj-0.1.0-py3-none-any.whl (95.2 kB view details)

Uploaded Python 3

File details

Details for the file yuj-0.1.0.tar.gz.

File metadata

  • Download URL: yuj-0.1.0.tar.gz
  • Upload date:
  • Size: 205.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for yuj-0.1.0.tar.gz
Algorithm Hash digest
SHA256 baa2dcd500c0d24f4e8a2903a3121380f8c8d5a7f627703474dacab58f7899be
MD5 851e2e7aac4a0689706d146d48742b03
BLAKE2b-256 17d7a35989e50fd0775b7648ea5dc7301433bfcc30fcea602afa70aa7f112371

See more details on using hashes here.

Provenance

The following attestation bundles were made for yuj-0.1.0.tar.gz:

Publisher: release.yml on saketlab/yuj

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

File details

Details for the file yuj-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: yuj-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 95.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for yuj-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 90a45e977ac67f969634d7d1b124fbaf4486af41cc7ca7d98f8f8acac20dea42
MD5 0094cc642215317b6a121973fff202d6
BLAKE2b-256 351b5ef91ebcab41aa88e9f946f074247bf90f5be9273509c37f7a0ccbbbb962

See more details on using hashes here.

Provenance

The following attestation bundles were made for yuj-0.1.0-py3-none-any.whl:

Publisher: release.yml on saketlab/yuj

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