2019-10-03 08:48:33 +07:00
#!/bin/bash
2020-01-09 09:22:43 +07:00
# Yet Another Bench Script by Mason Rowe
2022-11-23 11:49:34 +07:00
# Initial Oct 2019; Last update Nov 2022
2020-01-09 09:22:43 +07:00
#
# Disclaimer: This project is a work in progress. Any errors or suggestions should be
# relayed to me via the GitHub project page linked below.
#
# Purpose: The purpose of this script is to quickly gauge the performance of a Linux-
# based server by benchmarking network performance via iperf3, CPU and
2020-02-11 11:56:08 +07:00
# overall system performance via Geekbench 4/5, and random disk
2020-02-05 09:43:28 +07:00
# performance via fio. The script is designed to not require any dependencies
2020-01-09 09:22:43 +07:00
# - either compiled or installed - nor admin privileges to run.
#
2022-11-23 11:49:34 +07:00
YABS_VERSION = "v2022-11-22"
2020-01-09 09:22:43 +07:00
2019-10-03 08:48:33 +07:00
echo -e '# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #'
echo -e '# Yet-Another-Bench-Script #'
2022-08-15 11:13:11 +07:00
echo -e '# ' $YABS_VERSION ' #'
2019-10-03 08:48:33 +07:00
echo -e '# https://github.com/masonr/yet-another-bench-script #'
echo -e '# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #'
2019-10-03 21:22:58 +07:00
echo -e
date
2022-08-17 11:24:54 +07:00
TIME_START = $( date '+%Y%m%d-%H%M%S' )
2019-10-03 21:22:58 +07:00
2020-07-22 11:48:53 +07:00
# override locale to eliminate parsing errors (i.e. using commas as delimiters rather than periods)
2021-11-30 07:53:50 +07:00
if locale -a | grep ^C$ > /dev/null ; then
# locale "C" installed
export LC_ALL = C
else
# locale "C" not installed, display warning
2021-12-03 22:50:07 +07:00
echo -e "\nWarning: locale 'C' not detected. Test outputs may not be parsed correctly."
2021-11-30 07:53:50 +07:00
fi
2020-01-11 03:48:58 +07:00
2020-02-05 09:43:28 +07:00
# 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"
2021-06-05 14:12:29 +07:00
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
2021-11-30 12:36:13 +07:00
echo -e "\nARM compatibility is considered *experimental*"
2020-02-05 09:43:28 +07:00
else
# host is running a non-supported kernel
echo -e "Architecture not supported by YABS."
exit 1
fi
2020-02-11 11:56:08 +07:00
# flags to skip certain performance tests
2022-08-20 06:27:32 +07:00
unset PREFER_BIN SKIP_FIO SKIP_IPERF SKIP_GEEKBENCH PRINT_HELP REDUCE_NET GEEKBENCH_4 GEEKBENCH_5 DD_FALLBACK IPERF_DL_FAIL JSON JSON_SEND JSON_RESULT JSON_FILE
2020-06-21 03:01:06 +07:00
GEEKBENCH_5 = "True" # gb5 test enabled by default
2020-02-11 11:56:08 +07:00
# get any arguments that were passed to the script and set the associated skip flags (if applicable)
2022-08-20 06:27:32 +07:00
while getopts 'bfdighr49jw:s:' flag; do
2020-02-11 11:56:08 +07:00
case " ${ flag } " in
2021-11-30 12:36:13 +07:00
b) PREFER_BIN = "True" ; ;
2020-02-11 11:56:08 +07:00
f) SKIP_FIO = "True" ; ;
d) SKIP_FIO = "True" ; ;
i) SKIP_IPERF = "True" ; ;
g) SKIP_GEEKBENCH = "True" ; ;
h) PRINT_HELP = "True" ; ;
r) REDUCE_NET = "True" ; ;
2020-06-21 03:01:06 +07:00
4) GEEKBENCH_4 = "True" && unset GEEKBENCH_5 ; ;
9) GEEKBENCH_4 = "True" && GEEKBENCH_5 = "True" ; ;
2022-08-17 11:24:54 +07:00
j) JSON += "j" ; ;
2022-08-20 06:27:32 +07:00
w) JSON += "w" && JSON_FILE = ${ OPTARG } ; ;
2022-08-17 11:24:54 +07:00
s) JSON += "s" && JSON_SEND = ${ OPTARG } ; ;
2020-02-11 11:56:08 +07:00
*) 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
2022-05-07 00:08:27 +07:00
# check for curl/wget
command -v curl >/dev/null 2>& 1 && LOCAL_CURL = true || unset LOCAL_CURL
2020-02-11 11:56:08 +07:00
# test if the host has IPv4/IPv6 connectivity
2022-05-07 00:08:27 +07:00
[ [ ! -z $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)
2022-02-19 10:57:29 +07:00
if [ [ -z " $IPV4_CHECK " && -z " $IPV6_CHECK " ] ] ; then
echo -e
echo -e "Warning: Both IPv4 AND IPv6 connectivity were not detected. Check for DNS issues..."
fi
2020-02-11 11:56:08 +07:00
# print help and exit script, if help flag was passed
if [ ! -z " $PRINT_HELP " ] ; then
echo -e
2021-11-30 12:36:13 +07:00
echo -e "Usage: ./yabs.sh [-flags]"
2020-02-11 11:56:08 +07:00
echo -e " curl -sL yabs.sh | bash"
2022-08-17 11:24:54 +07:00
echo -e " curl -sL yabs.sh | bash -s -- -flags"
2022-05-07 00:08:27 +07:00
echo -e " wget -qO- yabs.sh | bash"
2022-08-17 11:24:54 +07:00
echo -e " wget -qO- yabs.sh | bash -s -- -flags"
2020-02-11 11:56:08 +07:00
echo -e
echo -e "Flags:"
2021-11-30 12:36:13 +07:00
echo -e " -b : prefer pre-compiled binaries from repo over local packages"
2020-02-11 11:56:08 +07:00
echo -e " -f/d : skips the fio disk benchmark test"
echo -e " -i : skips the iperf network test"
echo -e " -g : skips the geekbench performance test"
echo -e " -h : prints this lovely message, shows any flags you passed,"
echo -e " shows if fio/iperf3 local packages have been detected,"
echo -e " then exits"
echo -e " -r : reduce number of iperf3 network locations (to only three)"
echo -e " to lessen bandwidth usage"
echo -e " -4 : use geekbench 4 instead of geekbench 5"
2020-07-22 11:48:53 +07:00
echo -e " -9 : use both geekbench 4 AND geekbench 5"
2022-08-17 11:24:54 +07:00
echo -e " -j : print jsonified YABS results at conclusion of test"
2022-08-20 06:27:32 +07:00
echo -e " -w <filename> : write jsonified YABS results to disk using file name provided"
2022-08-17 11:24:54 +07:00
echo -e " -s <url> : send jsonified YABS results to URL"
2020-02-11 11:56:08 +07:00
echo -e
echo -e " Detected Arch: $ARCH "
echo -e
echo -e "Detected Flags:"
2021-11-30 12:36:13 +07:00
[ [ ! -z $PREFER_BIN ] ] && echo -e " -b, force using precompiled binaries from repo"
2020-02-11 11:56:08 +07:00
[ [ ! -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 $REDUCE_NET ] ] && echo -e " -r, using reduced (3) iperf3 locations"
2020-06-21 03:01:06 +07:00
[ [ ! -z $GEEKBENCH_4 ] ] && echo -e " running geekbench 4"
[ [ ! -z $GEEKBENCH_5 ] ] && echo -e " running geekbench 5"
2020-02-11 11:56:08 +07:00
echo -e
echo -e "Local Binary Check:"
[ [ -z $LOCAL_FIO ] ] && echo -e " fio not detected, will download precompiled binary" ||
2021-11-30 12:36:13 +07:00
[ [ -z $PREFER_BIN ] ] && echo -e " fio detected, using local package" ||
echo -e " fio detected, but using precompiled binary instead"
2020-02-11 11:56:08 +07:00
[ [ -z $LOCAL_IPERF ] ] && echo -e " iperf3 not detected, will download precompiled binary" ||
2021-11-30 12:36:13 +07:00
[ [ -z $PREFER_BIN ] ] && echo -e " iperf3 detected, using local package" ||
echo -e " iperf3 detected, but using precompiled binary instead"
2020-02-11 11:56:08 +07:00
echo -e
2020-12-07 14:15:52 +07:00
echo -e "Detected Connectivity:"
[ [ ! -z $IPV4_CHECK ] ] && echo -e " IPv4 connected" ||
echo -e " IPv4 not connected"
[ [ ! -z $IPV6_CHECK ] ] && echo -e " IPv6 connected" ||
echo -e " IPv6 not connected"
echo -e
2022-08-17 11:24:54 +07:00
echo -e "JSON Options:"
[ [ -z $JSON ] ] && echo -e " none"
[ [ $JSON = *j* ] ] && echo -e " printing json to screen after test"
2022-08-20 06:27:32 +07:00
[ [ $JSON = *w* ] ] && echo -e " writing json to file ( $JSON_FILE ) after test "
2022-08-17 11:24:54 +07:00
[ [ $JSON = *s* ] ] && echo -e " sharing json YABS results to $JSON_SEND "
2022-08-15 11:13:11 +07:00
echo -e
2020-02-11 11:56:08 +07:00
echo -e "Exiting..."
exit 0
fi
2020-09-24 04:17:00 +07:00
# format_size
# Purpose: Formats raw disk and memory sizes from kibibytes (KiB) to largest unit
# Parameters:
# 1. RAW - the raw memory size (RAM/Swap) in kibibytes
# Returns:
# Formatted memory size in KiB, MiB, GiB, or TiB
2020-12-07 14:15:52 +07:00
function format_size {
2020-11-20 13:11:38 +07:00
RAW = $1 # mem size in KiB
RESULT = $RAW
local DENOM = 1
local UNIT = "KiB"
2020-09-24 04:17:00 +07:00
# ensure the raw value is a number, otherwise return blank
re = '^[0-9]+$'
if ! [ [ $RAW = ~ $re ] ] ; then
echo ""
return 0
fi
if [ " $RAW " -ge 1073741824 ] ; then
DENOM = 1073741824
UNIT = "TiB"
2020-11-20 13:11:38 +07:00
elif [ " $RAW " -ge 1048576 ] ; then
DENOM = 1048576
UNIT = "GiB"
elif [ " $RAW " -ge 1024 ] ; then
DENOM = 1024
UNIT = "MiB"
fi
# 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) }' )
# concat formatted result value with units and return result
RESULT = " $RESULT $UNIT "
echo $RESULT
2020-09-24 04:17:00 +07:00
}
2020-01-09 09:22:43 +07:00
# gather basic system information (inc. CPU, AES-NI/virt status, RAM + swap + disk size)
2019-10-03 21:22:58 +07:00
echo -e
echo -e "Basic System Information:"
echo -e "---------------------------------"
2022-05-07 00:08:27 +07:00
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 "
2021-06-05 14:12:29 +07:00
if [ [ $ARCH = *aarch64* || $ARCH = *arm* ] ] ; 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
2019-10-04 09:33:33 +07:00
echo -e " Processor : $CPU_PROC "
2021-06-05 14:12:29 +07:00
if [ [ $ARCH = *aarch64* || $ARCH = *arm* ] ] ; then
2021-06-11 10:18:06 +07:00
CPU_CORES = $( lscpu | grep "^[[:blank:]]*CPU(s):" | sed 's/CPU(s): *//g' )
2021-06-05 14:12:29 +07:00
CPU_FREQ = $( lscpu | grep "CPU max MHz" | sed 's/CPU max MHz: *//g' )
2021-06-11 10:18:06 +07:00
[ [ -z " $CPU_FREQ " ] ] && CPU_FREQ = "???"
2021-06-05 14:12:29 +07:00
CPU_FREQ = " ${ CPU_FREQ } MHz "
else
CPU_CORES = $( awk -F: '/model name/ {core++} END {print core}' /proc/cpuinfo)
CPU_FREQ = $( awk -F: ' /cpu MHz/ {freq=$2} END {print freq " MHz"}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//' )
fi
2019-10-04 09:33:33 +07:00
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"
echo -e " AES-NI : $CPU_AES "
2019-10-07 19:57:24 +07:00
CPU_VIRT = $( cat /proc/cpuinfo | grep 'vmx\|svm' )
2019-10-04 09:33:33 +07:00
[ [ -z " $CPU_VIRT " ] ] && CPU_VIRT = "\xE2\x9D\x8C Disabled" || CPU_VIRT = "\xE2\x9C\x94 Enabled"
echo -e " VM-x/AMD-V : $CPU_VIRT "
2022-08-15 11:13:11 +07:00
TOTAL_RAM_RAW = $( free | awk 'NR==2 {print $2}' )
TOTAL_RAM = $( format_size $TOTAL_RAM_RAW )
2019-10-04 09:33:33 +07:00
echo -e " RAM : $TOTAL_RAM "
2022-08-15 11:13:11 +07:00
TOTAL_SWAP_RAW = $( free | grep Swap | awk '{ print $2 }' )
TOTAL_SWAP = $( format_size $TOTAL_SWAP_RAW )
2019-10-04 09:33:33 +07:00
echo -e " Swap : $TOTAL_SWAP "
2020-01-09 09:22:43 +07:00
# total disk size is calculated by adding all partitions of the types listed below (after the -t flags)
2022-08-15 11:13:11 +07:00
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 )
2019-10-04 09:33:33 +07:00
echo -e " Disk : $TOTAL_DISK "
2022-05-07 00:08:27 +07:00
DISTRO = $( grep 'PRETTY_NAME' /etc/os-release | cut -d '"' -f 2 )
echo -e " Distro : $DISTRO "
KERNEL = $( uname -r)
echo -e " Kernel : $KERNEL "
2019-10-03 21:22:58 +07:00
2022-08-17 11:24:54 +07:00
if [ ! -z $JSON ] ; then
2022-08-15 11:13:11 +07:00
UPTIME_S = $( awk '{print $1}' /proc/uptime)
IPV4 = $( [ ! -z $IPV4_CHECK ] && echo "true" || echo "false" )
IPV6 = $( [ ! -z $IPV6_CHECK ] && echo "true" || echo "false" )
AES = $( [ [ " $CPU_AES " = *Enabled* ] ] && echo "true" || echo "false" )
VIRT = $( [ [ " $CPU_VIRT " = *Enabled* ] ] && echo "true" || echo "false" )
2022-08-17 11:24:54 +07:00
JSON_RESULT = '{"version":"' $YABS_VERSION '","time":"' $TIME_START '","os":{"arch":"' $ARCH '","distro":"' $DISTRO '","kernel":"' $KERNEL '",'
JSON_RESULT += '"uptime":' $UPTIME_S '},"net":{"ipv4":' $IPV4 ',"ipv6":' $IPV6 '},"cpu":{"model":"' $CPU_PROC '","cores":' $CPU_CORES ','
JSON_RESULT += '"freq":"' $CPU_FREQ '","aes":' $AES ',"virt":' $VIRT '},"mem":{"ram":' $TOTAL_RAM_RAW ',"swap":' $TOTAL_SWAP_RAW ',"disk":' $TOTAL_DISK_RAW '}'
2022-08-15 11:13:11 +07:00
fi
2020-01-09 09:22:43 +07:00
# create a directory in the same location that the script is being run to temporarily store YABS-related files
2019-10-04 09:33:33 +07:00
DATE = ` date -Iseconds | sed -e "s/:/_/g" `
2019-10-09 01:36:02 +07:00
YABS_PATH = ./$DATE
touch $DATE .test 2> /dev/null
2020-01-09 09:22:43 +07:00
# test if the user has write permissions in the current directory and exit if not
2019-10-09 01:36:02 +07:00
if [ ! -f " $DATE .test " ] ; then
echo -e
echo -e "You do not have write permission in this directory. Switch to an owned directory and re-run the script.\nExiting..."
exit 1
fi
rm $DATE .test
2019-10-05 08:14:41 +07:00
mkdir -p $YABS_PATH
2020-06-21 03:01:06 +07:00
# trap CTRL+C signals to exit script cleanly
trap catch_abort INT
# catch_abort
# 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
}
2020-02-05 09:43:28 +07:00
# format_speed
2021-08-08 16:56:34 +07:00
# Purpose: This method is a convenience function to format the output of the fio disk tests which
2020-02-05 09:43:28 +07:00
# always returns a result in KB/s. If result is >= 1 GB/s, use GB/s. If result is < 1 GB/s
# and >= 1 MB/s, then use MB/s. Otherwise, use KB/s.
# Parameters:
# 1. RAW - the raw disk speed result (in KB/s)
# Returns:
# Formatted disk speed in GB/s, MB/s, or KB/s
function format_speed {
RAW = $1 # disk speed in KB/s
RESULT = $RAW
local DENOM = 1
local UNIT = "KB/s"
# ensure raw value is not null, if it is, return blank
2020-02-11 11:56:08 +07:00
if [ -z " $RAW " ] ; then
echo ""
return 0
fi
2020-02-05 09:43:28 +07:00
# check if disk speed >= 1 GB/s
if [ " $RAW " -ge 1000000 ] ; then
DENOM = 1000000
UNIT = "GB/s"
# check if disk speed < 1 GB/s && >= 1 MB/s
elif [ " $RAW " -ge 1000 ] ; then
DENOM = 1000
UNIT = "MB/s"
fi
# 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) }' )
# concat formatted result value with units and return result
RESULT = " $RESULT $UNIT "
echo $RESULT
}
# format_iops
2020-07-22 11:48:53 +07:00
# Purpose: This method is a convenience function to format the output of the raw IOPS result
2020-02-05 09:43:28 +07:00
# Parameters:
# 1. RAW - the raw IOPS result
# Returns:
# Formatted IOPS (i.e. 8, 123, 1.7k, 275.9k, etc.)
function format_iops {
RAW = $1 # iops
RESULT = $RAW
# ensure raw value is not null, if it is, return blank
if [ -z " $RAW " ] ; then
echo ""
return 0
fi
# check if IOPS speed > 1k
if [ " $RAW " -ge 1000 ] ; then
# 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 = " $RESULT " k
fi
echo $RESULT
}
2020-01-09 09:22:43 +07:00
# disk_test
# Purpose: This method is designed to test the disk performance of the host using the partition that the
2020-02-05 21:03:52 +07:00
# script is being run from using fio random read/write speed tests.
2020-01-09 09:22:43 +07:00
# Parameters:
# - (none)
2019-10-09 01:36:02 +07:00
function disk_test {
2021-06-05 14:12:29 +07:00
if [ [ " $ARCH " = "aarch64" || " $ARCH " = "arm" ] ] ; then
FIO_SIZE = 512M
else
FIO_SIZE = 2G
fi
2020-02-05 09:43:28 +07:00
# run a quick test to generate the fio test file to be used by the actual tests
echo -en "Generating fio test file..."
2021-06-05 14:12:29 +07:00
$FIO_CMD --name= setup --ioengine= libaio --rw= read --bs= 64k --iodepth= 64 --numjobs= 2 --size= $FIO_SIZE --runtime= 1 --gtod_reduce= 1 --filename= $DISK_PATH /test.fio --direct= 1 --minimal & > /dev/null
2020-02-05 09:43:28 +07:00
echo -en "\r\033[0K"
2020-06-21 03:01:06 +07:00
# get array of block sizes to evaluate
BLOCK_SIZES = ( " $@ " )
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... "
2021-06-05 14:12:29 +07:00
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 )
2020-06-21 03:01:06 +07:00
DISK_IOPS_R = $( echo $DISK_TEST | awk -F';' '{print $8}' )
DISK_IOPS_W = $( echo $DISK_TEST | awk -F';' '{print $49}' )
2022-08-15 11:13:11 +07:00
DISK_IOPS = $( awk -v a = " $DISK_IOPS_R " -v b = " $DISK_IOPS_W " 'BEGIN { print a + b }' )
2020-06-21 03:01:06 +07:00
DISK_TEST_R = $( echo $DISK_TEST | awk -F';' '{print $7}' )
DISK_TEST_W = $( echo $DISK_TEST | awk -F';' '{print $48}' )
2022-08-15 11:13:11 +07:00
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 )
2020-06-21 03:01:06 +07:00
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"
done
2020-02-11 11:56:08 +07:00
}
# 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
# is better than nothing.
# Parameters:
# - (none)
function dd_test {
I = 0
DISK_WRITE_TEST_RES = ( )
DISK_READ_TEST_RES = ( )
DISK_WRITE_TEST_AVG = 0
DISK_READ_TEST_AVG = 0
# run the disk speed tests (write and read) thrice over
while [ $I -lt 3 ]
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)
[ [ " $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)
2020-11-20 13:11:38 +07:00
[ [ " $DISK_READ_TEST " = = *"GB" * ] ] && VAL = $( awk -v a = " $VAL " 'BEGIN { print a * 1000 }' )
2020-02-11 11:56:08 +07:00
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 ))
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 }' )
DISK_READ_TEST_AVG = $( awk -v a = " $DISK_READ_TEST_AVG " 'BEGIN { print a / 3 }' )
2019-10-05 08:14:41 +07:00
}
2020-12-27 13:45:40 +07:00
# check if disk performance is being tested and the host has required space (2G)
AVAIL_SPACE = ` df -k . | awk 'NR==2{print $4}' `
2021-06-05 14:12:29 +07:00
if [ [ -z " $SKIP_FIO " && " $AVAIL_SPACE " -lt 2097152 && " $ARCH " != "aarch64" && " $ARCH " != "arm" ] ] ; then # 2GB = 2097152KB
2020-12-27 13:45:40 +07:00
echo -e "\nLess than 2GB of space available. Skipping disk test..."
2021-06-05 14:12:29 +07:00
elif [ [ -z " $SKIP_FIO " && " $AVAIL_SPACE " -lt 524288 && ( " $ARCH " = "aarch64" || " $ARCH " = "arm" ) ] ] ; then # 512MB = 524288KB
echo -e "\nLess than 512MB of space available. Skipping disk test..."
2020-01-09 09:22:43 +07:00
# if the skip disk flag was set, skip the disk performance test, otherwise test disk performance
2020-12-27 13:45:40 +07:00
elif [ -z " $SKIP_FIO " ] ; then
2020-12-29 20:39:49 +07:00
# 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 )) )
warning = 0
poss = ( )
for pathls in $( df -Th | awk '{print $7}' | tail -n +2)
do
if [ [ " ${ PWD ## $pathls } " != " ${ PWD } " ] ] ; then
poss += ( $pathls )
fi
done
2019-10-09 01:36:02 +07:00
2020-12-29 20:39:49 +07:00
long = ""
m = -1
for x in ${ poss [@] }
do
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)
if [ [ $size_b = = 'T' ] ] ; then
free_space = $( bc <<< " $free_space *1024 " )
size_b = 'G'
2020-12-29 02:25:06 +07:00
fi
2020-12-29 20:39:49 +07:00
if [ [ $( df -Th | grep -w $long ) = = *"zfs" * ] ] ; then
if [ [ $size_b = = 'G' ] ] ; then
if [ [ $( echo " $free_space < $mul_spa " | bc) -ne 0 ] ] ; then
warning = 1
fi
else
2020-12-29 02:25:06 +07:00
warning = 1
fi
2020-12-29 20:39:49 +07:00
fi
if [ [ $warning -eq 1 ] ] ; 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 "
2020-12-29 02:25:06 +07:00
fi
fi
2020-12-29 20:39:49 +07:00
echo -en "\nPreparing system for disk tests..."
2020-12-29 02:25:06 +07:00
2020-01-09 09:22:43 +07:00
# create temp directory to store disk write/read test files
2019-10-09 01:36:02 +07:00
DISK_PATH = $YABS_PATH /disk
mkdir -p $DISK_PATH
2020-02-05 09:43:28 +07:00
2021-11-30 12:36:13 +07:00
if [ [ -z " $PREFER_BIN " && ! -z " $LOCAL_FIO " ] ] ; then # local fio has been detected, use instead of pre-compiled binary
2020-02-11 11:56:08 +07:00
FIO_CMD = fio
else
# download fio binary
2022-05-07 00:08:27 +07:00
if [ [ ! -z $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
fi
2020-02-11 11:56:08 +07:00
2020-11-20 13:11:38 +07:00
if [ ! -f " $DISK_PATH /fio " ] ; then # ensure fio binary download successfully
echo -en "\r\033[0K"
echo -e "Fio binary download failed. Running dd test as fallback...."
DD_FALLBACK = True
else
chmod +x $DISK_PATH /fio
FIO_CMD = $DISK_PATH /fio
fi
2020-02-05 09:43:28 +07:00
fi
2020-11-20 13:11:38 +07:00
if [ -z " $DD_FALLBACK " ] ; then # if not falling back on dd tests, run fio test
echo -en "\r\033[0K"
# init global array to store disk performance values
2022-08-15 11:13:11 +07:00
declare -a DISK_RESULTS DISK_RESULTS_RAW
2020-11-20 13:11:38 +07:00
# disk block sizes to evaluate
BLOCK_SIZES = ( "4k" "64k" "512k" "1m" )
2020-06-21 03:01:06 +07:00
2020-11-20 13:11:38 +07:00
# execute disk performance test
disk_test " ${ BLOCK_SIZES [@] } "
fi
2019-10-09 01:36:02 +07:00
2020-11-20 13:11:38 +07:00
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 [ -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
2020-02-11 11:56:08 +07:00
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
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
DISK_READ_TEST_AVG = $( awk -v a = " $DISK_READ_TEST_AVG " 'BEGIN { print a / 1000 }' )
DISK_READ_TEST_UNIT = "GB/s"
else
DISK_READ_TEST_UNIT = "MB/s"
fi
# print dd sequential disk speed test results
echo -e
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 } "
2021-08-08 16:56:34 +07:00
else # fio tests completed successfully, print results
2022-08-17 11:24:54 +07:00
[ [ ! -z $JSON ] ] && JSON_RESULT += ',"fio":['
2020-06-21 03:01:06 +07:00
DISK_RESULTS_NUM = $( expr ${# DISK_RESULTS [@] } / 6)
DISK_COUNT = 0
2020-02-05 09:43:28 +07:00
# print disk speed test results
echo -e "fio Disk Speed Tests (Mixed R/W 50/50):"
echo -e "---------------------------------"
2020-06-21 03:01:06 +07:00
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] } ) "
2022-08-17 11:24:54 +07:00
if [ ! -z $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] } '},'
JSON_RESULT += '{"bs":"' ${ BLOCK_SIZES [DISK_COUNT+1] } '","speed_r":' ${ DISK_RESULTS_RAW [(DISK_COUNT+1)*6+1] } ',"iops_r":' ${ DISK_RESULTS_RAW [(DISK_COUNT+1)*6+4] }
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] } '},'
2022-08-15 11:13:11 +07:00
fi
2020-06-21 03:01:06 +07:00
DISK_COUNT = $( expr $DISK_COUNT + 2)
done
2022-08-17 11:24:54 +07:00
[ [ ! -z $JSON ] ] && JSON_RESULT = ${ JSON_RESULT : : ${# JSON_RESULT } -1 } && JSON_RESULT += ']'
2019-10-09 01:36:02 +07:00
fi
2019-10-05 08:14:41 +07:00
fi
2020-01-09 09:22:43 +07:00
# 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
2021-08-08 16:56:34 +07:00
# (send and receive) are tested.
2020-01-09 09:22:43 +07:00
# Parameters:
# 1. URL - URL/domain name of the iperf server
# 2. PORTS - the range of ports on which the iperf server operates
# 3. HOST - the friendly name of the iperf server host/owner
# 4. FLAGS - any flags that should be passed to the iperf command
2019-10-03 09:51:36 +07:00
function iperf_test {
URL = $1
2019-10-04 09:33:33 +07:00
PORTS = $2
2020-01-09 09:22:43 +07:00
HOST = $3
FLAGS = $4
2019-10-03 09:51:36 +07:00
2022-06-12 04:46:39 +07:00
# attempt the iperf send test 3 times, allowing for a slot to become available on the
2020-01-09 09:22:43 +07:00
# server or to throw out any bad/error results
I = 1
2022-06-12 04:46:39 +07:00
while [ $I -le 3 ]
2019-10-03 09:51:36 +07:00
do
2022-06-12 04:46:39 +07:00
echo -en " Performing $MODE iperf3 send test to $HOST (Attempt # $I of 3)... "
2020-01-09 09:22:43 +07:00
# select a random iperf port from the range provided
2019-10-04 09:33:33 +07:00
PORT = ` shuf -i $PORTS -n 1`
2020-01-09 09:22:43 +07:00
# 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
2020-02-11 11:56:08 +07:00
IPERF_RUN_SEND = " $( timeout 15 $IPERF_CMD $FLAGS -c $URL -p $PORT -P 8 2> /dev/null) "
2020-01-09 09:22:43 +07:00
# check if iperf exited cleanly and did not return an error
2019-10-04 09:33:33 +07:00
if [ [ " $IPERF_RUN_SEND " = = *"receiver" * && " $IPERF_RUN_SEND " != *"error" * ] ] ; then
2020-01-09 09:22:43 +07:00
# test did not result in an error, parse speed result
2019-10-04 10:48:43 +07:00
SPEED = $( echo " ${ IPERF_RUN_SEND } " | grep SUM | grep receiver | awk '{ print $6 }' )
2020-01-09 09:22:43 +07:00
# 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
2019-10-03 09:51:36 +07:00
else
2020-01-09 09:22:43 +07:00
# 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
2019-10-03 09:51:36 +07:00
fi
2020-01-09 09:22:43 +07:00
echo -en "\r\033[0K"
2019-10-03 09:51:36 +07:00
done
2020-01-09 09:22:43 +07:00
# small sleep necessary to give iperf server a breather to get ready for a new test
sleep 1
2022-06-12 04:46:39 +07:00
# attempt the iperf receive test 3 times, allowing for a slot to become available on
2020-01-09 09:22:43 +07:00
# the server or to throw out any bad/error results
J = 1
2022-06-12 04:46:39 +07:00
while [ $J -le 3 ]
2019-10-03 09:51:36 +07:00
do
2022-06-12 04:46:39 +07:00
echo -n " Performing $MODE iperf3 recv test from $HOST (Attempt # $J of 3)... "
2020-01-09 09:22:43 +07:00
# select a random iperf port from the range provided
2019-10-04 09:33:33 +07:00
PORT = ` shuf -i $PORTS -n 1`
2021-08-08 16:56:34 +07:00
# run the iperf test receiving data from the iperf server to the host; includes
2020-01-09 09:22:43 +07:00
# a timeout of 15s in case the iperf server is not responding; uses 8 parallel
# threads for the network test
2020-02-11 11:56:08 +07:00
IPERF_RUN_RECV = " $( timeout 15 $IPERF_CMD $FLAGS -c $URL -p $PORT -P 8 -R 2> /dev/null) "
2020-01-09 09:22:43 +07:00
# check if iperf exited cleanly and did not return an error
2019-10-04 09:33:33 +07:00
if [ [ " $IPERF_RUN_RECV " = = *"receiver" * && " $IPERF_RUN_RECV " != *"error" * ] ] ; then
2020-01-09 09:22:43 +07:00
# test did not result in an error, parse speed result
2019-10-04 10:48:43 +07:00
SPEED = $( echo " ${ IPERF_RUN_RECV } " | grep SUM | grep receiver | awk '{ print $6 }' )
2020-01-09 09:22:43 +07:00
# 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
2019-10-03 09:51:36 +07:00
else
2020-01-09 09:22:43 +07:00
# 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
2019-10-03 09:51:36 +07:00
fi
2020-01-09 09:22:43 +07:00
echo -en "\r\033[0K"
2019-10-03 09:51:36 +07:00
done
2022-11-23 11:46:52 +07:00
# Run a latency test via ping -c1 command -> will return "xx.x ms"
LATENCY_RUN = " $( ping -c1 $URL | grep -Po 'time=.*' | sed s/'time=' //) "
2019-10-03 09:51:36 +07:00
2021-08-08 16:56:34 +07:00
# parse the resulting send and receive speed results
2019-10-03 09:51:36 +07:00
IPERF_SENDRESULT = " $( echo " ${ IPERF_RUN_SEND } " | grep SUM | grep receiver) "
IPERF_RECVRESULT = " $( echo " ${ IPERF_RUN_RECV } " | grep SUM | grep receiver) "
2022-11-23 11:46:52 +07:00
LATENCY_RESULT = " $( echo " ${ LATENCY_RUN } " ) "
2019-10-03 09:51:36 +07:00
}
2020-01-09 09:22:43 +07:00
# launch_iperf
# Purpose: This method is designed to facilitate the execution of iperf network speed tests to
# each public iperf server in the iperf server locations array.
# Parameters:
# 1. MODE - indicates the type of iperf tests to run (IPv4 or IPv6)
2019-10-07 09:17:24 +07:00
function launch_iperf {
2019-10-09 01:36:02 +07:00
MODE = $1
2020-01-09 09:22:43 +07:00
[ [ " $MODE " = = *"IPv6" * ] ] && IPERF_FLAGS = "-6" || IPERF_FLAGS = "-4"
2019-10-07 09:17:24 +07:00
2020-01-09 09:22:43 +07:00
# print iperf3 network speed results as they are completed
2019-10-07 09:17:24 +07:00
echo -e
echo -e " iperf3 Network Speed Tests ( $MODE ): "
echo -e "---------------------------------"
2022-11-23 11:49:34 +07:00
printf "%-15s | %-25s | %-15s | %-15s | %-15s\n" "Provider" "Location (Link)" "Send Speed" "Recv Speed" "Ping"
2022-11-23 11:46:52 +07:00
printf "%-15s | %-25s | %-15s | %-15s | %-15s\n" "-----" "-----" "----" "----" "----"
2019-10-07 09:17:24 +07:00
2020-01-09 09:22:43 +07:00
# loop through iperf locations array to run iperf test using each public iperf server
2019-10-07 09:17:24 +07:00
for ( ( i = 0; i < IPERF_LOCS_NUM; i++ ) ) ; do
2020-01-09 09:22:43 +07:00
# test if the current iperf location supports the network mode being tested (IPv4/IPv6)
2019-10-07 09:17:24 +07:00
if [ [ " ${ IPERF_LOCS [i*5+4] } " = = *" $MODE " * ] ] ; then
2020-01-09 09:22:43 +07:00
# 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 "
2021-08-08 16:56:34 +07:00
# parse the send and receive speed results
2019-10-07 09:17:24 +07:00
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 }' )
2022-11-23 11:46:52 +07:00
LATENCY_VAL = $( echo $LATENCY_RESULT )
2020-01-09 09:22:43 +07:00
# if the results are blank, then the server is "busy" and being overutilized
2020-02-05 09:43:28 +07:00
[ [ -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 = ""
2020-01-09 09:22:43 +07:00
# print the speed results for the iperf location currently being evaluated
2022-11-23 11:46:52 +07:00
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 "
2022-08-17 11:24:54 +07:00
if [ ! -z $JSON ] ; then
JSON_RESULT += '{"mode":"' $MODE '","provider":"' ${ IPERF_LOCS [i*5+2] } '","loc":"' ${ IPERF_LOCS [i*5+3] }
2022-11-23 11:46:52 +07:00
JSON_RESULT += '","send":"' $IPERF_SENDRESULT_VAL ' ' $IPERF_SENDRESULT_UNIT '","recv":"' $IPERF_RECVRESULT_VAL ' ' $IPERF_RECVRESULT_UNIT '","latency":"' $LATENCY_VAL '"},'
2022-08-15 11:13:11 +07:00
fi
2019-10-07 09:17:24 +07:00
fi
done
}
2020-01-09 09:22:43 +07:00
# if the skip iperf flag was set, skip the network performance test, otherwise test network performance
2019-10-07 10:51:09 +07:00
if [ -z " $SKIP_IPERF " ] ; then
2020-02-05 09:43:28 +07:00
2021-11-30 12:36:13 +07:00
if [ [ -z " $PREFER_BIN " && ! -z " $LOCAL_IPERF " ] ] ; then # local iperf has been detected, use instead of pre-compiled binary
2020-02-11 11:56:08 +07:00
IPERF_CMD = iperf3
else
# create a temp directory to house the required iperf binary and library
IPERF_PATH = $YABS_PATH /iperf
mkdir -p $IPERF_PATH
# download iperf3 binary
2022-05-07 00:08:27 +07:00
if [ [ ! -z $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
fi
2020-02-05 09:43:28 +07:00
2020-11-20 13:11:38 +07:00
if [ ! -f " $IPERF_PATH /iperf3 " ] ; then # ensure iperf3 binary downloaded successfully
IPERF_DL_FAIL = True
else
chmod +x $IPERF_PATH /iperf3
IPERF_CMD = $IPERF_PATH /iperf3
fi
2020-02-11 11:56:08 +07:00
fi
2019-10-07 10:51:09 +07:00
2020-01-09 09:22:43 +07:00
# 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
# 2. range of ports that the iperf server is running on (lowest-highest)
# 3. friendly name of the host/owner of the iperf server
# 4. location and advertised speed link of the iperf server
# 5. network modes supported by the iperf server (IPv4 = IPv4-only, IPv4|IPv6 = IPv4 + IPv6, etc.)
2019-10-07 10:51:09 +07:00
IPERF_LOCS = ( \
2021-02-21 15:00:16 +07:00
"lon.speedtest.clouvider.net" "5200-5209" "Clouvider" "London, UK (10G)" "IPv4|IPv6" \
2019-10-07 10:51:09 +07:00
"ping.online.net" "5200-5209" "Online.net" "Paris, FR (10G)" "IPv4" \
"ping6.online.net" "5200-5209" "Online.net" "Paris, FR (10G)" "IPv6" \
2022-04-30 19:21:23 +07:00
"speedtest-nl-oum.hybula.net" "5201-5206" "Hybula" "The Netherlands (40G)" "IPv4|IPv6" \
2022-06-12 04:39:36 +07:00
"speedtest.uztelecom.uz" "5200-5207" "Uztelecom" "Tashkent, UZ (10G)" "IPv4|IPv6" \
2021-02-21 15:00:16 +07:00
"nyc.speedtest.clouvider.net" "5200-5209" "Clouvider" "NYC, NY, US (10G)" "IPv4|IPv6" \
2022-06-12 04:48:13 +07:00
"dal.speedtest.clouvider.net" "5200-5209" "Clouvider" "Dallas, TX, US (10G)" "IPv4|IPv6" \
2021-02-21 15:00:16 +07:00
"la.speedtest.clouvider.net" "5200-5209" "Clouvider" "Los Angeles, CA, US (10G)" "IPv4|IPv6" \
2019-10-07 10:51:09 +07:00
)
2020-02-11 11:56:08 +07:00
# if the "REDUCE_NET" flag is activated, then do a shorter iperf test with only three locations
2020-09-21 11:52:00 +07:00
# (Clouvider London, Clouvider NYC, and Online.net France)
2020-02-11 11:56:08 +07:00
if [ ! -z " $REDUCE_NET " ] ; then
IPERF_LOCS = ( \
2021-02-21 15:00:16 +07:00
"lon.speedtest.clouvider.net" "5200-5209" "Clouvider" "London, UK (10G)" "IPv4|IPv6" \
2020-02-11 11:56:08 +07:00
"ping.online.net" "5200-5209" "Online.net" "Paris, FR (10G)" "IPv4" \
"ping6.online.net" "5200-5209" "Online.net" "Paris, FR (10G)" "IPv6" \
2021-02-21 15:00:16 +07:00
"nyc.speedtest.clouvider.net" "5200-5209" "Clouvider" "NYC, NY, US (10G)" "IPv4|IPv6" \
2020-02-11 11:56:08 +07:00
)
fi
2019-10-07 10:51:09 +07:00
2020-01-09 09:22:43 +07:00
# get the total number of iperf locations (total array size divided by 5 since each location has 5 elements)
2019-10-07 10:51:09 +07:00
IPERF_LOCS_NUM = ${# IPERF_LOCS [@] }
IPERF_LOCS_NUM = $(( IPERF_LOCS_NUM / 5 ))
2020-11-20 13:11:38 +07:00
if [ -z " $IPERF_DL_FAIL " ] ; then
2022-08-17 11:24:54 +07:00
[ [ ! -z $JSON ] ] && JSON_RESULT += ',"iperf":['
2020-11-20 13:11:38 +07:00
# check if the host has IPv4 connectivity, if so, run iperf3 IPv4 tests
[ ! -z " $IPV4_CHECK " ] && launch_iperf "IPv4"
# check if the host has IPv6 connectivity, if so, run iperf3 IPv6 tests
[ ! -z " $IPV6_CHECK " ] && launch_iperf "IPv6"
2022-08-17 11:24:54 +07:00
[ [ ! -z $JSON ] ] && JSON_RESULT = ${ JSON_RESULT : : ${# JSON_RESULT } -1 } && JSON_RESULT += ']'
2020-11-20 13:11:38 +07:00
else
echo -e "\niperf3 binary download failed. Skipping iperf network tests..."
fi
2019-10-07 10:51:09 +07:00
fi
2020-06-21 03:01:06 +07:00
# launch_geekbench
# Purpose: This method is designed to run the Primate Labs' Geekbench 4/5 Cross-Platform Benchmark utility
# Parameters:
# 1. VERSION - indicates which Geekbench version to run
function launch_geekbench {
VERSION = $1
2020-01-09 09:22:43 +07:00
# create a temp directory to house all geekbench files
2020-06-21 03:01:06 +07:00
GEEKBENCH_PATH = $YABS_PATH /geekbench_$VERSION
2019-10-07 10:51:09 +07:00
mkdir -p $GEEKBENCH_PATH
2020-02-05 09:43:28 +07:00
2022-05-07 00:08:27 +07:00
# check for curl vs wget
[ [ ! -z $LOCAL_CURL ] ] && DL_CMD = "curl -s" || DL_CMD = "wget -qO-"
2021-06-05 14:12:29 +07:00
if [ [ $VERSION = = *4* && ( $ARCH = *aarch64* || $ARCH = *arm*) ] ] ; then
echo -e "\nARM architecture not supported by Geekbench 4, use Geekbench 5."
elif [ [ $VERSION = = *4* && $ARCH != *aarch64* && $ARCH != *arm* ] ] ; then # Geekbench v4
2020-11-20 13:11:38 +07:00
echo -en "\nRunning GB4 benchmark test... *cue elevator music*"
2020-02-11 11:56:08 +07:00
# download the latest Geekbench 4 tarball and extract to geekbench temp directory
2022-05-07 00:08:27 +07:00
$DL_CMD https://cdn.geekbench.com/Geekbench-4.4.4-Linux.tar.gz | tar xz --strip-components= 1 -C $GEEKBENCH_PATH & >/dev/null
2020-02-11 11:56:08 +07:00
if [ [ " $ARCH " = = *"x86" * ] ] ; then
2020-08-14 03:41:29 +07:00
# check if geekbench file exists
if test -f "geekbench.license" ; then
2020-09-10 08:32:25 +07:00
$GEEKBENCH_PATH /geekbench_x86_32 --unlock ` cat geekbench.license` > /dev/null 2>& 1
2020-08-14 03:41:29 +07:00
fi
2020-09-10 08:32:25 +07:00
2020-02-11 11:56:08 +07:00
# run the Geekbench 4 test and grep the test results URL given at the end of the test
2020-09-10 08:32:25 +07:00
GEEKBENCH_TEST = $( $GEEKBENCH_PATH /geekbench_x86_32 --upload 2>/dev/null | grep "https://browser" )
2020-02-11 11:56:08 +07:00
else
2020-08-14 03:41:29 +07:00
# check if geekbench file exists
if test -f "geekbench.license" ; then
2020-09-10 08:32:25 +07:00
$GEEKBENCH_PATH /geekbench4 --unlock ` cat geekbench.license` > /dev/null 2>& 1
2020-08-14 03:41:29 +07:00
fi
2020-02-11 11:56:08 +07:00
# run the Geekbench 4 test and grep the test results URL given at the end of the test
2020-09-10 08:32:25 +07:00
GEEKBENCH_TEST = $( $GEEKBENCH_PATH /geekbench4 --upload 2>/dev/null | grep "https://browser" )
2020-02-11 11:56:08 +07:00
fi
2020-02-05 09:43:28 +07:00
fi
2020-01-09 09:22:43 +07:00
2020-06-21 03:01:06 +07:00
if [ [ $VERSION = = *5* ] ] ; then # Geekbench v5
2020-11-20 13:11:38 +07:00
if [ [ $ARCH = *x86* && $GEEKBENCH_4 = = *False* ] ] ; then # don't run Geekbench 5 if on 32-bit arch
2020-06-21 03:01:06 +07:00
echo -e "\nGeekbench 5 cannot run on 32-bit architectures. Re-run with -4 flag to use"
2020-07-22 11:48:53 +07:00
echo -e "Geekbench 4, which can support 32-bit architectures. Skipping Geekbench 5."
2020-11-20 13:11:38 +07:00
elif [ [ $ARCH = *x86* && $GEEKBENCH_4 = = *True* ] ] ; then
echo -e "\nGeekbench 5 cannot run on 32-bit architectures. Skipping test."
2020-06-21 03:01:06 +07:00
else
2020-11-20 13:11:38 +07:00
echo -en "\nRunning GB5 benchmark test... *cue elevator music*"
2020-06-21 03:01:06 +07:00
# download the latest Geekbench 5 tarball and extract to geekbench temp directory
2021-06-05 14:12:29 +07:00
if [ [ $ARCH = *aarch64* || $ARCH = *arm* ] ] ; then
2022-05-07 00:08:27 +07:00
$DL_CMD https://cdn.geekbench.com/Geekbench-5.4.4-LinuxARMPreview.tar.gz | tar xz --strip-components= 1 -C $GEEKBENCH_PATH & >/dev/null
2021-06-05 14:12:29 +07:00
else
2022-08-20 21:54:24 +07:00
$DL_CMD https://cdn.geekbench.com/Geekbench-5.4.5-Linux.tar.gz | tar xz --strip-components= 1 -C $GEEKBENCH_PATH & >/dev/null
2021-06-05 14:12:29 +07:00
fi
2020-06-21 03:01:06 +07:00
2020-08-14 03:41:29 +07:00
# check if geekbench file exists
if test -f "geekbench.license" ; then
2020-09-10 08:32:25 +07:00
$GEEKBENCH_PATH /geekbench5 --unlock ` cat geekbench.license` > /dev/null 2>& 1
2020-08-14 03:41:29 +07:00
fi
2020-09-10 08:32:25 +07:00
GEEKBENCH_TEST = $( $GEEKBENCH_PATH /geekbench5 --upload 2>/dev/null | grep "https://browser" )
2020-06-21 03:01:06 +07:00
fi
fi
2020-01-09 09:22:43 +07:00
# ensure the test ran successfully
if [ -z " $GEEKBENCH_TEST " ] ; then
2020-12-29 20:39:49 +07:00
if [ [ -z " $IPV4_CHECK " ] ] ; then
2020-06-21 03:01:06 +07:00
# Geekbench test failed to download because host lacks IPv4 (cdn.geekbench.com = IPv4 only)
2020-02-05 09:43:28 +07:00
echo -e "\r\033[0KGeekbench releases can only be downloaded over IPv4. FTP the Geekbench files and run manually."
2020-11-20 13:11:38 +07:00
elif [ [ $ARCH != *x86* ] ] ; then
2020-02-11 11:56:08 +07:00
# if the Geekbench test failed for any reason, exit cleanly and print error message
2020-06-21 03:01:06 +07:00
echo -e " \r\033[0KGeekbench $VERSION test failed. Run manually to determine cause. "
2020-02-05 09:43:28 +07:00
fi
2020-01-09 09:22:43 +07:00
else
2020-02-11 11:56:08 +07:00
# if the Geekbench test succeeded, parse the test results URL
2020-01-09 09:22:43 +07:00
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
2020-08-10 04:13:44 +07:00
sleep 20
2020-02-11 11:56:08 +07:00
# parse the public results page for the single and multi core geekbench scores
2022-05-07 00:08:27 +07:00
[ [ $VERSION = = *5* ] ] && GEEKBENCH_SCORES = $( $DL_CMD $GEEKBENCH_URL | grep "div class='score'" ) ||
GEEKBENCH_SCORES = $( $DL_CMD $GEEKBENCH_URL | grep "span class='score'" )
2020-01-09 09:22:43 +07:00
GEEKBENCH_SCORES_SINGLE = $( echo $GEEKBENCH_SCORES | awk -v FS = "(>|<)" '{ print $3 }' )
2020-09-10 08:32:25 +07:00
GEEKBENCH_SCORES_MULTI = $( echo $GEEKBENCH_SCORES | awk -v FS = "(>|<)" '{ print $7 }' )
2019-10-07 10:51:09 +07:00
2020-02-11 11:56:08 +07:00
# print the Geekbench results
2020-01-09 09:22:43 +07:00
echo -en "\r\033[0K"
2020-06-21 03:01:06 +07:00
echo -e " Geekbench $VERSION Benchmark Test: "
2020-01-09 09:22:43 +07:00
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 "
2022-08-17 11:24:54 +07:00
if [ ! -z $JSON ] ; then
JSON_RESULT += '{"version":' $VERSION ',"single":' $GEEKBENCH_SCORES_SINGLE ',"multi":' $GEEKBENCH_SCORES_MULTI
JSON_RESULT += ',"url":"' $GEEKBENCH_URL '"},'
2022-08-15 11:13:11 +07:00
fi
2020-02-11 11:56:08 +07:00
# write the geekbench claim URL to a file so the user can add the results to their profile (if desired)
2020-06-21 03:01:06 +07:00
[ ! -z " $GEEKBENCH_URL_CLAIM " ] && echo -e " $GEEKBENCH_URL_CLAIM " >> geekbench_claim.url 2> /dev/null
fi
}
# if the skip geekbench flag was set, skip the system performance test, otherwise test system performance
if [ -z " $SKIP_GEEKBENCH " ] ; then
2022-08-17 11:24:54 +07:00
[ [ ! -z $JSON ] ] && JSON_RESULT += ',"geekbench":['
2020-06-21 03:01:06 +07:00
if [ [ $GEEKBENCH_4 = = *True* ] ] ; then
launch_geekbench 4
fi
if [ [ $GEEKBENCH_5 = = *True* ] ] ; then
launch_geekbench 5
2020-01-09 09:22:43 +07:00
fi
2022-08-17 11:24:54 +07:00
[ [ ! -z $JSON ] ] && JSON_RESULT = ${ JSON_RESULT : : ${# JSON_RESULT } -1 } && JSON_RESULT += ']'
2019-10-07 10:51:09 +07:00
fi
2019-10-06 08:55:21 +07:00
2020-01-09 09:22:43 +07:00
# finished all tests, clean up all YABS files and exit
2019-10-03 21:22:58 +07:00
echo -e
2019-10-08 11:01:51 +07:00
rm -rf $YABS_PATH
2020-01-11 03:48:58 +07:00
2022-08-17 11:24:54 +07:00
if [ [ ! -z $JSON ] ] ; then
2022-08-15 11:13:11 +07:00
JSON_RESULT += '}'
2022-08-17 11:24:54 +07:00
# write json results to file
if [ [ $JSON = *w* ] ] ; then
2022-08-20 06:27:32 +07:00
echo $JSON_RESULT > $JSON_FILE
2022-08-17 11:24:54 +07:00
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
2022-08-15 11:13:11 +07:00
fi
fi
2020-01-11 03:48:58 +07:00
# reset locale settings
unset LC_ALL