Skip to content

Instantly share code, notes, and snippets.

@silv3rr
Last active July 1, 2024 20:36
Show Gist options
  • Save silv3rr/572964d668bfe20ba4c5e9e304a63e8a to your computer and use it in GitHub Desktop.
Save silv3rr/572964d668bfe20ba4c5e9e304a63e8a to your computer and use it in GitHub Desktop.
Wrapper around speedtest-cli (uses speedtest.net)
#!/bin/bash
# Wrapper around speedtest cli (speedtest.net)
####################################################
# - Required: https://www.speedtest.net/apps/cli or https://github.com/sivel/speedtest-cli
# - Put this script in same dir as speedtest-cli or in parent dir
# - Uncomment line below to add an extra exclude besides "-x" ('grep -v server/country')
#exclude="\(Vodafone\|Brazil\|Comcast\|Hawaii\)"
speedtest_bin="/usr/bin/speedtest"
#speedtest_bin="./test.sh"
func_exit () {
if [ -n "$speedtest_ip4" ] && [ -f "$speedtest_ip4" ]; then
rm -f "$speedtest_ip4" >/dev/null 2>&1
fi
exit 0
}
cli=0
if echo "$speedtest_bin"|grep -Eq 'speedtest$'; then
cli=1
elif echo "$speedtest_bin"|grep -Eq 'speedtest.py$'; then
cli=2
# Try to locate required bin or .py script
else
if [ -z "$speedtest_bin" ]; then
scmd="$(command -v speedtest 2>&1)"
if [ -n "$scmd" ]; then
speedtest_bin="$scmd"
cli=1
else
for i in . .. ../../src/speedtest-cli ../speedtest-cli speedtest-cli; do
if [ -x "$i/speedtest.py" ]; then
speedtest_bin="$i/speedtest.py"
cli=2
break
fi
done
fi
fi
fi
if [ -z "$speedtest_bin" ]; then
printf "You need 'speedtest' or 'speedtest-cli':\n"
printf " - official cli: https://www.speedtest.net/apps/cli\n"
printf " - 3rd party: https://github.com/sivel/speedtest-cli\n"
printf " (git clone & chmod +x speedtest-cli/speedtest.py\n"
exit 1
fi
if echo "$@" | grep -q '\-h'; then
printf "\nspeedtest cli wrapper (speedtest.net)\n"
printf "\nUsage : %s -[l|x] <Country|Server>\n" "$( basename "$0")"
printf "Options : [-l] to List servers\n"
printf " [-x] <pattern> to eXclude country/server\n"
printf " [-4] force ipv4 (speedtest-cli.py)\n"
printf " [-s] bind source <ip> (to speedtest)\n\n"
printf "Example : ./%s Romania\n\n" "$( basename "$0")"
printf "Press CTRL-C during speedtesting to abort\n\n"
exit 0
fi
# Passtrough --ip and --source option
if echo "$@" | grep -q '\-s'; then
if [ "${cli:-0}" -eq 1 ]; then
source="--ip="
elif [ "${cli:-0}" -eq 2 ]; then
source="--source "
fi
source+="$( echo "$@" | sed -E 's/.*(-s|--source) ?([0-9a-fA-F\.:]{4,}) ?.*/\2/' )"
fi
if echo "$@" | grep -q '\-x'; then
excl_argx="$( echo "$@" | sed -E 's/.*-x ?([^ ]+) ?.*/\1/' )"
grep_excl_argx="grep -Ev $excl_argx"
fi
if [ -n "$exclude" ]; then
grep_excl_var="grep -Ev $exclude"
fi
# Remove args except for Country
params="$(
echo "$@" | sed -E \
-e 's/ ?(-l|--list|--servers|-4) ?//g' \
-e 's/( ?-x ?[^ ]+ ?)(.*|$)/\2/' \
-e 's/( ?(-s|--source) ?[0-9a-fA-F\.:]{4,} ?)(.*|$)/\3/' \
)"
# Country specific excludes
case $params in
*AW*|*Aruba*) country_regex="(Aruba.*Italy)"; ;;
*ES*|*Spain*) country_regex="(Canarias|Lanzarote|Las Palmas|Mogan|Santa Cruz|Trinidad)"; ;;
*JE*|*Jersey*) country_regex="(Jersey.*United States)"; ;;
*GE*|*Georgia*) country_regex="(Georgia.*United States)"; ;;
*IN*|*India*) country_regex="(Indiara.*Brazil|Indianapolis.*United States)"; ;;
*ML*|*Mali*) country_regex="(Malik Cable.*New Delhi)"; ;;
*ME*|*Montenegro*) country_regex="(Montenegro.*Brazil)"; ;;
*MU*|*Mauritius*) country_regex="(Mauritius Telecom.*London)"; ;;
*NL*|*Netherlands*) country_regex="(Antilles|Curacao|St. Maarten|Saint Martin)"; ;;
*PE*|*Peru*) country_regex="(Telecom Italia.*Italy)"; ;;
*TR*|*Turkey*) country_regex="(Turkeynet.*Brazil)"; ;;
*UG*|*Uganda*) country_regex="(Uganda Hosting.*Germany|Uganda Hosting.*Finland)"; ;;
esac
if [ -n "$country_regex" ]; then
grep_excl_country="grep -Ev '$country_regex'"
fi
# Country code
if echo "$params" | grep -Eq "[A-Z]{2}"; then
ccode="$( echo "$params" | sed -E 's/.*([A-Z]{2}).*/\1/' )"
if command -v isoquery >/dev/null 2>&1; then
params="$(isoquery "$ccode" | awk -F'\t' '{ print $NF }')"
else
echo "To use ISO Country Codes install \"isoquery\", or use full Country Name instead"
exit 1
fi
fi
if [ -z "$params" ]; then
printf "Specify country/server to result or speedtest, or try \"%s -h\"\n" "$(basename "$0")"
exit 1
fi
if echo "$params" | grep -q "^-"; then
echo "Wrong argument(s)"; exit 1
fi
# Modify Python code on the fly to force IPv4 (from: https://stackoverflow.com/a/50044152)
if echo "$@" | grep -q '\-4' && [ "${cli:-0}" -eq 2 ]; then
speedtest_ip4="/tmp/speedtest4.$$.py"
sed '/import socket/a\
old_getaddrinfo = socket.getaddrinfo\
def new_getaddrinfo(*args, **kwargs):\
responses = old_getaddrinfo(*args, **kwargs)\
return [response\
for response in responses\
if response[0] == socket.AF_INET]\
socket.getaddrinfo = new_getaddrinfo'\
"$speedtest_bin" >"$speedtest_ip4" && chmod +x "$speedtest_ip4"
speedtest_bin="$speedtest_ip4"
if [ -z "$speedtest_ip4" ] || [ ! -x "$speedtest_ip4" ]; then
printf "ERROR: could not force IPv4"
fi
fi
trap 'func_exit' HUP INT QUIT TERM
# Filter servers
for i in "grep \"$params\"" "$grep_excl_var" "$grep_excl_argx" "$grep_excl_country"; do
if [ -n "$i" ]; then
filter="$filter | $i"
fi
done && \
filter="$( echo "$filter" | sed -E 's/^ ?\| //' )"
IFS="$IFS_SAVE"
IFS=$'\n'
snum=0
if [ "${cli:-0}" -eq 1 ]; then
arg_list="--servers"
else
arg_list="--list"
fi
for i in $(eval "$speedtest_bin $arg_list | $filter"); do
result="$result $i _EOL_"
snum=$((snum+1))
done
# List servers or run speedtest
printf "\nCountry/Server: %s\n" "$params"
printf "Excluding: %s %s %s\n\n" "$country_regex" "$excl_argx" "$exclude"
if { echo "$@" | grep -qi '\-l'; } then
for i in $( echo $result | sed 's/_EOL_/\n/g' ); do
echo "$i"
done
printf "\nTotal: %s servers\n\n" "$snum"
else
j=1
if [ "${cli:-0}" -eq 1 ]; then
args="server-id="
elif [ "${cli:-0}" -eq 2 ]; then
args="--secure --server "
awk_args=""
fi
for i in $( echo $result | sed 's/_EOL_/\n/g' | awk $awk_args '{ print $1 }' ); do
echo -n "Server ${j} of ${snum} -- "
$speedtest_bin $source ${args}${i}
echo
j=$((j+1));
done
fi
IFS="$IFS_SAVE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment