Repository navigation
Architecture and Script Flow
YABS is a single ~1200-line bash script that runs strictly top to bottom: print a banner, lock the locale, detect the architecture, parse flags, check connectivity, print system info, then run disk → network → CPU tests, clean up, and emit JSON if asked. Functions are defined inline where they're used. There is no state file, no daemon, no config — everything lives in variables and one temporary directory.
flowchart TD
A["banner + date<br/>TIME_START / YABS_START_TIME"] --> B{"locale -a has 'C'?"}
B -->|yes| B1["export LC_ALL=C"]
B -->|no| B2["warn: 'locale C not detected...'"]
B1 --> C["ARCH = uname -m mapping<br/>x64/x86/aarch64/arm/riscv64"]
B2 --> C
C -->|unsupported| CX["print 'Architecture not supported by YABS.'<br/>exit 1"]
C --> D["getopts 'bfdignhr45796jw:s:p:'<br/>(GB6 on by default)"]
D --> E["detect local fio, iperf3, ping, curl|wget, tar"]
E --> F["IPv4/IPv6 probes:<br/>ping google ± icanhazip"]
F -->|neither| F1["warn: 'Both IPv4 AND IPv6...'"]
F --> G{"-h?"}
F1 --> G
G -->|yes| G1["print help + detected state<br/>exit 0"]
G -->|no| H["fetch releases.atom -> latest fio-X.Y / iperf3-X.Y<br/>(fallback: pinned tags)"]
H --> I["Basic System Information"]
I --> J{"-n?"}
J -->|no| K["ip_info(): ip6.me + ip-api.com<br/>Network Information"]
J -->|yes| L
K --> L["touch ./<ts>.test -> writeable?<br/>mkdir ./<ts>/"]
L -->|not writable| LX["'You do not have write permission...'<br/>exit 1"]
L --> M["trap catch_abort INT"]
M --> N{"disk test? (-f/-d, space, ZFS)"}
N --> O["fio x4 block sizes<br/>or dd fallback"]
O --> P{"iperf? (-i)"}
P --> Q["IPv4 table: 7 servers x send/recv<br/>IPv6 table: same"]
Q --> R{"geekbench? (-g)"}
R --> S["for each of GB 4/5/6/7 selected:<br/>download or reuse, --unlock?, --upload,<br/>parse scores"]
S --> T["rm -rf ./<ts><br/>'YABS completed in X min Y sec'"]
T --> U{"JSON requested?"}
U -->|"w"| U1["write file"]
U -->|"s"| U2["POST to url(s)"]
U -->|"j"| U3["print to stdout"]
U1 --> V["unset LC_ALL, exit 0"]
U2 --> V
U3 --> V
U -->|none| V
-
Banner + timestamps —
TIME_START(YYYYMMDD-HHMMSS, used in JSON) andYABS_START_TIME(epoch, for the elapsed-time line). -
Locale — if
locale -alistsC,export LC_ALL=Cso parsing is locale-stable (decimal commas broke awk parsing for EU users in 2019); otherwise warn and continue. -
Arch —
uname -m→x64/x86/aarch64/arm/riscv64; anything else exits 1.riscv64additionally prints the experimental notice. ARM bitness comes fromgetconf LONG_BIT. -
Flags —
getopts 'bfdignhr45796jw:s:p:';GEEKBENCH_6defaults on. -
Local tool detection —
fio,iperf3,ping,curl(elsewget),tar. -
Connectivity probes —
ping -4|-6 -c1 -W4 ipv{4,6}.google.com, elsecurl/wget -4|-6 icanhazip.com. -
-hshort-circuit — prints usage + all detected state, exits 0. Nothing is downloaded or tested. -
Binary release discovery — greps the repo's
releases.atomfeed for the newestfio-X.Y/iperf3-X.Ytags; pinned fallbacksfio-3.42/iperf3-3.21. Skipped entirely when both tests are skipped. - Basic System Information (see System Information).
-
JSON header —
version/time/os/net/cpu/memassembled if any JSON flag. -
Network Information —
ip_info()unless-n. -
Working directory —
./$(date -Iseconds | tr : _); atouchprobe verifies writability (exit 1 if not).trap catch_abort INTis armed here. - Tests — disk → iperf IPv4 → iperf IPv6 → Geekbench 4→5→6→7.
-
Teardown —
rm -rf $YABS_PATH, elapsed-time line, JSON write/send/print,unset LC_ALL.
./2026-10-31T02_13_22-04_00/ # $YABS_PATH = ./$(date -Iseconds) with : -> _
├── disk/
│ ├── fio # downloaded fio_$ARCH (if no local fio)
│ ├── test.fio # 2 GiB / 512 MiB fio test file
│ └── <ts>.test # dd-fallback 1 GiB file
├── iperf/
│ └── iperf3 # downloaded iperf3_$ARCH
└── geekbench_<N>/ # per Geekbench version run
└── Geekbench-<ver>-Linux/… # tarball contents (--strip-components=1)
Outside the directory, the script may also write geekbench_claim.url and the -w JSON file — both in $PWD, both intentionally persistent.
Defined inline in the script, in order of appearance:
| Function | Purpose |
|---|---|
format_size |
KiB → x.y KiB/MiB/GiB/TiB for RAM/swap/disk display |
ip_info |
ip6.me + ip-api.com lookup; prints Network Information, appends ip_info JSON |
catch_abort |
SIGINT handler: rm -rf $YABS_PATH, unset LC_ALL, exit 0 |
format_speed |
KiB/s → decimal KB/s/MB/s/GB/s (thresholds 977 / 976563 KiB/s) |
format_iops |
IOPS → x.yk when ≥ 1000 |
disk_test |
fio setup pass + the per-block-size randrw runs and terse parsing |
dd_test |
3× sequential dd write/read fallback + averages |
iperf_test |
one server, both directions: retry loops, -P 8, latency ping |
launch_iperf |
prints a table header and loops the server list for one IP mode |
launch_geekbench |
per-version Geekbench: URL selection, download/reuse, unlock, run, score parse, output |
calculate_time_taken |
YABS completed in X min Y sec + runtime JSON block |
| Host | Purpose | Protocol |
|---|---|---|
yabs.sh |
The domain you curl the script from; UA-based redirect to GitHub raw | HTTPS |
ipv4.google.com / ipv6.google.com
|
Connectivity probes | ICMP ping |
icanhazip.com |
Connectivity fallback | HTTP(S) GET |
github.com/.../releases.atom |
Latest binary release tags | HTTPS GET |
github.com/.../releases/download/<tag>/<bin> |
fio/iperf3 binaries | HTTPS GET |
ip6.me/api/ |
Detect preferred-egress IP + family | HTTP GET |
ip-api.com/json/<ip> |
Geolocation | HTTP GET (free tier has no HTTPS) |
lon.speedtest.clouvider.net, iperf-ams-nl.eranium.net, speedtest.uztelecom.uz, speedtest.sin1.sg.leaseweb.net, la.speedtest.clouvider.net, speedtest.nyc1.us.leaseweb.net, speedtest.sao1.edgoo.net
|
iperf3 test servers (TCP 5200–5210, 9204–9240) + ping | TCP + ICMP |
cdn.geekbench.com |
Geekbench tarballs | HTTPS, IPv4 only |
browser.geekbench.com |
Result upload (by Geekbench itself) + results-page scrape for scores | HTTPS |
whatever -s names |
JSON submissions | HTTP(S) POST |
Core (POSIX/coreutils, assumed present): awk, sed, grep, cut, tr, df, stat, free, uptime, uname, date, shuf, timeout, dd, touch, mkdir, rm, locale, getconf, cat, head, tail, sleep, printf, plus /proc and /sys.
Detected-and-adapted: curl or wget (at least one needed for anything network), ping (latency column + connectivity probes), lscpu (ARM/RISC-V CPU info), systemd-detect-virt (VM Type), tar (Geekbench extraction), fio/iperf3/geekbenchN (local installs preferred over downloads).
The script deliberately avoids non-portable tools: no bc (removed Nov 2023, #79 — awk does all arithmetic), no grep -P (removed Mar 2023, #59), no jq (JSON is string-built, responses are parsed with sed/awk).
| Situation | Exit code |
|---|---|
| Clean finish | 0 |
-h |
0 |
Ctrl+C (after trap installed) |
0 via catch_abort
|
| Unknown flag | 1 (getopts *) case) |
| Unsupported architecture | 1 |
No write permission in $PWD
|
1 |
Individual test failures never abort the run — they print a message and either fall back (fio→dd) or skip the section (iperf download failure, Geekbench failure).
- System Information — the info blocks in detail
- Tests: Disk (fio) / Tests: Network (iperf3) / Tests: CPU (Geekbench) — each stage in depth
- Precompiled Binaries — the release discovery mechanism
- Supported Platforms — portability constraints behind the dependency choices
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