Files
2GT-RichandClaude Opus 5 98a72e1f7a docs: versioned documentation site, and the four pages that were missing (v0.23.28-beta)
Closes #112.

Source stays `docs/*.md`, rendered by MkDocs-Material and published to GitHub
Pages by Actions. Same repository on purpose: documentation drifts, and
co-location is the only thing that reliably prevents it — the pull request that
changes behaviour changes the description, and review sees both. A separate repo
would double the ceremony and guarantee divergence.

The markdown remains readable when browsing the repository, so the site renders
those files rather than replacing them.

**Versioned from the start**, using mike. Images are published to GHCR and this
project ships betas most days, so readers are routinely running something other
than the newest build; a single "latest" would confidently describe a release
they do not have. Versions follow the product rather than the docs, so the site
and the running image carry the same number.

**Content came first, and it had to.** The docs were eleven days and sixteen
releases stale — SSH keys, bulk commands, the data-cap SMS, poller health and the
timezone setting appeared in exactly zero files between them. Publishing that
would have given documentation missing five of the most consequential features a
polished, authoritative home, and a well-presented wrong answer is worse than an
obviously rough one. Four pages now cover them:

  - cellular.md — signal grading, carrier aggregation, the uplink anchor,
    observed bands, and the data-cap SMS including why it fires early and how to
    calibrate the margin
  - ssh-keys.md — leading with what installing a key costs, because RouterOS
    disables password SSH for that user and the database becomes load-bearing
  - commands.md — why waves exist, and why reading output matters when RouterOS
    reports failure in text rather than an exit code
  - scaling.md — headroom, why it is insufficient on its own, and every tunable

Pull requests build the site with `--strict`, which turns warnings into errors.
That is the point of running it there at all, and it earned itself immediately:
the first build failed on two links to the project README, which sits outside the
docs tree. They are absolute now, so they resolve both in the rendered site and
when reading the markdown on GitHub.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 18:42:40 -07:00

69 lines
2.6 KiB
Markdown

# Bulk commands
[← Documentation index](README.md)
Run one RouterOS console command across many devices, in waves, stopping at the first
failure.
Commands run over **SSH**, because console syntax — `:put`, `:foreach`, `/interface print`
— is not reachable through the binary API, which has its own command tree.
## Why waves exist
A shell loop already runs a command on many hosts, costs nothing, and prints errors as
they happen. What it cannot do is **stop**.
Devices run together within a wave; waves run strictly in sequence. With halt-on-failure
enabled, a mistake reaches one wave rather than the whole fleet. That is the entire reason
to do this here rather than in a terminal — without it, this would be a worse shell loop.
Start with a wave of one. Widen it once the command has proved itself.
## Detecting failure
RouterOS reports most errors in the **output text** rather than through an exit code, so a
rejected command and a successful one are indistinguishable unless the output is read.
Output is scanned for unambiguous markers — `syntax error`, `bad command name`, `no such
item`, `failure:` and similar. The matching is deliberately conservative: mistaking
ordinary output for failure would halt a run that was working, which is worse than the
error it guards against.
## Change Guard
Each device is wrapped by [Change Guard](change-guard.md) by default, so one that stops
answering after the command restores itself.
It is **one click to turn off**. You may know exactly why you are running something that
will drop a device, and a tool that refuses to cut is not a sharp tool.
The one combination that asks for explicit acknowledgement is a command that can sever
management **with the guard disabled** — the only case where nothing catches a mistake.
## Preview
Before running, the preview shows:
- which devices are selected and which wave each falls into
- whether the command matches patterns that can cut management access, and why
- devices with **no SSH credential**, which would otherwise produce a wave of identical
authentication failures
It warns; it never blocks.
## Output
Captured per device and kept with the run. Some commands exist purely for their output —
`:put [:resolve google.com]` across a fleet is a legitimate use — and "it failed" without
the device's own words is not actionable.
## Stopping a run
Cancelling prevents the **next wave**. Devices already executing finish, because that is
the only point at which stopping is safe.
## Requirements
Every targeted device needs an SSH credential: either a password, or a verified
[SSH key](ssh-keys.md). On a fleet of any size, keys are the practical answer.