Repository navigation
Contributing
YABS is a single bash file maintained conservatively: minimal diffs, extreme portability, and edge cases tested in containers before anything lands. Contributions are welcome via issues and pull requests — but read the conventions below first, because the maintainer's bar for merging is "does it help the majority of VPS users without breaking the weird ones".
yet-another-bench-script/
├── yabs.sh # the entire product — ~1200 lines of bash
├── README.md # user docs (has a few known stale bits)
├── LICENSE # WTFPL
├── AGENTS.md # maintainer/agent notes — worth reading before editing
├── bin/
│ ├── README.md # binary build docs
│ ├── compile.sh # native (x86_64) build in Holy Build Box
│ ├── cross-compile.sh # musl cross build, driven by ARCH/CROSS/HOST
│ └── example.json # JSON schema example (stale: v2023-04-23)
└── .github/workflows/
├── ci.yml # ShellCheck gate on push to master
├── build-fio.yml # fio release pipeline
└── build-iperf3.yml # iperf3 release pipeline
The fio/iperf3 binaries are not in the repo — they're release assets built by the workflows. See Precompiled Binaries.
A typical fix goes: reproduce (ideally in a named container) → edit yabs.sh → bash -n → ShellCheck → regression-diff old vs new (-f -i -g -n and -h) → describe the evidence in the issue/PR.
- No dependency additions. The whole point is zero deps and no root. Solutions must use POSIX-ish tools already in play (awk, sed, grep, df, stat…) or degrade gracefully.
- JSON is a public schema. Third-party sites consume it — additive changes only, never rename keys or change value formats/units. See JSON Output.
- Minimal, surgical diffs. Match the file's conventions: tab indentation, lowercase comments that explain why (not what), no gratuitous reformatting or comment churn.
- No noise features for the majority audience. E.g. printing disk model names was declined (#106) as noise for most VPS users.
- iperf server changes are 1:1 swaps. The list is donated bandwidth; additions must improve diversity/capacity as a swap, not grow the list. See Tests: Network.
-
YABS_VERSIONbumps are the maintainer's job — done inside the same commit as the change; don't bump it in a PR. -
Commit messages: short, lowercase, imperative, issue number in parens — e.g.
fix for disk size over-counting with btrfs subvolumes/bind mounts (#130),add tar check and clearer error message for geekbench (#99). - The maintainer commits/pushes/tags/releases manually — don't expect contributors to do any of that.
The standard verification battery:
# syntax
bash -n yabs.sh
# ShellCheck — exactly what ci.yml runs (shellcheck isn't assumed installed)
docker run --rm -v "$PWD/yabs.sh:/y.sh:ro" koalaman/shellcheck:stable -S warning /y.sh
# smoke test: system info only, no tests, exits in seconds
bash yabs.sh -f -i -g -n
# dry-run: flag/binary/connectivity detection output
bash yabs.sh -h
# workflows changed? lint them too
docker run --rm -v "$PWD:/repo:ro" rhysd/actionlint:latest /repo/.github/workflows/*.ymlRegression check: run the unmodified and modified scripts side by side with -f -i -g -n and -h, and diff the output — only the uptime/date/runtime lines should differ.
The project's historical bugs are portability bugs. Docker images used for testing (no sudo needed):
| Image | What it exercises |
|---|---|
alpine:3.20 |
BusyBox userland — df without -t/--total, no grep -P, musl |
busybox:1.36-musl |
bare-minimum BusyBox |
almalinux:9-minimal |
minimal RHEL-ish — no tar (the #99 case) |
debian:12-slim |
typical Debian minimal |
ubuntu:25.10 |
uutils Rust coreutils — Ubuntu's new default |
opensuse/tumbleweed |
container has no awk (real installs do) |
docker run --rm -v "$PWD/yabs.sh:/y.sh:ro" alpine:3.20 sh -c 'apk add bash >/dev/null && bash /y.sh -f -i -g -n'--privileged containers can mount loop devices — how the btrfs-subvolume disk-counting bug (#130) was reproduced.
| Convention | Rule |
|---|---|
| Indentation | tabs |
| Comments | lowercase, explain why; don't narrate the code |
| Version string | maintainer bumps YABS_VERSION in the release commit — leave it alone |
| Commit messages | short, lowercase, imperative, (#NNN) issue ref |
| JSON | additive only; never rename keys or change units |
| Messages to users | quoted literally, terse, actionable where possible |
- Never
stat -fan unfiltered mount — stale NFS/CIFS mounts can hang the run. Filter by fstype first. - Redirection order silences correctly one way:
done 2>/dev/null < file, notdone < file 2>/dev/null(leaks "No such file"). - Keep arithmetic in awk —
bcis not universal (#79). -
LC_ALL=Cis exported early — parsing must stay locale-stable.
Open an issue before a large change so the approach can be agreed first — several past PRs were declined on the principles above rather than on code quality. Good first contributions historically look like: concrete bug with repro (ideally a container recipe), portability fix with evidence on the affected userland, or a docs fix. For binary/toolchain work, see GitHub Actions Automation — and run bin/cross-compile.sh on a copy in a scratch dir, not in the repo.
The server list is donated bandwidth, so the rule is 1:1 swap only: identify which existing entry your proposal replaces, and argue it on geographic/provider diversity, port-range depth, or link capacity. Pure additions get declined regardless of how good the server is — see the two parked PRs (#125, #115) held for a future assessment.
Include: the YABS_VERSION from the banner, uname -a, distro, the exact flags, and the exact output. For portability bugs, a Dockerfile or image name that reproduces the failure is worth more than paragraphs of description — most historical fixes trace back to a reproducible minimal environment (a container, a VM image, a specific fstype).
- Architecture and Script Flow — code layout and conventions
- GitHub Actions Automation — the CI gates your PR will hit
- Precompiled Binaries — building binaries locally
- History — where the conventions came from
Repository · Issues · Binary releases · Usage stats · curl -sL yabs.sh | bash · Licensed under the WTFPL
Using YABS
- Getting Started
- Command-Line Flags
- Understanding the Output
- Interpreting Results
- Benchmarks Are Snapshots
- JSON Output and Integrations
The tests
Internals
Help and project
Background