diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..28410c1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,17 @@ +name: CI 🤖 + +on: + push: + branches: + - master + +jobs: + shellcheck: + name: Shellcheck 🐚 + runs-on: ubuntu-latest + steps: + - name: Checkout repository 📥 + uses: actions/checkout@v4 + + - name: Run ShellCheck ✅ + uses: ludeeus/action-shellcheck@2.0.0 diff --git a/README.md b/README.md index 3602436..251307b 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,7 @@ Presenting an attempt to create _yet another_ Linux server *bench*marking _scrip ![](https://user-images.githubusercontent.com/8313125/106475387-e1f6da00-6473-11eb-918c-c785ebeef8b9.jpg) Logo design by [Dian Pratama](https://github.com/dianp) -This script throws together and automates the execution of the best benchmarking tools of the biz. Included are several tests to check the performance of critical areas of a server: disk performance with [fio](https://github.com/axboe/fio), network performance with [iperf3](https://github.com/esnet/iperf), and CPU/memory performance with [Geekbench](https://www.geekbench.com/). The script is designed to not require any external dependencies to be installed nor elevated privileges to run. If there are any features that you would like to see added, feel free to submit an issue describing your feature request or fork the project and submit a PR! - -View YABS usage stats [here](https://yabs.rowe.sh). +This script automates the execution of the best benchmarking tools in the industry. Included are several tests to check the performance of critical areas of a server: disk performance with [fio](https://github.com/axboe/fio), network performance with [iperf3](https://github.com/esnet/iperf), and CPU/memory performance with [Geekbench](https://www.geekbench.com/). The script is designed to not require any external dependencies to be installed nor elevated privileges to run. If there are any features that you would like to see added, feel free to submit an issue describing your feature request or fork the project and submit a PR! ### **What's New With YABS?** * [27 Feb 2023](https://github.com/masonr/yet-another-bench-script/commit/06eaa2ab3b32355bec8278c51c4be93b3662a96d) - Newly released [Geekbench 6](https://www.geekbench.com/) is added as the default Geekbench test. @@ -17,7 +15,7 @@ View YABS usage stats [here](https://yabs.rowe.sh). ## How to Run ``` -curl -sL yabs.sh | bash +curl -sL https://yabs.sh | bash ``` or @@ -26,18 +24,18 @@ or wget -qO- yabs.sh | bash ``` -This script has been tested on the following Linux distributions: CentOS 6+, Debian 8+, Fedora 30, and Ubuntu 16.04+. - **Local fio/iperf3 Packages**: If the tested system has fio and/or iperf3 already installed, the local package will take precedence over the precompiled binary. **Experimental ARM Compatibility**: Initial ARM compatibility has been introduced, however, is not considered entirely stable due to limited testing on distinct ARM devices. Report any errors or issues. **High Bandwidth Usage Notice**: By default, this script will perform many iperf network tests, which will try to max out the network port for ~20s per location (10s in each direction). Low-bandwidth servers (such as a NAT VPS) should consider running this script with the `-r` flag (for reduced iperf locations) or the `-i` flag (to disable network tests entirely). +**Windows Users**: This script can be run on Windows systems by using [Windows Subsystem for Linux v2 (WSL 2)](https://learn.microsoft.com/en-us/windows/wsl/about). WSLv1 will not run the script and binaries correctly. + ### Flags (Skipping Tests, Reducing iperf Locations, Geekbench 4/5/6, etc.) ``` -curl -sL yabs.sh | bash -s -- -flags +curl -sL https://yabs.sh | bash -s -- -flags ``` | Flag | Description | @@ -66,7 +64,7 @@ Options can be grouped together to skip multiple tests, i.e. `-fg` to skip the d Results from running this script can be sent to your benchmark results website of choice in JSON format. Invoke the `-s` flag and pass the URL to where the results should be submitted to: ``` -curl -sL yabs.sh | bash -s -- -s "https://example.com/yabs/post" +curl -sL https://yabs.sh | bash -s -- -s "https://example.com/yabs/post" ``` JSON results can be sent to multiple endpoints by entering each site joined by a comma (e.g. "https://example.com/yabs/post,http://example.com/yabs2/post"). @@ -75,9 +73,8 @@ Sites supporting submission of YABS JSON results: | Website | Example Command | | --- | --- | -| [YABSdb](https://yabsdb.com/) | `curl -sL yabs.sh \| bash -s -- -s "https://yabsdb.com/add"` | -| [VPSBenchmarks](https://www.vpsbenchmarks.com/yabs/get_started) | `curl -sL yabs.sh \| bash -s -- -s https://www.vpsbenchmarks.com/yabs/upload` | -| [s0c Online](https://s0c.org/) | `curl -sL yabs.sh \| bash -s -- -s https://s0c.org/api/yabs -9` | +| [YABSdb](https://yabsdb.com/) | `curl -sL https://yabs.sh \| bash -s -- -s "https://yabsdb.com/add"` | +| [VPSBenchmarks](https://www.vpsbenchmarks.com/yabs/get_started) | `curl -sL https://yabs.sh \| bash -s -- -s https://www.vpsbenchmarks.com/yabs/upload` | Example JSON output: [example.json](bin/example.json). @@ -185,7 +182,7 @@ YABS completed in 12 min 49 sec ## Acknowledgements -This script was inspired by several great benchmarking scripts out there, including, but not limited to, [bench.sh](https://bench.sh/), [nench.sh](https://github.com/n-st/nench), [ServerBench](https://github.com/K4Y5/ServerBench), among others. Members of the [HostedTalk](https://hostedtalk.net), [LowEndSpirit](https://lowendspirit.com), and [LowEndTalk](https://lowendtalk.com) hosting-related communities play a pivotal role in testing, evaluating, and shaping this script as it matures. +This script was inspired by several great benchmarking scripts out there, including, but not limited to, [bench.sh](https://bench.sh/), [nench.sh](https://github.com/n-st/nench), [ServerBench](https://github.com/K4Y5/ServerBench), among others. Members of the [HostBalls](https://hostballs.com), [LowEndSpirit](https://lowendspirit.com), and [LowEndTalk](https://lowendtalk.com) hosting-related communities play a pivotal role in testing, evaluating, and shaping this script as it matures. ## License ``` diff --git a/bin/README.md b/bin/README.md index 2e1e9e4..ed1560c 100644 --- a/bin/README.md +++ b/bin/README.md @@ -4,20 +4,18 @@ This directory contains all of the binaries required to run the benchmarking tes ### Binaries -| Binary Name | Version | Compile Date | Architecture | OS | -|:-:|:-:|:-:|:-:|:-:| -| fio_x64 | 3.34 | 24-MAR-2023 | x86_64 | 64-bit | -| fio_x86 | 3.30* | 19-AUG-2022 | x86 | 32-bit | -| fio_aarch64 | 3.34 | 24-MAR-2023 | ARM | 64-bit | -| fio_arm | 3.34 | 24-MAR-2023 | ARM | 32-bit | -| iperf_x64 | 3.13 | 26-FEB-2023 | x86_64 | 64-bit | -| iperf_x86 | 3.13 | 26-FEB-2023 | x86 | 32-bit | -| iperf_aarch64 | 3.13 | 26-FEB-2023 | ARM | 64-bit | -| iperf_arm | 3.13 | 26-FEB-2023 | ARM | 32-bit | +| Binary Name | Version | Compile Date | Architecture | OS | SHA-256 Hash
(VirusTotal Scan) | +|:-:|:-:|:-:|:-:|:-:|:-:| +| fio_x64 | 3.38 | 14-DEC-2024 | x86_64 | 64-bit | [b802ea1](https://www.virustotal.com/gui/file/b802ea1460f8a0ab6a9d8a48d5d23dec8f68228293b88c2e4567424e6d2a7a47) | +| fio_x86 | 3.38 | 14-DEC-2024 | i686 | 32-bit | [8f06655](https://www.virustotal.com/gui/file/8f066550c35a8c6bbb53c80264ec0c1962128267562a785391fd3bb36ca489cb) | +| fio_aarch64 | 3.38 | 23-NOV-2024 | ARM (aarch64) | 64-bit | [ed703a8](https://www.virustotal.com/gui/file/ed703a87951992696a0870dfb3094956ebe0f5ea304918dc05a921d32aacb760) | +| fio_arm | 3.38 | 23-NOV-2024 | ARM | 32-bit | [b52a809](https://www.virustotal.com/gui/file/b52a809f748587909c429edc14e54299249aedb19b5db72a60affc0de4b5c608) | +| iperf3_x64 | 3.18 | 14-DEC-2024 | x86_64 | 64-bit | [ef787ab](https://www.virustotal.com/gui/file/ef787abbe4b09c7958ed592df52dfe3a2848cbdee5b76738c757d7c51c348053) | +| iperf3_x86 | 3.18 | 14-DEC-2024 | i686 | 32-bit | [655eb51](https://www.virustotal.com/gui/file/655eb51abc36ddaa624c1d0e98c6930e8b1e9d91c85e5a3443624355656be9b9) | +| iperf3_aarch64 | 3.18 | 14-DEC-2024 | ARM (aarch64) | 64-bit | [92e5821](https://www.virustotal.com/gui/file/92e5821cfbaa1f8faf123b4d6773dc0f6efef221b9308668a21ddabc04a1de20) | +| iperf3_arm | 3.15* | 20-OCT-2023 | ARM | 32-bit | [310e80f](https://www.virustotal.com/gui/file/310e80f442dda47fa0fe41225af85e8b91e75116dce5187f123380fd3c3c85a8) | -Note: ARM compatibility is considered experimental. Static binaries for ARM-based machines are cross-compiled within a Holy Build Box container using the [musl toolchain](https://musl.cc/). - -\* fio v3.31+ is failing to build in a 32-bit environment +Note: ARM compatibility is considered experimental. Static binaries for 32-bit and ARM-based machines are cross-compiled within a Holy Build Box container using the [musl toolchain](https://musl.cc/). ### Compile Notes @@ -30,28 +28,30 @@ Note: ARM compatibility is considered experimental. Static binaries for ARM-base docker run -t -i --rm -v `pwd`:/io phusion/holy-build-box-64:latest bash /io/compile.sh ``` -**Compiling 32-bit binaries**: +64-bit binaries will be placed in the current directory. -```sh -docker run -t -i --rm -v `pwd`:/io phusion/holy-build-box-32:latest linux32 bash /io/compile.sh -``` - -64-bit and 32-bit binaries will be placed in the current directory. - -### ARM Compile Notes +### Cross-compiling Notes Compilation of ARM-compatible binaries requires additional environment variables to identify the proper musl toolchain and architecture to target for cross-compilation. -**Compiling 64-bit binaries**: - -```sh -docker run -t -i --rm -v `pwd`:/io --env ARCH=aarch64 --env CROSS=aarch64-linux-musl --env HOST=aarch64-linux-gnu phusion/holy-build-box-64:latest bash /io/compile-arm.sh -``` - **Compiling 32-bit binaries**: ```sh -docker run -t -i --rm -v `pwd`:/io --env ARCH=arm --env CROSS=arm-linux-musleabihf --env HOST=arm-linux-gnueabihf phusion/holy-build-box-64:latest bash /io/compile-arm.sh +docker run -t -i --rm -v `pwd`:/io --env ARCH=x86 --env CROSS=i686-linux-musl --env HOST=i686-linux-musl phusion/holy-build-box-64:latest bash /io/cross-compile.sh ``` -64-bit (aarch64) and 32-bit (arm) binaries will be placed in the current directory. +**Compiling ARM 64-bit binaries**: + +```sh +docker run -t -i --rm -v `pwd`:/io --env ARCH=aarch64 --env CROSS=aarch64-linux-musl --env HOST=aarch64-linux-gnu phusion/holy-build-box-64:latest bash /io/cross-compile.sh +``` + +**Compiling ARM 32-bit binaries\***: + +```sh +docker run -t -i --rm -v `pwd`:/io --env ARCH=arm --env CROSS=arm-linux-musleabihf --env HOST=arm-linux-gnueabihf phusion/holy-build-box-64:latest bash /io/cross-compile.sh +``` + +64-bit (aarch64) and 32-bit (x86, arm) binaries will be placed in the current directory. + +\* ARM 32-bit: Last sucessful compiliation of ARM 32-bit binary for iperf3 is v3.15. All later versions fail to compile. diff --git a/bin/compile.sh b/bin/compile.sh index 868a937..9948309 100755 --- a/bin/compile.sh +++ b/bin/compile.sh @@ -6,8 +6,9 @@ source /hbb/activate set -x -# temp workaround to fix issue with phusion's repo -rm -f /etc/yum.repos.d/phusion_centos-6-scl-i386.repo +# remove obsolete CentOS repos +cd /etc/yum.repos.d/ +rm CentOS-Base.repo CentOS-SCLo-scl-rh.repo CentOS-SCLo-scl.repo CentOS-fasttrack.repo CentOS-x86_64-kernel.repo yum install -y yum-plugin-ovl # fix for docker overlay fs yum install -y xz @@ -35,7 +36,7 @@ source /hbb_exe/activate # download and compile fio cd ~ -curl -L https://github.com/axboe/fio/archive/fio-3.34.tar.gz -o "fio.tar.gz" +curl -L https://github.com/axboe/fio/archive/fio-3.38.tar.gz -o "fio.tar.gz" tar xf fio.tar.gz cd fio-fio* ./configure --disable-native @@ -44,11 +45,11 @@ make # verify no external shared library links libcheck fio # copy fio binary to mounted dir -cp fio /io/fio_$ARCH +cp fio "/io/fio_$ARCH" # download and compile iperf cd ~ -curl -L https://github.com/esnet/iperf/archive/3.13.tar.gz -o "iperf.tar.gz" +curl -L https://github.com/esnet/iperf/archive/3.18.tar.gz -o "iperf.tar.gz" tar xf iperf.tar.gz cd iperf* ./configure --disable-shared --disable-profiling @@ -57,4 +58,4 @@ make # verify no external shared library links libcheck src/iperf3 # copy iperf binary to mounted dir -cp src/iperf3 /io/iperf3_$ARCH +cp src/iperf3 "/io/iperf3_$ARCH" diff --git a/bin/compile-arm.sh b/bin/cross-compile.sh similarity index 70% rename from bin/compile-arm.sh rename to bin/cross-compile.sh index 000cce0..2b16edc 100755 --- a/bin/compile-arm.sh +++ b/bin/cross-compile.sh @@ -6,13 +6,17 @@ source /hbb/activate set -x +# remove obsolete CentOS repos +cd /etc/yum.repos.d/ +rm CentOS-Base.repo CentOS-SCLo-scl-rh.repo CentOS-SCLo-scl.repo CentOS-fasttrack.repo CentOS-x86_64-kernel.repo + yum install -y yum-plugin-ovl # fix for docker overlay fs yum install -y xz # download musl cross compilation toolchain cd ~ curl -L "https://musl.cc/${CROSS}-cross.tgz" -o "${CROSS}-cross.tgz" -tar xf ${CROSS}-cross.tgz +tar xf "${CROSS}-cross.tgz" # download, compile, and install libaio as static library cd ~ @@ -26,7 +30,7 @@ source /hbb_exe/activate # download and compile fio cd ~ -curl -L https://github.com/axboe/fio/archive/fio-3.34.tar.gz -o "fio.tar.gz" +curl -L https://github.com/axboe/fio/archive/fio-3.38.tar.gz -o "fio.tar.gz" tar xf fio.tar.gz cd fio-fio* CC=/root/${CROSS}-cross/bin/${CROSS}-gcc ./configure --disable-native --build-static @@ -35,17 +39,17 @@ make # verify no external shared library links libcheck fio # copy fio binary to mounted dir -cp fio /io/fio_$ARCH +cp fio "/io/fio_$ARCH" # download and compile iperf cd ~ -curl -L https://github.com/esnet/iperf/archive/3.13.tar.gz -o "iperf.tar.gz" +curl -L https://github.com/esnet/iperf/archive/3.18.tar.gz -o "iperf.tar.gz" tar xf iperf.tar.gz cd iperf* -CC=/root/${CROSS}-cross/bin/${CROSS}-gcc ./configure --disable-shared --disable-profiling --build x86_64-pc-linux-gnu --host ${HOST} --with-openssl=no --enable-static-bin +CC=/root/${CROSS}-cross/bin/${CROSS}-gcc ./configure --disable-shared --disable-profiling --build x86_64-pc-linux-gnu --host "${HOST}" --with-openssl=no --enable-static-bin make # verify no external shared library links libcheck src/iperf3 # copy iperf binary to mounted dir -cp src/iperf3 /io/iperf3_$ARCH +cp src/iperf3 "/io/iperf3_$ARCH" diff --git a/bin/fio/fio_aarch64 b/bin/fio/fio_aarch64 index e893f69..e086a36 100755 Binary files a/bin/fio/fio_aarch64 and b/bin/fio/fio_aarch64 differ diff --git a/bin/fio/fio_arm b/bin/fio/fio_arm index ef59dde..a396b31 100755 Binary files a/bin/fio/fio_arm and b/bin/fio/fio_arm differ diff --git a/bin/fio/fio_x64 b/bin/fio/fio_x64 index 8ad2ad0..e869abd 100755 Binary files a/bin/fio/fio_x64 and b/bin/fio/fio_x64 differ diff --git a/bin/fio/fio_x86 b/bin/fio/fio_x86 index ab59b5f..ee6aed5 100755 Binary files a/bin/fio/fio_x86 and b/bin/fio/fio_x86 differ diff --git a/bin/iperf/iperf3_aarch64 b/bin/iperf/iperf3_aarch64 index bc4aa04..406df23 100755 Binary files a/bin/iperf/iperf3_aarch64 and b/bin/iperf/iperf3_aarch64 differ diff --git a/bin/iperf/iperf3_arm b/bin/iperf/iperf3_arm index 8677df3..4c64443 100755 Binary files a/bin/iperf/iperf3_arm and b/bin/iperf/iperf3_arm differ diff --git a/bin/iperf/iperf3_x64 b/bin/iperf/iperf3_x64 index 16ddf8f..ebe44d7 100755 Binary files a/bin/iperf/iperf3_x64 and b/bin/iperf/iperf3_x64 differ diff --git a/bin/iperf/iperf3_x86 b/bin/iperf/iperf3_x86 index 415fcb5..de7caeb 100755 Binary files a/bin/iperf/iperf3_x86 and b/bin/iperf/iperf3_x86 differ diff --git a/yabs.sh b/yabs.sh index 34c4561..b18bba4 100644 --- a/yabs.sh +++ b/yabs.sh @@ -1,7 +1,7 @@ #!/bin/bash # Yet Another Bench Script by Mason Rowe -# Initial Oct 2019; Last update Apr 2023 +# Initial Oct 2019; Last update Jun 2024 # Disclaimer: This project is a work in progress. Any errors or suggestions should be # relayed to me via the GitHub project page linked below. @@ -12,7 +12,7 @@ # performance via fio. The script is designed to not require any dependencies # - either compiled or installed - nor admin privileges to run. -YABS_VERSION="v2023-04-23" +YABS_VERSION="v2024-06-09" echo -e '# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #' echo -e '# Yet-Another-Bench-Script #' @@ -96,8 +96,8 @@ command -v curl >/dev/null 2>&1 && LOCAL_CURL=true || unset LOCAL_CURL # 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" -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) +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 echo -e echo -e "Warning: Both IPv4 AND IPv6 connectivity were not detected. Check for DNS issues..." @@ -214,13 +214,15 @@ 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 [[ $ARCH = *aarch64* || $ARCH = *arm* ]]; then +# 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 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* ]]; then +if [[ $ARCH = *aarch64* || $ARCH = *arm* ]] && [[ ! -z $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="???" @@ -273,34 +275,27 @@ function ip_info() { return fi - local country=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^country/ {print $2}' | head -1) - country=${country//\"} - - local region=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^regionName/ {print $2}') - region=${region//\"} - - local region_code=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^region/ {print $2}' | head -1) - region_code=${region_code//\"} - - local city=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^city/ {print $2}') - city=${city//\"} - - local isp=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^isp/ {print $2}') - isp=${isp//\"} - - local org=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^org/ {print $2}') - org=${org//\"} - - local as=$(echo "$response" | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^as/ {print $2}') - as=${as//\"} + 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/') echo echo "$net_type Network Information:" echo "---------------------------------" - if [[ -n "$isp" && -n "$as" ]]; then + if [[ -n "$isp" ]]; then echo "ISP : $isp" + else + echo "ISP : Unknown" + fi + if [[ -n "$as" ]]; then echo "ASN : $as" + else + echo "ASN : Unknown" fi if [[ -n "$org" ]]; then echo "Host : $org" @@ -333,15 +328,15 @@ fi # create a directory in the same location that the script is being run to temporarily store YABS-related files DATE=$(date -Iseconds | sed -e "s/:/_/g") YABS_PATH=./$DATE -touch $DATE.test 2> /dev/null +touch "$DATE.test" 2> /dev/null # test if the user has write permissions in the current directory and exit if not 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 -mkdir -p $YABS_PATH +rm "$DATE.test" +mkdir -p "$YABS_PATH" # trap CTRL+C signals to exit script cleanly trap catch_abort INT @@ -351,7 +346,7 @@ trap catch_abort INT # yabs-related files. function catch_abort() { echo -e "\n** Aborting YABS. Cleaning up files...\n" - rm -rf $YABS_PATH + rm -rf "$YABS_PATH" unset LC_ALL exit 0 } @@ -437,7 +432,7 @@ function disk_test { # run a quick test to generate the fio test file to be used by the actual tests echo -en "Generating fio test file..." - $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 + $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 echo -en "\r\033[0K" # get array of block sizes to evaluate @@ -446,7 +441,7 @@ 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_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 }') @@ -484,14 +479,14 @@ function dd_test { 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)}') + 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)}') + 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) [[ "$DISK_READ_TEST" == *"GB"* ]] && VAL=$(awk -v a="$VAL" 'BEGIN { print a * 1000 }') DISK_READ_TEST_RES+=( "$DISK_READ_TEST" ) @@ -522,7 +517,7 @@ elif [ -z "$SKIP_FIO" ]; then for pathls in $(df -Th | awk '{print $7}' | tail -n +2) do if [[ "${PWD##$pathls}" != "${PWD}" ]]; then - poss+=($pathls) + poss+=("$pathls") fi done @@ -536,18 +531,18 @@ elif [ -z "$SKIP_FIO" ]; then fi done - size_b=$(df -Th | grep -w $long | grep -i zfs | awk '{print $5}' | tail -c 2 | head -c 1) + 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") + free_space=$(awk "BEGIN {print int($free_space * 1024)}") size_b='G' fi if [[ $(df -Th | grep -w $long) == *"zfs"* ]];then if [[ $size_b == 'G' ]]; then - if [[ $(echo "$free_space < $mul_spa" | bc) -ne 0 ]];then + if ((free_space < mul_spa)); then warning=1 fi else @@ -565,16 +560,16 @@ elif [ -z "$SKIP_FIO" ]; then # create temp directory to store disk write/read test files DISK_PATH=$YABS_PATH/disk - mkdir -p $DISK_PATH + mkdir -p "$DISK_PATH" if [[ -z "$PREFER_BIN" && ! -z "$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 - 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 + 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 + 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 if [ ! -f "$DISK_PATH/fio" ]; then # ensure fio binary download successfully @@ -582,7 +577,7 @@ elif [ -z "$SKIP_FIO" ]; then echo -e "Fio binary download failed. Running dd test as fallback...." DD_FALLBACK=True else - chmod +x $DISK_PATH/fio + chmod +x "$DISK_PATH/fio" FIO_CMD=$DISK_PATH/fio fi fi @@ -629,12 +624,13 @@ elif [ -z "$SKIP_FIO" ]; then 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 - [[ ! -z $JSON ]] && JSON_RESULT+=',"fio":[' + 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) DISK_COUNT=0 # print disk speed test results - echo -e "fio Disk Speed Tests (Mixed R/W 50/50):" + echo -e "fio Disk Speed Tests (Mixed R/W 50/50) (Partition $CURRENT_PARTITION):" echo -e "---------------------------------" while [ $DISK_COUNT -lt $DISK_RESULTS_NUM ] ; do @@ -684,7 +680,7 @@ function iperf_test { # 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 @@ -712,7 +708,7 @@ function iperf_test { # 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 @@ -785,19 +781,19 @@ if [ -z "$SKIP_IPERF" ]; then else # create a temp directory to house the required iperf binary and library IPERF_PATH=$YABS_PATH/iperf - mkdir -p $IPERF_PATH + mkdir -p "$IPERF_PATH" # download iperf3 binary 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 + 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 + 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 if [ ! -f "$IPERF_PATH/iperf3" ]; then # ensure iperf3 binary downloaded successfully IPERF_DL_FAIL=True else - chmod +x $IPERF_PATH/iperf3 + chmod +x "$IPERF_PATH/iperf3" IPERF_CMD=$IPERF_PATH/iperf3 fi fi @@ -811,13 +807,14 @@ if [ -z "$SKIP_IPERF" ]; then # 5. network modes supported by the iperf server (IPv4 = IPv4-only, IPv4|IPv6 = IPv4 + IPv6, etc.) IPERF_LOCS=( \ "lon.speedtest.clouvider.net" "5200-5209" "Clouvider" "London, UK (10G)" "IPv4|IPv6" \ - "ping.online.net" "5200-5209" "Scaleway" "Paris, FR (10G)" "IPv4" \ - "ping6.online.net" "5200-5209" "Scaleway" "Paris, FR (10G)" "IPv6" \ - "speedtest.novoserve.com" "5201-5206" "NovoServe" "North Holland, NL (40G)" "IPv4|IPv6" \ - "speedtest.uztelecom.uz" "5200-5207" "Uztelecom" "Tashkent, UZ (10G)" "IPv4|IPv6" \ - "nyc.speedtest.clouvider.net" "5200-5209" "Clouvider" "NYC, NY, US (10G)" "IPv4|IPv6" \ - "dal.speedtest.clouvider.net" "5200-5209" "Clouvider" "Dallas, TX, US (10G)" "IPv4|IPv6" \ + "iperf-ams-nl.eranium.net" "5201-5210" "Eranium" "Amsterdam, NL (100G)" "IPv4|IPv6" \ + #"speedtest.extra.telia.fi" "5201-5208" "Telia" "Helsinki, FI (10G)" "IPv4" \ + # AFR placeholder + "speedtest.uztelecom.uz" "5200-5209" "Uztelecom" "Tashkent, UZ (10G)" "IPv4|IPv6" \ + "speedtest.sin1.sg.leaseweb.net" "5201-5210" "Leaseweb" "Singapore, SG (10G)" "IPv4|IPv6" \ "la.speedtest.clouvider.net" "5200-5209" "Clouvider" "Los Angeles, CA, US (10G)" "IPv4|IPv6" \ + "speedtest.nyc1.us.leaseweb.net" "5201-5210" "Leaseweb" "NYC, NY, US (10G)" "IPv4|IPv6" \ + "speedtest.sao1.edgoo.net" "9204-9240" "Edgoo" "Sao Paulo, BR (1G)" "IPv4|IPv6" ) # if the "REDUCE_NET" flag is activated, then do a shorter iperf test with only three locations @@ -825,9 +822,8 @@ if [ -z "$SKIP_IPERF" ]; then if [ ! -z "$REDUCE_NET" ]; then IPERF_LOCS=( \ "lon.speedtest.clouvider.net" "5200-5209" "Clouvider" "London, UK (10G)" "IPv4|IPv6" \ - "ping.online.net" "5200-5209" "Scaleway" "Paris, FR (10G)" "IPv4" \ - "ping6.online.net" "5200-5209" "Scaleway" "Paris, FR (10G)" "IPv6" \ - "nyc.speedtest.clouvider.net" "5200-5209" "Clouvider" "NYC, NY, US (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 @@ -856,7 +852,7 @@ function launch_geekbench { # create a temp directory to house all geekbench files GEEKBENCH_PATH=$YABS_PATH/geekbench_$VERSION - mkdir -p $GEEKBENCH_PATH + mkdir -p "$GEEKBENCH_PATH" GB_URL="" GB_CMD="" @@ -883,8 +879,8 @@ function launch_geekbench { || GB_URL="https://cdn.geekbench.com/Geekbench-5.5.1-Linux.tar.gz" GB_CMD="geekbench5" else # Geekbench v6 - [[ $ARCH = *aarch64* || $ARCH = *arm* ]] && GB_URL="https://cdn.geekbench.com/Geekbench-6.0.3-LinuxARMPreview.tar.gz" \ - || GB_URL="https://cdn.geekbench.com/Geekbench-6.0.3-Linux.tar.gz" + [[ $ARCH = *aarch64* || $ARCH = *arm* ]] && GB_URL="https://cdn.geekbench.com/Geekbench-6.3.0-LinuxARMPreview.tar.gz" \ + || GB_URL="https://cdn.geekbench.com/Geekbench-6.3.0-Linux.tar.gz" GB_CMD="geekbench6" fi GB_RUN="True" @@ -894,17 +890,26 @@ function launch_geekbench { if [[ $GB_RUN == *True* ]]; then # run GB test echo -en "\nRunning GB$VERSION benchmark test... *cue elevator music*" - # download the desired Geekbench tarball and extract to geekbench temp directory - $DL_CMD $GB_URL | tar xz --strip-components=1 -C $GEEKBENCH_PATH &>/dev/null + # check for local geekbench installed + if command -v "$GB_CMD" &>/dev/null; then + GEEKBENCH_PATH=$(dirname "$(command -v "$GB_CMD")") + else + # download the desired Geekbench tarball and extract to geekbench temp directory + $DL_CMD $GB_URL | tar xz --strip-components=1 -C "$GEEKBENCH_PATH" &>/dev/null + 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") + GEEKBENCH_TEST=$("$GEEKBENCH_PATH/$GB_CMD" --upload 2>/dev/null | grep "https://browser") # ensure the test ran successfully if [ -z "$GEEKBENCH_TEST" ]; then + # detect if CentOS 7 and print a more helpful error message + if grep -q "CentOS Linux 7" /etc/os-release; then + echo -e "\r\033[0K CentOS 7 and Geekbench have known issues relating to glibc (see issue #71 for details)" + fi if [[ -z "$IPV4_CHECK" ]]; then # Geekbench test failed to download because host lacks IPv4 (cdn.geekbench.com = IPv4 only) echo -e "\r\033[0KGeekbench releases can only be downloaded over IPv4. FTP the Geekbench files and run manually." @@ -970,7 +975,7 @@ fi # finished all tests, clean up all YABS files and exit echo -e -rm -rf $YABS_PATH +rm -rf "$YABS_PATH" YABS_END_TIME=$(date +%s) @@ -1001,7 +1006,7 @@ if [[ ! -z $JSON ]]; then # write json results to file if [[ $JSON = *w* ]]; then - echo $JSON_RESULT > $JSON_FILE + echo $JSON_RESULT > "$JSON_FILE" fi # send json results