Skip to content

berkaycubuk/binary-manager

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bm — Binary Manager

A tiny terminal tool for running small binaries on a Linux box as per-user systemd services. It wraps systemctl --user, so you get start/stop/restart, crash auto-restart, reboot persistence, and per-binary log files — no sudo day-to-day, and no daemon of its own to babysit.

Single static binary. JSON registry. Deliberately minimal.


Why bm?

If you SSH into a Linux server and just want to keep a binary running, the usual answers all carry baggage:

  • Writing .service files by hand is tedious and easy to get wrong.
  • pm2 / supervisor install their own supervisor daemon and restart logic — redundant on a systemd box, since systemd already does this natively.
  • Docker / Compose is great for stacks, but overkill when you have one compiled binary and just want it to stay up.

bm takes the lightest path: it generates systemd user units for you and gets out of the way. systemd supervises; bm just makes it one command to set up. No daemon, no containers, no root (after a one-time enable-linger).

When not to use bm: if you need process isolation, reproducible images, multi-container stacks, or a team-grade deployment pipeline — use Docker. If you want Node.js cluster mode or language-specific features — use pm2. bm is for the simple middle: "run this binary, restart it if it dies, survive reboots, give me logs."

Features

  • Daemonsbm add writes a user unit with Restart=always (default), so your binary comes back after a crash and at boot.
  • Scheduled jobs--every 1h or --on daily renders a oneshot service
    • a systemd timer (a friendlier cron). bm run triggers it on demand.
  • No sudo day-to-day — runs entirely as your user via systemctl --user.
  • Survives logout/reboot — via systemd "lingering" (one-time setup).
  • Per-binary logs — stdout/stderr appended to ~/.local/share/bm/logs/<name>.log.
  • Upsert by namebm add the same name again to update config and restart.
  • XDG-aware — honours XDG_CONFIG_HOME / XDG_DATA_HOME.

Requirements

  • A Linux server with systemd (Ubuntu, Debian, Fedora, Arch, …). Commands that need systemctl exit gracefully on macOS / WSL — bm is meant to run on the server.
  • Go only to build it; the result is a standalone binary with no runtime dependency.

Install

From source (produces a bm binary on your PATH):

git clone https://github.com/berkaycubuk/binary-manager
cd binary-manager
make build            # or: go build -o bm .
sudo install -m 0755 bm /usr/local/bin/bm   # optional, to put it on PATH

