Skip to content
wegelPublic

About

A lightweight per-user daemon manager for running, supervising, and restarting background processes

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

27 Commits

Folders and files

Repository files navigation

budom

budom is a per-user background daemon manager for Linux/Unix user processes.

Example terminal log:

$ budom run --kind service --name demo --tag project.example --tag purpose.demo -- /bin/sh -lc 'while true; do echo hello; sleep 1; done'
3mZ7aK2pQ9xT

$ budom ps
ID            NAME  DESIRED  STATE    PID     RESTARTS  TAGS
3mZ7aK2pQ9xT  demo  Running  Running  482311  0         project.example,purpose.demo,kind.service

$ budom logs demo --tail 3
hello
hello
hello

$ budom stop demo

$ budom ps --all
ID            NAME  DESIRED  STATE   PID  RESTARTS  TAGS
3mZ7aK2pQ9xT  demo  Stopped  Exited  -    0         project.example,purpose.demo,kind.service

It provides:

  • run/list/inspect/start/stop/restart/remove lifecycle management
  • a per-user supervisor process (no systemd dependency)
  • reboot recovery with explicit budom recover command
  • restart policies with exponential backoff
  • raw stdout/stderr log capture and size-based rotation
  • stable job names and short/partial ID references
  • tag-based targeting for bulk stop/remove operations
  • explicit service and one-shot job kinds

Build

cargo build --release

Install locally:

install -m 755 target/release/budom ~/.local/bin/budom

Quick Start

Run a long-lived process that Budom may start again after a reboot:

budom run --kind service --name demo --tag project.example --tag purpose.demo -- /bin/sh -lc 'while true; do echo hello; sleep 1; done'

Run a task once. A completed or interrupted one-shot stays stopped across supervisor restarts and budom recover calls:

budom run --kind one-shot --name rebuild-index --tag project.example --tag purpose.index-rebuild -- /path/to/rebuild-index

budom start rebuild-index explicitly arms one more attempt. One-shots reject --restart always and --restart on-failure because those rules conflict with run-once behavior.

Every run command requires --kind service or --kind one-shot. Budom adds the reserved kind.service or kind.one-shot tag. Add concrete project and purpose tags so operators can find related jobs without relying on names.

Load environment variables from a file and override specific keys inline:

budom run --kind service --name demo --env-file .env --env PORT=8080 -- /path/to/server

Delay a service's manual/recovery start without needing extra flags later:

budom run --kind service --name api --start-delay 10s -- /path/to/api

List running jobs:

budom ps

Inspect details:

budom inspect demo --json

Read logs:

budom logs demo --tail 50

Recover desired-running services after reboot:

budom recover

Recover quietly while still returning failure via exit status:

budom recover --quiet

Only recover when supervisor is down:

budom recover --if-supervisor-down

Interleave logs from all daemons matching tags (colorized per daemon):

budom logs --tag api --tag blue --tail 100 -f

Stop one or many jobs:

budom stop demo other-job 01abcde

Start one or many stopped jobs:

budom start demo other-job
budom start --tag api --tag blue

Restart one or many jobs:

budom restart demo other-job
budom restart --tag api --timeout 5s

Remove job state:

budom rm demo --force

Run with tags:

budom run --kind service --name api-a --tag project.example --tag purpose.api --tag blue -- /bin/sh -lc 'sleep 9999'

Filter by tags:

budom ps --tag api --tag blue

Stop/remove by tags:

budom stop --tag api --tag blue
budom rm tag:api --force

Replace an existing named daemon:

# Graceful replace: TERM, wait (default 10s), then KILL if needed
budom run --kind service --name api-a --replace --replace-timeout 15s -- /path/to/new-binary

# Force replace: immediate forced removal of old daemon
budom run --kind service --name api-a --replace --force -- /path/to/new-binary

# Keep the replaced job's metadata and logs under its old ID
budom run --kind service --name api-a --replace --retain-replaced -- /path/to/new-binary
budom inspect OLD_JOB_ID --retained --json
budom logs OLD_JOB_ID --retained --tail 100

--retain-replaced keeps a hard-linked snapshot under $XDG_DATA_HOME/budom/retained/OLD_JOB_ID. Budom prints the retained ID to standard error. The retained status describes the process at snapshot time; it is not a live process state. Use the old job ID or a unique ID prefix with inspect --retained and logs --retained.

ID and Ref Resolution

Commands that take a <ref> accept:

  1. exact name
  2. exact full ID (case-sensitive)
  3. unique ID prefix (including 1 character if unique)
  4. tag:<tag> selectors (for commands supporting multi-target refs, like stop/restart/rm)

If a prefix is ambiguous, the command fails with an ambiguity error.

Development

Checks used for CI/public quality:

cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test

License

MIT (see LICENSE).

Interrupted job creation

The CLI publishes meta.json after the remaining job files and keeps a separate registration lock through the supervisor's first Run request. Named creators also serialize replacement and creation for that name. Incomplete unpublished records do not appear in job lists.

If a creating CLI dies before the supervisor receives Run, a later targeted command can recover that CLI's complete record. It checks the creation marker, account, schemas, and absence of any PID or execution history, then marks the abandoned job stopped before registering it. Inspect, stop, remove, and replacement never execute that abandoned command. An explicit start remains an instruction to execute it. Recovery refuses legacy or malformed abandoned records instead of guessing whether they have run.

This CLI works with the existing one-shot-aware supervisor. Installing it does not require restarting that supervisor or disturbing other jobs and log pipes. A newly started supervisor also leaves an abandoned creation stopped. Do not kill a running supervisor to upgrade it: the current supervisor owns child log pipes and cannot transfer them to a replacement.

Run the normal test suite with cargo test --workspace. To repeat registration and real CLI interruption tests against an older supervisor binary:

BUDOM_TEST_OLD_BINARY=/absolute/path/to/prior/budom cargo test registration

About

A lightweight per-user daemon manager for running, supervising, and restarting background processes

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages