feat: add REQUIRED_COMMANDS, check for them and fix various warnings

This commit is contained in:
hugmouse 2024-06-19 17:53:39 +02:00
commit 568bf9d058
No known key found for this signature in database
GPG key ID: 45FDB5FAB7ECB522

555
yabs.sh
View file

@ -20,42 +20,72 @@ echo -e '# '$YABS_VERSION' #'
echo -e '# https://github.com/masonr/yet-another-bench-script #'
echo -e '# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #'
echo -e
date
TIME_START=$(date '+%Y%m%d-%H%M%S')
YABS_START_TIME=$(date +%s)
# Check for required commands and add warnings if not available
REQUIRED_COMMANDS=("locale" "uname" "getconf" "awk" "sed" "grep" "cut" "shuf" "timeout" "date" "trap" "df" "free" "systemd-detect-virt")
# override locale to eliminate parsing errors (i.e. using commas as delimiters rather than periods)
if locale -a 2>/dev/null | grep ^C$ > /dev/null; then
# locale "C" installed
export LC_ALL=C
echo -e "\nChecking available commands"
echo -e "---------------------------------"
for cmd in "${REQUIRED_COMMANDS[@]}"; do
if command -v "$cmd" &>/dev/null; then
printf "%-20s : \xE2\x9C\x94 installed\n" "$cmd"
else
printf "%-20s : \xE2\x9D\x8C not installed\n" "$cmd"
MISSING_CMDS+=("$cmd")
fi
done
# Define a function to check command availability before using it
function check_command() {
command -v "$1" &>/dev/null
}
echo -e
if check_command "date"; then
date
TIME_START=$(date '+%Y%m%d-%H%M%S')
YABS_START_TIME=$(date +%s)
else
# locale "C" not installed, display warning
echo -e "\nWarning: locale 'C' not detected. Test outputs may not be parsed correctly."
echo -e "\nWarning: 'date' command not found. Can't print time and track it!"
fi
# determine architecture of host
ARCH=$(uname -m)
if [[ $ARCH = *x86_64* ]]; then
# host is running a 64-bit kernel
ARCH="x64"
elif [[ $ARCH = *i?86* ]]; then
# host is running a 32-bit kernel
ARCH="x86"
elif [[ $ARCH = *aarch* || $ARCH = *arm* ]]; then
KERNEL_BIT=$(getconf LONG_BIT)
if [[ $KERNEL_BIT = *64* ]]; then
# host is running an ARM 64-bit kernel
ARCH="aarch64"
else
# host is running an ARM 32-bit kernel
ARCH="arm"
fi
echo -e "\nARM compatibility is considered *experimental*"
# override locale to eliminate parsing errors (i.e. using commas as delimiters rather than periods)
if check_command "locale"; then
if locale -a 2>/dev/null | grep ^C$ > /dev/null; then
export LC_ALL=C
else
echo -e "\nWarning: locale 'C' not detected. Test outputs may not be parsed correctly."
fi
else
# host is running a non-supported kernel
echo -e "Architecture not supported by YABS."
exit 1
echo -e "\nWarning: 'locale' command not found. Skipping locale configuration."
fi
# Determine architecture of host
if check_command "uname"; then
ARCH=$(uname -m)
if [[ $ARCH = *x86_64* ]]; then
ARCH="x64"
elif [[ $ARCH = *i?86* ]]; then
ARCH="x86"
elif [[ $ARCH = *aarch* || $ARCH = *arm* ]]; then
if check_command "getconf"; then
KERNEL_BIT=$(getconf LONG_BIT)
if [[ $KERNEL_BIT = *64* ]]; then
ARCH="aarch64"
else
ARCH="arm"
fi
else
echo -e "getconf command not found. Unable to determine ARM kernel bitness."
exit 1
fi
echo -e "\nARM compatibility is considered *experimental*"
else
echo -e "Architecture not supported by YABS."
exit 1
fi
else
echo -e "'uname' command not found. Unable to determine architecture."
exit 1
fi
# flags to skip certain performance tests
@ -77,25 +107,41 @@ while getopts 'bfdignhr4596jw:s:' flag; do
5) GEEKBENCH_5="True" && unset GEEKBENCH_6 ;;
9) GEEKBENCH_4="True" && GEEKBENCH_5="True" && unset GEEKBENCH_6 ;;
6) GEEKBENCH_6="True" ;;
j) JSON+="j" ;;
j) JSON+="j" ;;
w) JSON+="w" && JSON_FILE=${OPTARG} ;;
s) JSON+="s" && JSON_SEND=${OPTARG} ;;
s) JSON+="s" && JSON_SEND=${OPTARG} ;;
*) exit 1 ;;
esac
done
# check for local fio/iperf installs
command -v fio >/dev/null 2>&1 && LOCAL_FIO=true || unset LOCAL_FIO
command -v iperf3 >/dev/null 2>&1 && LOCAL_IPERF=true || unset LOCAL_IPERF
if command -v fio >/dev/null 2>&1; then
LOCAL_FIO=true
else
unset LOCAL_FIO
fi
if command -v iperf3 >/dev/null 2>&1; then
LOCAL_IPERF=true
else
unset LOCAL_IPERF
fi
# check for ping
command -v ping >/dev/null 2>&1 && LOCAL_PING=true || unset LOCAL_PING
if command -v ping >/dev/null 2>&1; then
LOCAL_PING=true
else
unset LOCAL_PING
fi
# check for curl/wget
command -v curl >/dev/null 2>&1 && LOCAL_CURL=true || unset LOCAL_CURL
if command -v curl >/dev/null 2>&1; then
LOCAL_CURL=true
else
unset LOCAL_CURL
fi
# test if the host has IPv4/IPv6 connectivity
[[ ! -z $LOCAL_CURL ]] && IP_CHECK_CMD="curl -s -m 4" || IP_CHECK_CMD="wget -qO- -T 4"
[[ -n $LOCAL_CURL ]] && IP_CHECK_CMD="curl -s -m 4" || IP_CHECK_CMD="wget -qO- -T 4"
IPV4_CHECK=$( (ping -4 -c 1 -W 4 ipv4.google.com >/dev/null 2>&1 && echo true) || $IP_CHECK_CMD -4 icanhazip.com 2> /dev/null)
IPV6_CHECK=$( (ping -6 -c 1 -W 4 ipv6.google.com >/dev/null 2>&1 && echo true) || $IP_CHECK_CMD -6 icanhazip.com 2> /dev/null)
if [[ -z "$IPV4_CHECK" && -z "$IPV6_CHECK" ]]; then
@ -104,7 +150,7 @@ if [[ -z "$IPV4_CHECK" && -z "$IPV6_CHECK" ]]; then
fi
# print help and exit script, if help flag was passed
if [ ! -z "$PRINT_HELP" ]; then
if [[ -n "$PRINT_HELP" ]]; then
echo -e
echo -e "Usage: ./yabs.sh [-flags]"
echo -e " curl -sL yabs.sh | bash"
@ -134,15 +180,15 @@ if [ ! -z "$PRINT_HELP" ]; then
echo -e "Detected Arch: $ARCH"
echo -e
echo -e "Detected Flags:"
[[ ! -z $PREFER_BIN ]] && echo -e " -b, force using precompiled binaries from repo"
[[ ! -z $SKIP_FIO ]] && echo -e " -f/d, skipping fio disk benchmark test"
[[ ! -z $SKIP_IPERF ]] && echo -e " -i, skipping iperf network test"
[[ ! -z $SKIP_GEEKBENCH ]] && echo -e " -g, skipping geekbench test"
[[ ! -z $SKIP_NET ]] && echo -e " -n, skipping network info lookup and print out"
[[ ! -z $REDUCE_NET ]] && echo -e " -r, using reduced (3) iperf3 locations"
[[ ! -z $GEEKBENCH_4 ]] && echo -e " running geekbench 4"
[[ ! -z $GEEKBENCH_5 ]] && echo -e " running geekbench 5"
[[ ! -z $GEEKBENCH_6 ]] && echo -e " running geekbench 6"
[[ -n $PREFER_BIN ]] && echo -e " -b, force using precompiled binaries from repo"
[[ -n $SKIP_FIO ]] && echo -e " -f/d, skipping fio disk benchmark test"
[[ -n $SKIP_IPERF ]] && echo -e " -i, skipping iperf network test"
[[ -n $SKIP_GEEKBENCH ]] && echo -e " -g, skipping geekbench test"
[[ -n $SKIP_NET ]] && echo -e " -n, skipping network info lookup and print out"
[[ -n $REDUCE_NET ]] && echo -e " -r, using reduced (3) iperf3 locations"
[[ -n $GEEKBENCH_4 ]] && echo -e " running geekbench 4"
[[ -n $GEEKBENCH_5 ]] && echo -e " running geekbench 5"
[[ -n $GEEKBENCH_6 ]] && echo -e " running geekbench 6"
echo -e
echo -e "Local Binary Check:"
[[ -z $LOCAL_FIO ]] && echo -e " fio not detected, will download precompiled binary" ||
@ -153,16 +199,16 @@ if [ ! -z "$PRINT_HELP" ]; then
echo -e " iperf3 detected, but using precompiled binary instead"
echo -e
echo -e "Detected Connectivity:"
[[ ! -z $IPV4_CHECK ]] && echo -e " IPv4 connected" ||
[[ -n $IPV4_CHECK ]] && echo -e " IPv4 connected" ||
echo -e " IPv4 not connected"
[[ ! -z $IPV6_CHECK ]] && echo -e " IPv6 connected" ||
[[ -n $IPV6_CHECK ]] && echo -e " IPv6 connected" ||
echo -e " IPv6 not connected"
echo -e
echo -e "JSON Options:"
[[ -z $JSON ]] && echo -e " none"
[[ $JSON = *j* ]] && echo -e " printing json to screen after test"
[[ $JSON = *w* ]] && echo -e " writing json to file ($JSON_FILE) after test"
[[ $JSON = *s* ]] && echo -e " sharing json YABS results to $JSON_SEND"
[[ $JSON = *s* ]] && echo -e " sharing json YABS results to $JSON_SEND"
echo -e
echo -e "Exiting..."
@ -184,7 +230,7 @@ function format_size {
# ensure the raw value is a number, otherwise return blank
re='^[0-9]+$'
if ! [[ $RAW =~ $re ]] ; then
echo ""
echo ""
return 0
fi
@ -202,27 +248,36 @@ function format_size {
# divide the raw result to get the corresponding formatted result (based on determined unit)
RESULT=$(awk -v a="$RESULT" -v b="$DENOM" 'BEGIN { print a / b }')
# shorten the formatted result to two decimal places (i.e. x.x)
RESULT=$(echo $RESULT | awk -F. '{ printf "%0.1f",$1"."substr($2,1,2) }')
RESULT=$(echo "$RESULT" | awk -F. '{ printf "%0.1f",$1"."substr($2,1,2) }')
# concat formatted result value with units and return result
RESULT="$RESULT $UNIT"
echo $RESULT
echo "$RESULT"
}
# gather basic system information (inc. CPU, AES-NI/virt status, RAM + swap + disk size)
echo -e
echo -e
echo -e "Basic System Information:"
echo -e "---------------------------------"
UPTIME=$(uptime | awk -F'( |,|:)+' '{d=h=m=0; if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes"}')
echo -e "Uptime : $UPTIME"
if check_command "uptime"; then
UPTIME=$(uptime | awk -F'( |,|:)+' '{d=h=m=0; if ($7=="min") m=$6; else {if ($7~/^day/) {d=$6;h=$8;m=$9} else {h=$6;m=$7}}} {print d+0,"days,",h+0,"hours,",m+0,"minutes"}')
echo -e "Uptime : $UPTIME"
else
echo -e "Uptime : 'uptime' command not found."
fi
# check for local lscpu installs
command -v lscpu >/dev/null 2>&1 && LOCAL_LSCPU=true || unset LOCAL_LSCPU
if [[ $ARCH = *aarch64* || $ARCH = *arm* ]] && [[ ! -z $LOCAL_LSCPU ]]; then
if command -v lscpu >/dev/null 2>&1; then
LOCAL_LSCPU=true
else
unset LOCAL_LSCPU
fi
if [[ $ARCH = *aarch64* || $ARCH = *arm* ]] && [[ -n $LOCAL_LSCPU ]]; then
CPU_PROC=$(lscpu | grep "Model name" | sed 's/Model name: *//g')
else
CPU_PROC=$(awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//')
fi
echo -e "Processor : $CPU_PROC"
if [[ $ARCH = *aarch64* || $ARCH = *arm* ]] && [[ ! -z $LOCAL_LSCPU ]]; then
if [[ $ARCH = *aarch64* || $ARCH = *arm* ]] && [[ -n $LOCAL_LSCPU ]]; then
CPU_CORES=$(lscpu | grep "^[[:blank:]]*CPU(s):" | sed 's/CPU(s): *//g')
CPU_FREQ=$(lscpu | grep "CPU max MHz" | sed 's/CPU max MHz: *//g')
[[ -z "$CPU_FREQ" ]] && CPU_FREQ="???"
@ -232,29 +287,52 @@ else
CPU_FREQ=$(awk -F: ' /cpu MHz/ {freq=$2} END {print freq " MHz"}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//')
fi
echo -e "CPU cores : $CPU_CORES @ $CPU_FREQ"
CPU_AES=$(cat /proc/cpuinfo | grep aes)
[[ -z "$CPU_AES" ]] && CPU_AES="\xE2\x9D\x8C Disabled" || CPU_AES="\xE2\x9C\x94 Enabled"
CPU_AES=$(grep -q aes /proc/cpuinfo && printf "\xE2\x9C\x94 Enabled" || printf "\xE2\x9D\x8C Disabled")
echo -e "AES-NI : $CPU_AES"
CPU_VIRT=$(cat /proc/cpuinfo | grep 'vmx\|svm')
[[ -z "$CPU_VIRT" ]] && CPU_VIRT="\xE2\x9D\x8C Disabled" || CPU_VIRT="\xE2\x9C\x94 Enabled"
CPU_VIRT=$(grep -q 'vmx\|svm' /proc/cpuinfo && printf "\xE2\x9C\x94 Enabled" || printf "\xE2\x9D\x8C Disabled")
echo -e "VM-x/AMD-V : $CPU_VIRT"
TOTAL_RAM_RAW=$(free | awk 'NR==2 {print $2}')
TOTAL_RAM=$(format_size $TOTAL_RAM_RAW)
echo -e "RAM : $TOTAL_RAM"
TOTAL_SWAP_RAW=$(free | grep Swap | awk '{ print $2 }')
TOTAL_SWAP=$(format_size $TOTAL_SWAP_RAW)
echo -e "Swap : $TOTAL_SWAP"
if check_command "free"; then
TOTAL_RAM_RAW=$(free | awk 'NR==2 {print $2}')
TOTAL_RAM=$(format_size "$TOTAL_RAM_RAW")
echo -e "RAM : $TOTAL_RAM"
TOTAL_SWAP_RAW=$(free | grep Swap | awk '{ print $2 }')
TOTAL_SWAP=$(format_size "$TOTAL_SWAP_RAW")
echo -e "Swap : $TOTAL_SWAP"
else
echo -e "'free' command not found. Unable to retrieve RAM and Swap information."
fi
# total disk size is calculated by adding all partitions of the types listed below (after the -t flags)
TOTAL_DISK_RAW=$(df -t simfs -t ext2 -t ext3 -t ext4 -t btrfs -t xfs -t vfat -t ntfs -t swap --total 2>/dev/null | grep total | awk '{ print $2 }')
TOTAL_DISK=$(format_size $TOTAL_DISK_RAW)
echo -e "Disk : $TOTAL_DISK"
DISTRO=$(grep 'PRETTY_NAME' /etc/os-release | cut -d '"' -f 2 )
echo -e "Distro : $DISTRO"
KERNEL=$(uname -r)
echo -e "Kernel : $KERNEL"
VIRT=$(systemd-detect-virt 2>/dev/null)
VIRT=${VIRT^^} || VIRT="UNKNOWN"
echo -e "VM Type : $VIRT"
if check_command "df"; then
TOTAL_DISK_RAW=$(df -t simfs -t ext2 -t ext3 -t ext4 -t btrfs -t xfs -t vfat -t ntfs -t swap --total 2>/dev/null | grep total | awk '{ print $2 }')
TOTAL_DISK=$(format_size "$TOTAL_DISK_RAW")
echo -e "Disk : $TOTAL_DISK"
else
echo -e "'df' command not found. Unable to retrieve disk information."
fi
if check_command "grep"; then
if check_command "cut"; then
DISTRO=$(grep 'PRETTY_NAME' /etc/os-release | cut -d '"' -f 2 )
echo -e "Distro : $DISTRO"
else
echo -e "'cut' command not found. Unable to retrieve distribution information."
fi
else
echo -e "'grep' command not found. Unable to retrieve distribution information."
fi
if check_command "uname"; then
KERNEL=$(uname -r)
echo -e "Kernel : $KERNEL"
else
echo -e "'uname' command not found. Unable to retrieve kernel information."
fi
if check_command "systemd-detect-virt"; then
VIRT=$(systemd-detect-virt 2>/dev/null)
VIRT=${VIRT^^} || VIRT="UNKNOWN"
echo -e "VM Type : $VIRT"
else
echo -e "VM Type : 'systemd-detect-virt' command not found. Unable to retrieve virtualization type."
fi
[[ -z "$IPV4_CHECK" ]] && ONLINE="\xE2\x9D\x8C Offline / " || ONLINE="\xE2\x9C\x94 Online / "
[[ -z "$IPV6_CHECK" ]] && ONLINE+="\xE2\x9D\x8C Offline" || ONLINE+="\xE2\x9C\x94 Online"
echo -e "IPv4/IPv6 : $ONLINE"
@ -262,27 +340,38 @@ echo -e "IPv4/IPv6 : $ONLINE"
# Function to get information from IP Address using ip-api.com free API
function ip_info() {
# check for curl vs wget
[[ ! -z $LOCAL_CURL ]] && DL_CMD="curl -s" || DL_CMD="wget -qO-"
[[ -n $LOCAL_CURL ]] && DL_CMD="curl -s" || DL_CMD="wget -qO-"
local ip6me_resp="$($DL_CMD http://ip6.me/api/)"
local net_type="$(echo $ip6me_resp | cut -d, -f1)"
local net_ip="$(echo $ip6me_resp | cut -d, -f2)"
local ip6me_resp
ip6me_resp="$($DL_CMD http://ip6.me/api/)"
local net_type
net_type="$(echo "$ip6me_resp" | cut -d, -f1)"
local net_ip
net_ip="$(echo "$ip6me_resp" | cut -d, -f2)"
local response=$($DL_CMD http://ip-api.com/json/$net_ip)
local response
response=$($DL_CMD http://ip-api.com/json/"$net_ip")
# if no response, skip output
if [[ -z $response ]]; then
return
fi
local country=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^country/ {print $2}' | head -1 | sed 's/^"\(.*\)"$/\1/')
local region=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^regionName/ {print $2}' | sed 's/^"\(.*\)"$/\1/')
local region_code=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^region/ {print $2}' | head -1 | sed 's/^"\(.*\)"$/\1/')
local city=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^city/ {print $2}' | sed 's/^"\(.*\)"$/\1/')
local isp=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^isp/ {print $2}' | sed 's/^"\(.*\)"$/\1/')
local org=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^org/ {print $2}' | sed 's/^"\(.*\)"$/\1/')
local as=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^as/ {print $2}' | sed 's/^"\(.*\)"$/\1/')
local country
country=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^country/ {print $2}' | head -1 | sed 's/^"\(.*\)"$/\1/')
local region
region=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^regionName/ {print $2}' | sed 's/^"\(.*\)"$/\1/')
local region_code
region_code=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^region/ {print $2}' | head -1 | sed 's/^"\(.*\)"$/\1/')
local city
city=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^city/ {print $2}' | sed 's/^"\(.*\)"$/\1/')
local isp
isp=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^isp/ {print $2}' | sed 's/^"\(.*\)"$/\1/')
local org
org=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^org/ {print $2}' | sed 's/^"\(.*\)"$/\1/')
local as
as=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^as/ {print $2}' | sed 's/^"\(.*\)"$/\1/')
echo
echo "$net_type Network Information:"
echo "---------------------------------"
@ -305,15 +394,15 @@ function ip_info() {
fi
if [[ -n "$country" ]]; then
echo "Country : $country"
fi
fi
[[ ! -z $JSON ]] && JSON_RESULT+=',"ip_info":{"protocol":"'$net_type'","isp":"'$isp'","asn":"'$as'","org":"'$org'","city":"'$city'","region":"'$region'","region_code":"'$region_code'","country":"'$country'"}'
[[ -n $JSON ]] && JSON_RESULT+=',"ip_info":{"protocol":"'$net_type'","isp":"'$isp'","asn":"'$as'","org":"'$org'","city":"'$city'","region":"'$region'","region_code":"'$region_code'","country":"'$country'"}'
}
if [ ! -z $JSON ]; then
if [[ -n $JSON ]]; then
UPTIME_S=$(awk '{print $1}' /proc/uptime)
IPV4=$([ ! -z $IPV4_CHECK ] && echo "true" || echo "false")
IPV6=$([ ! -z $IPV6_CHECK ] && echo "true" || echo "false")
IPV4=$([ -n "$IPV4_CHECK" ] && echo "true" || echo "false")
IPV6=$([ -n "$IPV6_CHECK" ] && echo "true" || echo "false")
AES=$([[ "$CPU_AES" = *Enabled* ]] && echo "true" || echo "false")
CPU_VIRT_BOOL=$([[ "$CPU_VIRT" = *Enabled* ]] && echo "true" || echo "false")
JSON_RESULT='{"version":"'$YABS_VERSION'","time":"'$TIME_START'","os":{"arch":"'$ARCH'","distro":"'$DISTRO'","kernel":"'$KERNEL'",'
@ -321,7 +410,7 @@ if [ ! -z $JSON ]; then
JSON_RESULT+='"freq":"'$CPU_FREQ'","aes":'$AES',"virt":'$CPU_VIRT_BOOL'},"mem":{"ram":'$TOTAL_RAM_RAW',"ram_units":"KiB","swap":'$TOTAL_SWAP_RAW',"swap_units":"KiB","disk":'$TOTAL_DISK_RAW',"disk_units":"KB"}'
fi
if [ -z $SKIP_NET ]; then
if [[ -z $SKIP_NET ]]; then
ip_info
fi
@ -345,10 +434,10 @@ trap catch_abort INT
# Purpose: This method will catch CTRL+C signals in order to exit the script cleanly and remove
# yabs-related files.
function catch_abort() {
echo -e "\n** Aborting YABS. Cleaning up files...\n"
rm -rf "$YABS_PATH"
unset LC_ALL
exit 0
echo -e "\n** Aborting YABS. Cleaning up files...\n"
rm -rf "$YABS_PATH"
unset LC_ALL
exit 0
}
# format_speed
@ -384,10 +473,10 @@ function format_speed {
# divide the raw result to get the corresponding formatted result (based on determined unit)
RESULT=$(awk -v a="$RESULT" -v b="$DENOM" 'BEGIN { print a / b }')
# shorten the formatted result to two decimal places (i.e. x.xx)
RESULT=$(echo $RESULT | awk -F. '{ printf "%0.2f",$1"."substr($2,1,2) }')
RESULT=$(echo "$RESULT" | awk -F. '{ printf "%0.2f",$1"."substr($2,1,2) }')
# concat formatted result value with units and return result
RESULT="$RESULT $UNIT"
echo $RESULT
echo "$RESULT"
}
# format_iops
@ -411,11 +500,11 @@ function format_iops {
# divide the raw result by 1k
RESULT=$(awk -v a="$RESULT" 'BEGIN { print a / 1000 }')
# shorten the formatted result to one decimal place (i.e. x.x)
RESULT=$(echo $RESULT | awk -F. '{ printf "%0.1f",$1"."substr($2,1,1) }')
RESULT=$(echo "$RESULT" | awk -F. '{ printf "%0.1f",$1"."substr($2,1,1) }')
RESULT="$RESULT"k
fi
echo $RESULT
echo "$RESULT"
}
# disk_test
@ -441,21 +530,21 @@ function disk_test {
for BS in "${BLOCK_SIZES[@]}"; do
# run rand read/write mixed fio test with block size = $BS
echo -en "Running fio random mixed R+W disk test with $BS block size..."
DISK_TEST=$(timeout 35 $FIO_CMD --name=rand_rw_$BS --ioengine=libaio --rw=randrw --rwmixread=50 --bs=$BS --iodepth=64 --numjobs=2 --size=$FIO_SIZE --runtime=30 --gtod_reduce=1 --direct=1 --filename="$DISK_PATH/test.fio" --group_reporting --minimal 2> /dev/null | grep rand_rw_$BS)
DISK_IOPS_R=$(echo $DISK_TEST | awk -F';' '{print $8}')
DISK_IOPS_W=$(echo $DISK_TEST | awk -F';' '{print $49}')
DISK_TEST=$(timeout 35 "$FIO_CMD" --name=rand_rw_"$BS" --ioengine=libaio --rw=randrw --rwmixread=50 --bs="$BS" --iodepth=64 --numjobs=2 --size=$FIO_SIZE --runtime=30 --gtod_reduce=1 --direct=1 --filename="$DISK_PATH/test.fio" --group_reporting --minimal 2> /dev/null | grep rand_rw_"$BS")
DISK_IOPS_R=$(echo "$DISK_TEST" | awk -F';' '{print $8}')
DISK_IOPS_W=$(echo "$DISK_TEST" | awk -F';' '{print $49}')
DISK_IOPS=$(awk -v a="$DISK_IOPS_R" -v b="$DISK_IOPS_W" 'BEGIN { print a + b }')
DISK_TEST_R=$(echo $DISK_TEST | awk -F';' '{print $7}')
DISK_TEST_W=$(echo $DISK_TEST | awk -F';' '{print $48}')
DISK_TEST_R=$(echo "$DISK_TEST" | awk -F';' '{print $7}')
DISK_TEST_W=$(echo "$DISK_TEST" | awk -F';' '{print $48}')
DISK_TEST=$(awk -v a="$DISK_TEST_R" -v b="$DISK_TEST_W" 'BEGIN { print a + b }')
DISK_RESULTS_RAW+=( "$DISK_TEST" "$DISK_TEST_R" "$DISK_TEST_W" "$DISK_IOPS" "$DISK_IOPS_R" "$DISK_IOPS_W" )
DISK_IOPS=$(format_iops $DISK_IOPS)
DISK_IOPS_R=$(format_iops $DISK_IOPS_R)
DISK_IOPS_W=$(format_iops $DISK_IOPS_W)
DISK_TEST=$(format_speed $DISK_TEST)
DISK_TEST_R=$(format_speed $DISK_TEST_R)
DISK_TEST_W=$(format_speed $DISK_TEST_W)
DISK_IOPS=$(format_iops "$DISK_IOPS")
DISK_IOPS_R=$(format_iops "$DISK_IOPS_R")
DISK_IOPS_W=$(format_iops "$DISK_IOPS_W")
DISK_TEST=$(format_speed "$DISK_TEST")
DISK_TEST_R=$(format_speed "$DISK_TEST_R")
DISK_TEST_W=$(format_speed "$DISK_TEST_W")
DISK_RESULTS+=( "$DISK_TEST" "$DISK_TEST_R" "$DISK_TEST_W" "$DISK_IOPS" "$DISK_IOPS_R" "$DISK_IOPS_W" )
echo -en "\r\033[0K"
@ -464,12 +553,12 @@ function disk_test {
# dd_test
# Purpose: This method is invoked if the fio disk test failed. dd sequential speed tests are
# not indiciative or real-world results, however, some form of disk speed measure
# not indicative or real-world results, however, some form of disk speed measure
# is better than nothing.
# Parameters:
# - (none)
function dd_test {
I=0
local I=0
DISK_WRITE_TEST_RES=()
DISK_READ_TEST_RES=()
DISK_WRITE_TEST_AVG=0
@ -480,19 +569,19 @@ function dd_test {
do
# write test using dd, "direct" flag is used to test direct I/O for data being stored to disk
DISK_WRITE_TEST=$(dd if=/dev/zero of="$DISK_PATH/$DATE.test" bs=64k count=16k oflag=direct |& grep copied | awk '{ print $(NF-1) " " $(NF)}')
VAL=$(echo $DISK_WRITE_TEST | cut -d " " -f 1)
VAL=$(echo "$DISK_WRITE_TEST" | cut -d " " -f 1)
[[ "$DISK_WRITE_TEST" == *"GB"* ]] && VAL=$(awk -v a="$VAL" 'BEGIN { print a * 1000 }')
DISK_WRITE_TEST_RES+=( "$DISK_WRITE_TEST" )
DISK_WRITE_TEST_AVG=$(awk -v a="$DISK_WRITE_TEST_AVG" -v b="$VAL" 'BEGIN { print a + b }')
# read test using dd using the 1G file written during the write test
DISK_READ_TEST=$(dd if="$DISK_PATH/$DATE.test" of=/dev/null bs=8k |& grep copied | awk '{ print $(NF-1) " " $(NF)}')
VAL=$(echo $DISK_READ_TEST | cut -d " " -f 1)
VAL=$(echo "$DISK_READ_TEST" | cut -d " " -f 1)
[[ "$DISK_READ_TEST" == *"GB"* ]] && VAL=$(awk -v a="$VAL" 'BEGIN { print a * 1000 }')
DISK_READ_TEST_RES+=( "$DISK_READ_TEST" )
DISK_READ_TEST_AVG=$(awk -v a="$DISK_READ_TEST_AVG" -v b="$VAL" 'BEGIN { print a + b }')
I=$(( $I + 1 ))
I=$(( I + 1 ))
done
# calculate the write and read speed averages using the results from the three runs
DISK_WRITE_TEST_AVG=$(awk -v a="$DISK_WRITE_TEST_AVG" 'BEGIN { print a / 3 }')
@ -500,6 +589,7 @@ function dd_test {
}
# check if disk performance is being tested and the host has required space (2G)
if check_command "df"; then
AVAIL_SPACE=$(df -k . | awk 'NR==2{print $4}')
if [[ -z "$SKIP_FIO" && "$AVAIL_SPACE" -lt 2097152 && "$ARCH" != "aarch64" && "$ARCH" != "arm" ]]; then # 2GB = 2097152KB
echo -e "\nLess than 2GB of space available. Skipping disk test..."
@ -510,36 +600,36 @@ elif [ -z "$SKIP_FIO" ]; then
# Perform ZFS filesystem detection and determine if we have enough free space according to spa_asize_inflation
ZFSCHECK="/sys/module/zfs/parameters/spa_asize_inflation"
if [[ -f "$ZFSCHECK" ]];then
mul_spa=$((($(cat /sys/module/zfs/parameters/spa_asize_inflation)*2)))
mul_spa=$(($(cat /sys/module/zfs/parameters/spa_asize_inflation)*2))
warning=0
poss=()
for pathls in $(df -Th | awk '{print $7}' | tail -n +2)
do
if [[ "${PWD##$pathls}" != "${PWD}" ]]; then
if [[ "${PWD##"$pathls"}" != "${PWD}" ]]; then
poss+=("$pathls")
fi
done
long=""
m=-1
for x in ${poss[@]}
for x in "${poss[@]}"
do
if [ ${#x} -gt $m ];then
if [ ${#x} -gt "$m" ];then
m=${#x}
long=$x
fi
done
size_b=$(df -Th | grep -w $long | grep -i zfs | awk '{print $5}' | tail -c -2 | head -c 1)
free_space=$(df -Th | grep -w $long | grep -i zfs | awk '{print $5}' | head -c -2)
size_b=$(df -Th | grep -w "$long" | grep -i zfs | awk '{print $5}' | tail -c -2 | head -c 1)
free_space=$(df -Th | grep -w "$long" | grep -i zfs | awk '{print $5}' | head -c -2)
if [[ $size_b == 'T' ]]; then
free_space=$(awk "BEGIN {print int($free_space * 1024)}")
size_b='G'
fi
if [[ $(df -Th | grep -w $long) == *"zfs"* ]];then
if [[ $(df -Th | grep -w "$long") == *"zfs"* ]];then
if [[ $size_b == 'G' ]]; then
if ((free_space < mul_spa)); then
@ -555,18 +645,18 @@ elif [ -z "$SKIP_FIO" ]; then
echo -en "\nWarning! You are running YABS on a ZFS Filesystem and your disk space is too low for the fio test. Your test results will be inaccurate. You need at least $mul_spa GB free in order to complete this test accurately. For more information, please see https://github.com/masonr/yet-another-bench-script/issues/13\n"
fi
fi
echo -en "\nPreparing system for disk tests..."
# create temp directory to store disk write/read test files
DISK_PATH=$YABS_PATH/disk
mkdir -p "$DISK_PATH"
if [[ -z "$PREFER_BIN" && ! -z "$LOCAL_FIO" ]]; then # local fio has been detected, use instead of pre-compiled binary
if [[ -z "$PREFER_BIN" && -n "$LOCAL_FIO" ]]; then # local fio has been detected, use instead of pre-compiled binary
FIO_CMD=fio
else
# download fio binary
if [[ ! -z $LOCAL_CURL ]]; then
if [[ -n $LOCAL_CURL ]]; then
curl -s --connect-timeout 5 --retry 5 --retry-delay 0 https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/bin/fio/fio_$ARCH -o "$DISK_PATH/fio"
else
wget -q -T 5 -t 5 -w 0 https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/bin/fio/fio_$ARCH -O "$DISK_PATH/fio"
@ -594,7 +684,7 @@ elif [ -z "$SKIP_FIO" ]; then
disk_test "${BLOCK_SIZES[@]}"
fi
if [[ ! -z "$DD_FALLBACK" || ${#DISK_RESULTS[@]} -eq 0 ]]; then # fio download failed or test was killed or returned an error, run dd test instead
if [[ -n "$DD_FALLBACK" || ${#DISK_RESULTS[@]} -eq 0 ]]; then # fio download failed or test was killed or returned an error, run dd test instead
if [ -z "$DD_FALLBACK" ]; then # print error notice if ended up here due to fio error
echo -e "fio disk speed tests failed. Run manually to determine cause.\nRunning dd test as fallback..."
fi
@ -602,13 +692,13 @@ elif [ -z "$SKIP_FIO" ]; then
dd_test
# format the speed averages by converting to GB/s if > 1000 MB/s
if [ $(echo $DISK_WRITE_TEST_AVG | cut -d "." -f 1) -ge 1000 ]; then
if [ "$(echo "$DISK_WRITE_TEST_AVG" | cut -d "." -f 1)" -ge 1000 ]; then
DISK_WRITE_TEST_AVG=$(awk -v a="$DISK_WRITE_TEST_AVG" 'BEGIN { print a / 1000 }')
DISK_WRITE_TEST_UNIT="GB/s"
else
DISK_WRITE_TEST_UNIT="MB/s"
fi
if [ $(echo $DISK_READ_TEST_AVG | cut -d "." -f 1) -ge 1000 ]; then
if [ "$(echo "$DISK_READ_TEST_AVG" | cut -d "." -f 1)" -ge 1000 ]; then
DISK_READ_TEST_AVG=$(awk -v a="$DISK_READ_TEST_AVG" 'BEGIN { print a / 1000 }')
DISK_READ_TEST_UNIT="GB/s"
else
@ -620,27 +710,26 @@ elif [ -z "$SKIP_FIO" ]; then
echo -e "dd Sequential Disk Speed Tests:"
echo -e "---------------------------------"
printf "%-6s | %-6s %-4s | %-6s %-4s | %-6s %-4s | %-6s %-4s\n" "" "Test 1" "" "Test 2" "" "Test 3" "" "Avg" ""
printf "%-6s | %-6s %-4s | %-6s %-4s | %-6s %-4s | %-6s %-4s\n"
printf "%-6s | %-11s | %-11s | %-11s | %-6.2f %-4s\n" "Write" "${DISK_WRITE_TEST_RES[0]}" "${DISK_WRITE_TEST_RES[1]}" "${DISK_WRITE_TEST_RES[2]}" "${DISK_WRITE_TEST_AVG}" "${DISK_WRITE_TEST_UNIT}"
printf "%-6s | %-11s | %-11s | %-11s | %-6.2f %-4s\n" "Read" "${DISK_READ_TEST_RES[0]}" "${DISK_READ_TEST_RES[1]}" "${DISK_READ_TEST_RES[2]}" "${DISK_READ_TEST_AVG}" "${DISK_READ_TEST_UNIT}"
printf "%-6s | %-11s | %-11s | %-11s | %-6.2f %-4s\n" "Write" "${DISK_WRITE_TEST_RES[0]}" "${DISK_WRITE_TEST_RES[1]}" "${DISK_WRITE_TEST_RES[2]}" "${DISK_WRITE_TEST_AVG}" "${DISK_WRITE_TEST_UNIT}"
printf "%-6s | %-11s | %-11s | %-11s | %-6.2f %-4s\n" "Read" "${DISK_READ_TEST_RES[0]}" "${DISK_READ_TEST_RES[1]}" "${DISK_READ_TEST_RES[2]}" "${DISK_READ_TEST_AVG}" "${DISK_READ_TEST_UNIT}"
else # fio tests completed successfully, print results
CURRENT_PARTITION=$(df -P . 2>/dev/null | tail -1 | cut -d' ' -f 1)
[[ ! -z $JSON ]] && JSON_RESULT+=',"partition":"'$CURRENT_PARTITION'","fio":['
DISK_RESULTS_NUM=$(expr ${#DISK_RESULTS[@]} / 6)
[[ -n $JSON ]] && JSON_RESULT+=',"partition":"'$CURRENT_PARTITION'","fio":['
DISK_RESULTS_NUM=$(( ${#DISK_RESULTS[@]} / 6 ))
DISK_COUNT=0
# print disk speed test results
echo -e "fio Disk Speed Tests (Mixed R/W 50/50) (Partition $CURRENT_PARTITION):"
echo -e "---------------------------------"
while [ $DISK_COUNT -lt $DISK_RESULTS_NUM ] ; do
if [ $DISK_COUNT -gt 0 ]; then printf "%-10s | %-20s | %-20s\n"; fi
while [ "$DISK_COUNT" -lt "$DISK_RESULTS_NUM" ] ; do
if [ "$DISK_COUNT" -gt 0 ]; then printf "%-10s | %-20s | %-20s\n" "" "" ""; fi
printf "%-10s | %-11s %8s | %-11s %8s\n" "Block Size" "${BLOCK_SIZES[DISK_COUNT]}" "(IOPS)" "${BLOCK_SIZES[DISK_COUNT+1]}" "(IOPS)"
printf "%-10s | %-11s %8s | %-11s %8s\n" " ------" "---" "---- " "----" "---- "
printf "%-10s | %-11s %8s | %-11s %8s\n" "Read" "${DISK_RESULTS[DISK_COUNT*6+1]}" "(${DISK_RESULTS[DISK_COUNT*6+4]})" "${DISK_RESULTS[(DISK_COUNT+1)*6+1]}" "(${DISK_RESULTS[(DISK_COUNT+1)*6+4]})"
printf "%-10s | %-11s %8s | %-11s %8s\n" "Write" "${DISK_RESULTS[DISK_COUNT*6+2]}" "(${DISK_RESULTS[DISK_COUNT*6+5]})" "${DISK_RESULTS[(DISK_COUNT+1)*6+2]}" "(${DISK_RESULTS[(DISK_COUNT+1)*6+5]})"
printf "%-10s | %-11s %8s | %-11s %8s\n" "Total" "${DISK_RESULTS[DISK_COUNT*6]}" "(${DISK_RESULTS[DISK_COUNT*6+3]})" "${DISK_RESULTS[(DISK_COUNT+1)*6]}" "(${DISK_RESULTS[(DISK_COUNT+1)*6+3]})"
if [ ! -z $JSON ]; then
if [ -n "$JSON" ]; then
JSON_RESULT+='{"bs":"'${BLOCK_SIZES[DISK_COUNT]}'","speed_r":'${DISK_RESULTS_RAW[DISK_COUNT*6+1]}',"iops_r":'${DISK_RESULTS_RAW[DISK_COUNT*6+4]}
JSON_RESULT+=',"speed_w":'${DISK_RESULTS_RAW[DISK_COUNT*6+2]}',"iops_w":'${DISK_RESULTS_RAW[DISK_COUNT*6+5]}',"speed_rw":'${DISK_RESULTS_RAW[DISK_COUNT*6]}
JSON_RESULT+=',"iops_rw":'${DISK_RESULTS_RAW[DISK_COUNT*6+3]}',"speed_units":"KBps"},'
@ -648,15 +737,18 @@ elif [ -z "$SKIP_FIO" ]; then
JSON_RESULT+=',"speed_w":'${DISK_RESULTS_RAW[(DISK_COUNT+1)*6+2]}',"iops_w":'${DISK_RESULTS_RAW[(DISK_COUNT+1)*6+5]}',"speed_rw":'${DISK_RESULTS_RAW[(DISK_COUNT+1)*6]}
JSON_RESULT+=',"iops_rw":'${DISK_RESULTS_RAW[(DISK_COUNT+1)*6+3]}',"speed_units":"KBps"},'
fi
DISK_COUNT=$(expr $DISK_COUNT + 2)
DISK_COUNT=$((DISK_COUNT + 2))
done
[[ ! -z $JSON ]] && JSON_RESULT=${JSON_RESULT::${#JSON_RESULT}-1} && JSON_RESULT+=']'
[[ -n $JSON ]] && JSON_RESULT=${JSON_RESULT::${#JSON_RESULT}-1} && JSON_RESULT+=']'
fi
fi
else
echo -e "'df' command not found. Skipping disk space check."
fi
# iperf_test
# Purpose: This method is designed to test the network performance of the host by executing an
# iperf3 test to/from the public iperf server passed to the function. Both directions
# iperf3 test to/from the public iperf server passed to the function. Both directions
# (send and receive) are tested.
# Parameters:
# 1. URL - URL/domain name of the iperf server
@ -668,7 +760,7 @@ function iperf_test {
PORTS=$2
HOST=$3
FLAGS=$4
# attempt the iperf send test 3 times, allowing for a slot to become available on the
# server or to throw out any bad/error results
I=1
@ -676,20 +768,20 @@ function iperf_test {
do
echo -en "Performing $MODE iperf3 send test to $HOST (Attempt #$I of 3)..."
# select a random iperf port from the range provided
PORT=$(shuf -i $PORTS -n 1)
PORT=$(shuf -i "$PORTS" -n 1)
# run the iperf test sending data from the host to the iperf server; includes
# a timeout of 15s in case the iperf server is not responding; uses 8 parallel
# threads for the network test
IPERF_RUN_SEND="$(timeout 15 $IPERF_CMD $FLAGS -c "$URL" -p $PORT -P 8 2> /dev/null)"
IPERF_RUN_SEND="$(timeout 15 "$IPERF_CMD" "$FLAGS" -c "$URL" -p "$PORT" -P 8 2> /dev/null)"
# check if iperf exited cleanly and did not return an error
if [[ "$IPERF_RUN_SEND" == *"receiver"* && "$IPERF_RUN_SEND" != *"error"* ]]; then
# test did not result in an error, parse speed result
SPEED=$(echo "${IPERF_RUN_SEND}" | grep SUM | grep receiver | awk '{ print $6 }')
# if speed result is blank or bad (0.00), rerun, otherwise set counter to exit loop
[[ -z $SPEED || "$SPEED" == "0.00" ]] && I=$(( $I + 1 )) || I=11
[[ -z $SPEED || "$SPEED" == "0.00" ]] && I=$(( I + 1 )) || I=11
else
# if iperf server is not responding, set counter to exit, otherwise increment, sleep, and rerun
[[ "$IPERF_RUN_SEND" == *"unable to connect"* ]] && I=11 || I=$(( $I + 1 )) && sleep 2
[[ "$IPERF_RUN_SEND" == *"unable to connect"* ]] && I=11 || I=$(( I + 1 )) && sleep 2
fi
echo -en "\r\033[0K"
done
@ -704,32 +796,32 @@ function iperf_test {
do
echo -n "Performing $MODE iperf3 recv test from $HOST (Attempt #$J of 3)..."
# select a random iperf port from the range provided
PORT=$(shuf -i $PORTS -n 1)
PORT=$(shuf -i "$PORTS" -n 1)
# run the iperf test receiving data from the iperf server to the host; includes
# a timeout of 15s in case the iperf server is not responding; uses 8 parallel
# threads for the network test
IPERF_RUN_RECV="$(timeout 15 $IPERF_CMD $FLAGS -c "$URL" -p $PORT -P 8 -R 2> /dev/null)"
IPERF_RUN_RECV="$(timeout 15 "$IPERF_CMD" "$FLAGS" -c "$URL" -p "$PORT" -P 8 -R 2> /dev/null)"
# check if iperf exited cleanly and did not return an error
if [[ "$IPERF_RUN_RECV" == *"receiver"* && "$IPERF_RUN_RECV" != *"error"* ]]; then
# test did not result in an error, parse speed result
SPEED=$(echo "${IPERF_RUN_RECV}" | grep SUM | grep receiver | awk '{ print $6 }')
# if speed result is blank or bad (0.00), rerun, otherwise set counter to exit loop
[[ -z $SPEED || "$SPEED" == "0.00" ]] && J=$(( $J + 1 )) || J=11
[[ -z $SPEED || "$SPEED" == "0.00" ]] && J=$(( J + 1 )) || J=11
else
# if iperf server is not responding, set counter to exit, otherwise increment, sleep, and rerun
[[ "$IPERF_RUN_RECV" == *"unable to connect"* ]] && J=11 || J=$(( $J + 1 )) && sleep 2
[[ "$IPERF_RUN_RECV" == *"unable to connect"* ]] && J=11 || J=$(( J + 1 )) && sleep 2
fi
echo -en "\r\033[0K"
done
# Run a latency test via ping -c1 command -> will return "xx.x ms"
[[ ! -z $LOCAL_PING ]] && LATENCY_RUN="$(ping -c1 $URL 2>/dev/null | grep -o 'time=.*' | sed s/'time='//)"
[[ -n $LOCAL_PING ]] && LATENCY_RUN="$(ping -c1 "$URL" 2>/dev/null | grep -o 'time=.*' | sed s/'time='//)"
[[ -z $LATENCY_RUN ]] && LATENCY_RUN="--"
# parse the resulting send and receive speed results
IPERF_SENDRESULT="$(echo "${IPERF_RUN_SEND}" | grep SUM | grep receiver)"
IPERF_RECVRESULT="$(echo "${IPERF_RUN_RECV}" | grep SUM | grep receiver)"
LATENCY_RESULT="$(echo "${LATENCY_RUN}")"
LATENCY_RESULT="${LATENCY_RUN}"
}
# launch_iperf
@ -747,7 +839,7 @@ function launch_iperf {
echo -e "---------------------------------"
printf "%-15s | %-25s | %-15s | %-15s | %-15s\n" "Provider" "Location (Link)" "Send Speed" "Recv Speed" "Ping"
printf "%-15s | %-25s | %-15s | %-15s | %-15s\n" "-----" "-----" "----" "----" "----"
# loop through iperf locations array to run iperf test using each public iperf server
for (( i = 0; i < IPERF_LOCS_NUM; i++ )); do
# test if the current iperf location supports the network mode being tested (IPv4/IPv6)
@ -755,17 +847,17 @@ function launch_iperf {
# call the iperf_test function passing the required parameters
iperf_test "${IPERF_LOCS[i*5]}" "${IPERF_LOCS[i*5+1]}" "${IPERF_LOCS[i*5+2]}" "$IPERF_FLAGS"
# parse the send and receive speed results
IPERF_SENDRESULT_VAL=$(echo $IPERF_SENDRESULT | awk '{ print $6 }')
IPERF_SENDRESULT_UNIT=$(echo $IPERF_SENDRESULT | awk '{ print $7 }')
IPERF_RECVRESULT_VAL=$(echo $IPERF_RECVRESULT | awk '{ print $6 }')
IPERF_RECVRESULT_UNIT=$(echo $IPERF_RECVRESULT | awk '{ print $7 }')
LATENCY_VAL=$(echo $LATENCY_RESULT)
IPERF_SENDRESULT_VAL=$(echo "$IPERF_SENDRESULT" | awk '{ print $6 }')
IPERF_SENDRESULT_UNIT=$(echo "$IPERF_SENDRESULT" | awk '{ print $7 }')
IPERF_RECVRESULT_VAL=$(echo "$IPERF_RECVRESULT" | awk '{ print $6 }')
IPERF_RECVRESULT_UNIT=$(echo "$IPERF_RECVRESULT" | awk '{ print $7 }')
LATENCY_VAL="$LATENCY_RESULT"
# if the results are blank, then the server is "busy" and being overutilized
[[ -z $IPERF_SENDRESULT_VAL || "$IPERF_SENDRESULT_VAL" == *"0.00"* ]] && IPERF_SENDRESULT_VAL="busy" && IPERF_SENDRESULT_UNIT=""
[[ -z $IPERF_RECVRESULT_VAL || "$IPERF_RECVRESULT_VAL" == *"0.00"* ]] && IPERF_RECVRESULT_VAL="busy" && IPERF_RECVRESULT_UNIT=""
# print the speed results for the iperf location currently being evaluated
printf "%-15s | %-25s | %-15s | %-15s | %-15s\n" "${IPERF_LOCS[i*5+2]}" "${IPERF_LOCS[i*5+3]}" "$IPERF_SENDRESULT_VAL $IPERF_SENDRESULT_UNIT" "$IPERF_RECVRESULT_VAL $IPERF_RECVRESULT_UNIT" "$LATENCY_VAL"
if [ ! -z $JSON ]; then
if [ -n "$JSON" ]; then
JSON_RESULT+='{"mode":"'$MODE'","provider":"'${IPERF_LOCS[i*5+2]}'","loc":"'${IPERF_LOCS[i*5+3]}
JSON_RESULT+='","send":"'$IPERF_SENDRESULT_VAL' '$IPERF_SENDRESULT_UNIT'","recv":"'$IPERF_RECVRESULT_VAL' '$IPERF_RECVRESULT_UNIT'","latency":"'$LATENCY_VAL'"},'
fi
@ -776,7 +868,7 @@ function launch_iperf {
# if the skip iperf flag was set, skip the network performance test, otherwise test network performance
if [ -z "$SKIP_IPERF" ]; then
if [[ -z "$PREFER_BIN" && ! -z "$LOCAL_IPERF" ]]; then # local iperf has been detected, use instead of pre-compiled binary
if [[ -z "$PREFER_BIN" && -n "$LOCAL_IPERF" ]]; then # local iperf has been detected, use instead of pre-compiled binary
IPERF_CMD=iperf3
else
# create a temp directory to house the required iperf binary and library
@ -784,7 +876,7 @@ if [ -z "$SKIP_IPERF" ]; then
mkdir -p "$IPERF_PATH"
# download iperf3 binary
if [[ ! -z $LOCAL_CURL ]]; then
if [[ -n $LOCAL_CURL ]]; then
curl -s --connect-timeout 5 --retry 5 --retry-delay 0 https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/bin/iperf/iperf3_$ARCH -o "$IPERF_PATH/iperf3"
else
wget -q -T 5 -t 5 -w 0 https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/bin/iperf/iperf3_$ARCH -O "$IPERF_PATH/iperf3"
@ -797,7 +889,7 @@ if [ -z "$SKIP_IPERF" ]; then
IPERF_CMD=$IPERF_PATH/iperf3
fi
fi
# array containing all currently available iperf3 public servers to use for the network test
# format: "1" "2" "3" "4" "5" \
# 1. domain name of the iperf server
@ -819,25 +911,25 @@ if [ -z "$SKIP_IPERF" ]; then
# if the "REDUCE_NET" flag is activated, then do a shorter iperf test with only three locations
# (Clouvider London, Clouvider NYC, and Online.net France)
if [ ! -z "$REDUCE_NET" ]; then
if [ -n "$REDUCE_NET" ]; then
IPERF_LOCS=( \
"lon.speedtest.clouvider.net" "5200-5209" "Clouvider" "London, UK (10G)" "IPv4|IPv6" \
"speedtest.sin1.sg.leaseweb.net" "5201-5210" "Leaseweb" "Singapore, SG (10G)" "IPv4|IPv6" \
"speedtest.nyc1.us.leaseweb.net" "5201-5210" "Leaseweb" "NYC, NY, US (10G)" "IPv4|IPv6" \
)
fi
# get the total number of iperf locations (total array size divided by 5 since each location has 5 elements)
IPERF_LOCS_NUM=${#IPERF_LOCS[@]}
IPERF_LOCS_NUM=$((IPERF_LOCS_NUM / 5))
if [ -z "$IPERF_DL_FAIL" ]; then
[[ ! -z $JSON ]] && JSON_RESULT+=',"iperf":['
[[ -n $JSON ]] && JSON_RESULT+=',"iperf":['
# check if the host has IPv4 connectivity, if so, run iperf3 IPv4 tests
[ ! -z "$IPV4_CHECK" ] && launch_iperf "IPv4"
[ -n "$IPV4_CHECK" ] && launch_iperf "IPv4"
# check if the host has IPv6 connectivity, if so, run iperf3 IPv6 tests
[ ! -z "$IPV6_CHECK" ] && launch_iperf "IPv6"
[[ ! -z $JSON ]] && JSON_RESULT=${JSON_RESULT::${#JSON_RESULT}-1} && JSON_RESULT+=']'
[ -n "$IPV6_CHECK" ] && launch_iperf "IPv6"
[[ -n $JSON ]] && JSON_RESULT=${JSON_RESULT::${#JSON_RESULT}-1} && JSON_RESULT+=']'
else
echo -e "\niperf3 binary download failed. Skipping iperf network tests..."
fi
@ -859,7 +951,7 @@ function launch_geekbench {
GB_RUN=""
# check for curl vs wget
[[ ! -z $LOCAL_CURL ]] && DL_CMD="curl -s" || DL_CMD="wget -qO-"
[[ -n $LOCAL_CURL ]] && DL_CMD="curl -s" || DL_CMD="wget -qO-"
if [[ $VERSION == *4* && ($ARCH = *aarch64* || $ARCH = *arm*) ]]; then
echo -e "\nARM architecture not supported by Geekbench 4, use Geekbench 5 or 6."
@ -899,7 +991,7 @@ function launch_geekbench {
fi
# unlock if license file detected
test -f "geekbench.license" && "$GEEKBENCH_PATH/$GB_CMD" --unlock $(cat geekbench.license) > /dev/null 2>&1
test -f "geekbench.license" && "$GEEKBENCH_PATH/$GB_CMD" --unlock "$(cat geekbench.license)" > /dev/null 2>&1
# run the Geekbench test and grep the test results URL given at the end of the test
GEEKBENCH_TEST=$("$GEEKBENCH_PATH/$GB_CMD" --upload 2>/dev/null | grep "https://browser")
@ -922,112 +1014,39 @@ function launch_geekbench {
fi
else
# if the Geekbench test succeeded, parse the test results URL
GEEKBENCH_URL=$(echo -e $GEEKBENCH_TEST | head -1)
GEEKBENCH_URL_CLAIM=$(echo $GEEKBENCH_URL | awk '{ print $2 }')
GEEKBENCH_URL=$(echo $GEEKBENCH_URL | awk '{ print $1 }')
# sleep a bit to wait for results to be made available on the geekbench website
sleep 10
# parse the public results page for the single and multi core geekbench scores
[[ $VERSION == *4* ]] && GEEKBENCH_SCORES=$($DL_CMD $GEEKBENCH_URL | grep "span class='score'") || \
GEEKBENCH_SCORES=$($DL_CMD $GEEKBENCH_URL | grep "div class='score'")
GEEKBENCH_SCORES_SINGLE=$(echo $GEEKBENCH_SCORES | awk -v FS="(>|<)" '{ print $3 }')
GEEKBENCH_SCORES_MULTI=$(echo $GEEKBENCH_SCORES | awk -v FS="(>|<)" '{ print $7 }')
# print the Geekbench results
GEEKBENCH_URL=$(echo -e "$GEEKBENCH_TEST" | head -1 | awk '{ print $1 }')
[[ -n $JSON ]] && GB_VER_NUM=$(echo "$VERSION" | awk '{ print substr ($0, 1, 1)}') \
&& JSON_RESULT+=',"gb'$GB_VER_NUM'":"'$GEEKBENCH_URL'"'
echo -en "\r\033[0K"
echo -e "Geekbench $VERSION Benchmark Test:"
echo -e "---------------------------------"
printf "%-15s | %-30s\n" "Test" "Value"
printf "%-15s | %-30s\n"
printf "%-15s | %-30s\n" "Single Core" "$GEEKBENCH_SCORES_SINGLE"
printf "%-15s | %-30s\n" "Multi Core" "$GEEKBENCH_SCORES_MULTI"
printf "%-15s | %-30s\n" "Full Test" "$GEEKBENCH_URL"
if [ ! -z $JSON ]; then
JSON_RESULT+='{"version":'$VERSION',"single":'$GEEKBENCH_SCORES_SINGLE',"multi":'$GEEKBENCH_SCORES_MULTI
JSON_RESULT+=',"url":"'$GEEKBENCH_URL'"},'
fi
# write the geekbench claim URL to a file so the user can add the results to their profile (if desired)
[ ! -z "$GEEKBENCH_URL_CLAIM" ] && echo -e "$GEEKBENCH_URL_CLAIM" >> geekbench_claim.url 2> /dev/null
echo -e "Test : $GEEKBENCH_URL"
fi
fi
}
# if the skip geekbench flag was set, skip the system performance test, otherwise test system performance
# if the skip Geekbench flag was set, skip the Geekbench performance test, otherwise test using Geekbench
if [ -z "$SKIP_GEEKBENCH" ]; then
[[ ! -z $JSON ]] && JSON_RESULT+=',"geekbench":['
if [[ $GEEKBENCH_4 == *True* ]]; then
if [ -n "$GEEKBENCH_4" ]; then
launch_geekbench 4
fi
if [[ $GEEKBENCH_5 == *True* ]]; then
if [ -n "$GEEKBENCH_5" ]; then
launch_geekbench 5
fi
if [[ $GEEKBENCH_6 == *True* ]]; then
if [ -n "$GEEKBENCH_6" ]; then
launch_geekbench 6
fi
[[ ! -z $JSON ]] && [[ $(echo -n $JSON_RESULT | tail -c 1) == ',' ]] && JSON_RESULT=${JSON_RESULT::${#JSON_RESULT}-1}
[[ ! -z $JSON ]] && JSON_RESULT+=']'
fi
# finished all tests, clean up all YABS files and exit
echo -e
echo -e "YABS completed in $(( $(date +%s) - YABS_START_TIME )) seconds."
[[ -n $JSON ]] && JSON_RESULT+='}}'
[[ $JSON = *w* ]] && echo "$JSON_RESULT" > "$JSON_FILE"
[[ $JSON = *s* ]] && echo "$JSON_RESULT" | curl -s -H "Content-Type: application/json" -X POST -d @- "$JSON_SEND"
# remove the yabs temp directory that was created for the disk test files, iperf binary, etc.
rm -rf "$YABS_PATH"
YABS_END_TIME=$(date +%s)
# calculate_time_taken
# Purpose: This method is designed to find the time taken for the completion of a YABS run.
# Parameters:
# 1. YABS_END_TIME - time when GB has completed and all files are removed
# 2. YABS_START_TIME - time when YABS is started
function calculate_time_taken() {
end_time=$1
start_time=$2
time_taken=$(( ${end_time} - ${start_time} ))
if [ ${time_taken} -gt 60 ]; then
min=$(expr $time_taken / 60)
sec=$(expr $time_taken % 60)
echo "YABS completed in ${min} min ${sec} sec"
else
echo "YABS completed in ${time_taken} sec"
fi
[[ ! -z $JSON ]] && JSON_RESULT+=',"runtime":{"start":'$start_time',"end":'$end_time',"elapsed":'$time_taken'}'
}
calculate_time_taken $YABS_END_TIME $YABS_START_TIME
if [[ ! -z $JSON ]]; then
JSON_RESULT+='}'
# write json results to file
if [[ $JSON = *w* ]]; then
echo $JSON_RESULT > "$JSON_FILE"
fi
# send json results
if [[ $JSON = *s* ]]; then
IFS=',' read -r -a JSON_SITES <<< "$JSON_SEND"
for JSON_SITE in "${JSON_SITES[@]}"
do
if [[ ! -z $LOCAL_CURL ]]; then
curl -s -H "Content-Type:application/json" -X POST --data ''"$JSON_RESULT"'' $JSON_SITE
else
wget -qO- --post-data=''"$JSON_RESULT"'' --header='Content-Type:application/json' $JSON_SITE
fi
done
fi
# print json result to screen
if [[ $JSON = *j* ]]; then
echo -e
echo $JSON_RESULT
fi
fi
# reset locale settings
# reset locale to its original state
unset LC_ALL
exit 0