#!/bin/bash # omarchy:summary=Measure live internet speed for one direction # omarchy:group=network # omarchy:args=[down|up] set -e direction="${1:-}" probe=1.1.1.1 parallel=8 url_count=3 case "$direction" in down | up) ;; *) echo "Usage: omarchy-network-speedtest [down|up]" >&2 exit 2 ;; esac format_mbps() { awk -v value="$1" 'BEGIN { if (value <= 0) print "0.0" else if (value < 10) printf "%.1f\n", value else printf "%.0f\n", value }' } iface=$(ip route get "$probe" 2>/dev/null | awk '{ for (i = 1; i <= NF; i++) if ($i == "dev") { print $(i + 1); exit } }') if [[ -z $iface || ! -r /sys/class/net/$iface/statistics/rx_bytes || ! -r /sys/class/net/$iface/statistics/tx_bytes ]]; then echo "No active network interface" >&2 exit 1 fi if ! omarchy-cmd-present curl; then echo "curl is required" >&2 exit 1 fi fast_token="YXNkZmFzZGxmbnNkYWZoYXNkZmhrYWxm" fast_api_url="https://api.fast.com/netflix/speedtest/v2?https=true&token=$fast_token&urlCount=$url_count" fast_urls=$(curl -fsS "$fast_api_url" 2>/dev/null | jq -r '.targets[]?.url // empty') if [[ -z $fast_urls ]]; then echo "Failed to fetch speed test endpoints" >&2 exit 1 fi traffic_pids=() cleanup() { local pid for pid in "${traffic_pids[@]}"; do [[ -n $pid ]] || continue pkill -TERM -P "$pid" 2>/dev/null || true kill "$pid" 2>/dev/null || true done for pid in "${traffic_pids[@]}"; do [[ -n $pid ]] || continue wait "$pid" 2>/dev/null || true done } trap cleanup EXIT # Round-robin across the returned URLs so we spread load across Netflix OCA nodes. traffic_worker() { local urls=("$@") local url_count=${#urls[@]} local idx=$RANDOM if [[ $direction == "down" ]]; then while true; do url=${urls[$((idx % url_count))]} curl -fsS -o /dev/null "$url" 2>/dev/null || return idx=$((idx + 1)) done else while true; do url=${urls[$((idx % url_count))]} dd if=/dev/zero bs=1M count=64 2>/dev/null | curl -fsS -o /dev/null -X POST --data-binary @- "$url" 2>/dev/null || return idx=$((idx + 1)) done fi } for (( i = 0; i < parallel; i++ )); do traffic_worker $fast_urls & traffic_pids+=("$!") done rx_before=$(cat "/sys/class/net/$iface/statistics/rx_bytes") tx_before=$(cat "/sys/class/net/$iface/statistics/tx_bytes") any_alive() { local pid for pid in "${traffic_pids[@]}"; do [[ -n $pid ]] || continue if kill -0 "$pid" 2>/dev/null; then return 0 fi done return 1 } while any_alive; do sleep 1 rx_after=$(cat "/sys/class/net/$iface/statistics/rx_bytes") tx_after=$(cat "/sys/class/net/$iface/statistics/tx_bytes") if [[ $direction == "down" ]]; then rate=$(awk -v before="$rx_before" -v after="$rx_after" 'BEGIN { if (after < before) print 0 else print (after - before) * 8 / 1000000 }') else rate=$(awk -v before="$tx_before" -v after="$tx_after" 'BEGIN { if (after < before) print 0 else print (after - before) * 8 / 1000000 }') fi format_mbps "$rate" rx_before=$rx_after tx_before=$tx_after done wait 2>/dev/null || true