diff --git a/yabs.sh b/yabs.sh index 6530aaf..87c7ad1 100644 --- a/yabs.sh +++ b/yabs.sh @@ -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 \ No newline at end of file