Cross-build on your dev machine and ship to the VPS (the VPS doesn't need Go installed):

# pick the arch that matches your VPS CPU
make install-linux VPS_ARCH=amd64 VPS_HOST=user@your-vps
# then on the VPS: ~/bm setup

Or by hand:

GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -o bm .
scp bm user@your-vps:~/bm

One-time setup on the VPS

bm setup                          # checks systemd, dirs, and linger
sudo loginctl enable-linger $USER # do this once: survive logout/reboot

bm setup will tell you if lingering is off and print the exact command. That one sudo is the only privilege escalation you'll ever need.

Quick start

bm add web --exec /usr/bin/python3 -- -m http.server 8000   # register + start
bm list                                                      # see everything
bm logs web -f                                               # follow logs
bm remove web                                                # take it down

Usage — always-on daemons

# Register a binary (starts it immediately). Args after '--' go to the binary.
bm add web --exec /usr/bin/python3 -- -m http.server 8000
bm add bot --exec ~/bin/mybot --env TOKEN=secret -- --verbose
bm add job --exec ~/bin/etl --restart on-failure --no-start

# See what you've got
bm list
bm status            # all binaries, detailed
bm status web        # one binary, detailed

# Lifecycle
bm start bot
bm stop bot
bm restart bot       # use this after you scp a new binary in

# Logs (tail-style)
bm logs web
bm logs web -f
bm logs web -n 100

# Remove (stops, disables, deletes unit; leaves your binary + log on disk)
bm remove web

bm add flags

Flag Default Description
--exec PATH required Absolute path to the binary (~ is expanded)
--cwd PATH binary's dir Working directory
--env KEY=VAL Environment variable (repeatable)
--restart POLICY always always | on-failure | no (daemons only)
--desc TEXT Human-readable description
--every INTERVAL Run on an interval: 15m, 2h, 1d, 30s
--on CALENDAR Run on a systemd calendar: daily, hourly, *-*-* 03:00:00
--no-start off Register without (re)starting now
-- Everything after -- is passed verbatim to the binary

Notes:

  • Names must be lowercase, start with a letter/number, and use only [a-z0-9_-] (they become part of the systemd unit name) — e.g. web, api-1.
  • --every and --on are mutually exclusive (pick one schedule per job).
  • Re-running bm add <same-name> updates config in place and restarts.

Updating a binary you've developed

Just replace the file and restart — bm reuses the existing unit:

scp mybot user@your-vps:~/bin/mybot
ssh user@your-vps 'bm restart bot'

To change how it runs (args, env, restart policy), run bm add bot ... again with the same name — it's an upsert.

Usage — scheduled jobs

For binaries that should run periodically instead of staying up (a backup, a report, a poller), pass --every <interval> or --on <calendar>. bm writes a oneshot service plus a systemd timer that triggers it:

bm add backup --exec ~/bin/backup --every 1h            # interval
bm add report --exec ~/bin/report --on daily            # systemd OnCalendar keyword
bm add tick   --exec ~/bin/tick --on "*-*-* 03:00:00"   # every day at 03:00

Scheduled jobs behave slightly differently from daemons:

  • bm start <name> arms the timer; bm stop <name> disarms it (and stops any running instance). bm list / bm status show the next-run countdown.
  • bm run <name> triggers an immediate run now, without touching the schedule — handy for testing a job.
  • bm restart <name> re-arms the timer (picks up a changed schedule).
  • Scheduled jobs are Type=oneshot; --restart does not apply to them. Missed firings are caught up on boot (Persistent=true), so a daily backup still runs even if the box was off at the scheduled time.

Where things live

What Path
Registry (your bm add config) ~/.config/bm/registry.json
systemd user units ~/.config/systemd/user/bm-<name>.service
Timer units (scheduled jobs) ~/.config/systemd/user/bm-<name>.timer
Per-binary logs `~/.local/share/bm/logs/.log

Honours XDG_CONFIG_HOME / XDG_DATA_HOME if set.

Command reference

Command What it does
bm setup One-time environment check
bm add <name> Register / update a binary (daemon by default; --every/--on for scheduled)
bm list (ls) Table of all binaries + status (incl. next run)
bm status [name] Detailed status (one or all)
bm start <name> Start a daemon, or arm a schedule
bm stop <name> Stop a daemon, or disarm a schedule
bm restart <name> Restart a daemon, or re-arm a schedule
bm run <name> Trigger an immediate run (ignores the schedule)
bm logs <name> Tail the log (-f follow, -n N lines)
bm remove <name> (rm) Stop, disable, delete unit (+timer), drop from registry
bm version Print version

Notes / limitations

  • Restart policies — daemons default to Restart=always (good for long-running processes). Use --restart on-failure for things that should stay stopped after a clean exit, or --restart no to never auto-restart. Scheduled jobs ignore this.
  • Env vars are stored in plaintext in the generated unit file (Environment=KEY=VAL), not in a secret manager. Don't put high-value secrets there; prefer reading from a file your binary loads itself.
  • Logs are appended, never rotated. For long-running daemons, wire up logrotate (or have your binary handle its own rotation) to keep them bounded.
  • Your binary and its log file are never deleted by bm; remove only deletes the systemd unit/timer and the registry entry.
  • Single-user VPS. Multi-user isolation and production-grade hardening are out of scope — use full systemd (or Docker) for that.

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors