Skip to content

Architecture and Script Flow

Mason Rowe edited this page Oct 31, 2026 · 1 revision

Architecture and Script Flow

In short

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.

The whole script at a glance

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
Loading

Startup sequence, in order

  1. Banner + timestamps — TIME_START (YYYYMMDD-HHMMSS, used in JSON) and YABS_START_TIME (epoch, for the elapsed-time line).
  2. Locale — if locale -a lists C, export LC_ALL=C so parsing is locale-stable (decimal commas broke awk parsing for EU users in 2019); otherwise warn and continue.
  3. Arch — uname -m → x64 / x86 / aarch64 / arm / riscv64; anything else exits 1. riscv64 additionally prints the experimental notice. ARM bitness comes from getconf LONG_BIT.
  4. Flags — getopts 'bfdignhr45796jw:s:p:'; GEEKBENCH_6 defaults on.
  5. Local tool detection — fio, iperf3, ping, curl (else wget), tar.
  6. Connectivity probes — ping -4|-6 -c1 -W4 ipv{4,6}.google.com, else curl/wget -4|-6 icanhazip.com.
  7. -h short-circuit — prints usage + all detected state, exits 0. Nothing is downloaded or tested.
  8. Binary release discovery — greps the repo's releases.atom feed for the newest fio-X.Y/iperf3-X.Y tags; pinned fallbacks fio-3.42/iperf3-3.21. Skipped entirely when both tests are skipped.
  9. Basic System Information (see System Information).
  10. JSON header — version/time/os/net/cpu/mem assembled if any JSON flag.
  11. Network Information — ip_info() unless -n.
  12. Working directory — ./$(date -Iseconds | tr : _); a touch probe verifies writability (exit 1 if not). trap catch_abort INT is armed here.
  13. Tests — disk → iperf IPv4 → iperf IPv6 → Geekbench 4→5→6→7.
  14. Teardown — rm -rf $YABS_PATH, elapsed-time line, JSON write/send/print, unset LC_ALL.

Working-directory layout

./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.

Functions

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

External endpoints contacted

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

Dependencies actually used

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).

Exit paths

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).

See also

Clone this wiki locally