Skip to content

Instantly share code, notes, and snippets.

@hackerb9
Last active May 7, 2024 20:02
Show Gist options
  • Save hackerb9/43dba9ce91b967cc7f4bd5ada5037d81 to your computer and use it in GitHub Desktop.
Save hackerb9/43dba9ce91b967cc7f4bd5ada5037d81 to your computer and use it in GitHub Desktop.
Busybox compatible simple speedtest that downloads a file to /dev/null. Useful for sshing into various routers and seeing where the bottleneck is.
#!/bin/sh
# Silly speed test just by downloading a file directly to /dev/null
# Useful on routers which only have busybox installed.
# ↄ⃝🄯 B9 2016, 2018, 2023. Creative Commons Zero.
# NOTA BENE: cachefly has worked for over a decade, however they may
# be getting tired of scripts like this. Starting February 2023, their
# 100mb.test file is empty and the 50mb.test file holds 100MB.
dotest() {
# $1 is which file to grab 200, 100, 50, 10, or 1 (megabytes).
# $2 (optional) is how many megabytes that file actually is.
filename=${1}
megabytes=${2:-$1}
wget=$(whichwget)
bloburl=http://cachefly.cachefly.net/${filename}mb.test
blobsize=$(($megabytes*1024*1024))
if which time >/dev/null 2>/dev/null; then
totaltime=$(dotime $wget "$bloburl" -O /dev/null)
else
start=$(date +%s)
$wget "$bloburl" -O /dev/null
stop=$(date +%s)
totaltime=$(( (stop-start) * 1000))
fi
echo Total time was $totaltime milliseconds for $blobsize bytes
if [ $totaltime -ne 0 ]; then
bps=$(((1000*blobsize*8)/totaltime))
echo $((bps/1024/1024)) Mbps
echo $((bps/1024)) kbps
else
echo "Incalculable"
fi
}
dotime() {
# If we have the "time" program, use it for more precision
# This is a wrapper since we want to return just
# the number of milliseconds. Also, we handle different
# formats for output from `time`.
output=$("time" "$@" 2>&1 | tee /dev/tty)
if [ -z "$output" ]; then
echo "Error: Is the time (`which time`) program broken?" >&2
echo "Why was there no stderr?" >&2
echo 0
return
fi
# time's output usually looks like this:
# Connecting to cachefly.cachefly.net (205.234.175.175:80)
# null 100% |*******************************| 1024k 0:00:00 ETA
# real 0m 0.22s
# user 0m 0.00s
# sys 0m 0.08s
real=$(echo "$output" | grep ^real)
# We expect real="real 0m 0.22s", but double check
if [ "$real" ]; then
# Yup, we got what we expected.
set - $real
min=$2 # 0m
min=${min%m} # 0
sec=$3 # 0.22s
sec=${sec%s} # 0.22
else
# Oops. This must be one of those machines where `time` returns
# 0.00user 0.00system 0:00.22elapsed 1%CPU (0avgtext+0avgdata 1284maxresident)k
real=$(echo "$output" | grep elapsed)
if [ -z "$real" ]; then
echo "Error: Unknown format from the 'time' program:" >&2
echo "$output" >&2
echo 0
return
fi
# ...tem 0:00.22elapsed 1%cpu...
real=${real%%elapsed*} # ...tem 0:00.22
real=${real##* } # 0:00.22
min=${real%%:*} # 0
sec=${real##*:} # 00.22
fi
# Now we've got min=0 and sec=0.22, get rid of the decimal point
ms=${sec#*.} # 22
while [ ${#ms} -lt 3 ]; do # 220
ms=${ms}0
done
sec=${sec%.*}
# Bourne arithmetic in $(...) treats leading 0 as octal!
min=$(nooctal $min)
sec=$(nooctal $sec)
ms=$(nooctal $ms)
echo "$min minutes, $sec seconds, $ms milliseconds" >&2
# Now return the result as total number of milliseconds
echo $((min*60*1000 + sec*1000 + ms))
}
nooctal() {
# Given a string in $1, print without leading zeros.
# "008" --> "8"
x=$1
y=${x#0}
while [ "$x" != "$y" ]; do
x=$y
y=${x#0}
done
if [ "$x" ]; then
echo $x
else
echo 0
fi
}
whichwget() {
# On fancy machines, wget detects it is not on a tty and is too verbose.
# On routers, wget doesn't understand the --progress flag.
# Let's make everybody happy! :-)
# Run a test and see how it dies. (255.255.255.255 always fails).
wget --progress=bar:force -t 1 -T 0.1 255.255.255.255 >/dev/null 2>&1
case $? in
127) echo "Sorry this test requires wget (busybox or regular)." >&2
;;
4) # Yay! Fancy wget.
options="--quiet --show-progress --progress=bar:force --report-speed=bits"
;;
1) # Still Yay! Busybox wget or a veritable simulacrum.
;;
*) # Huh... um... yay?
echo Error: The shell or wget gave a mysterious error code. >&2
echo Error: This ought never happen. >&2
;;
esac
echo wget $options
}
echo "======================================================================"
echo "ROUGH APPROXIMATION"
dotest 1
echo "======================================================================"
echo "DOING QUICK TEST"
dotest 10
echo "======================================================================"
echo "DOING NORMAL TEST"
#dotest 100 # cachefly's "100" file is empty as of Feb 2023
dotest 50 100 # cachefly's "50" file is 100MB as of June 2023
#echo "======================================================================"
#echo "EXHAUSTIVE TEST"
#dotest 200
@painfull30
Copy link

Here is sample which not using "time" - more universal

@josegonzalez
Copy link

@hackerb9 is there a license for this file?

@hackerb9
Copy link
Author

hackerb9 commented Jun 11, 2023

@josegonzalez Thank you for asking. You can use it under CC0, but I wouldn't recommend distributing it widely as who knows how long cachefly.net will be around.

By the way, I updated the script to handle the peculiarity in how cachefly is now naming their files.

  • "50mb.test" holds 100MB of data
  • "100mb.test" holds the string "100mb"
  • "400mb.test" holds the string "pretend I just served you 400MB."

@josegonzalez
Copy link

Great! I'm using it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment