天小就的生活碎片

人生如过眼云烟 记录点点滴滴

VPS必备测试脚本

前言

在我刚刚接触VPS的那一段时间里面,对于自己的机子到底是一个什么样的情况并不太了解,就去网上搜索了一大堆方法用来测试自己的VPS到底情况如何。当初可谓是煞费苦心,安装了一系列东西结果不尽人意。直到后来才发现,最好用的方法其实是使用测试脚本。.


脚本一:Bench.sh

wget -qO- bench.sh | bash
#或者
curl -Lso- bench.sh | bash
#或者
wget -qO- 86.re/bench.sh | bash
#或者
curl -so- 86.re/bench.sh | bash
  • 显示当前测试的各种系统信息;

  • 取自世界多处的知名数据中心的测试点,下载测试比较全面;

  • 支持 IPv6 下载测速;

  • IO 测试三次,并显示平均值。

#!/usr/bin/env bash
#
# Description: A Bench Script by Teddysun
#
# Copyright (C) 2015 - 2022 Teddysun <i@teddysun.com>
# Thanks: LookBack <admin@dwhd.org>
# URL: https://teddysun.com/444.html
# https://github.com/teddysun/across/blob/master/bench.sh
#
trap _exit INT QUIT TERM

_red() {
    printf '\033[0;31;31m%b\033[0m' "$1"
}

_green() {
    printf '\033[0;31;32m%b\033[0m' "$1"
}

_yellow() {
    printf '\033[0;31;33m%b\033[0m' "$1"
}

_blue() {
    printf '\033[0;31;36m%b\033[0m' "$1"
}

_exists() {
    local cmd="$1"
    if eval type type > /dev/null 2>&1; then
        eval type "$cmd" > /dev/null 2>&1
    elif command > /dev/null 2>&1; then
        command -v "$cmd" > /dev/null 2>&1
    else
        which "$cmd" > /dev/null 2>&1
    fi
    local rt=$?
    return ${rt}
}

_exit() {
    _red "\nThe script has been terminated.\n"
    # clean up
    rm -fr speedtest.tgz speedtest-cli benchtest_*
    exit 1
}

get_opsy() {
    [ -f /etc/redhat-release ] && awk '{print $0}' /etc/redhat-release && return
    [ -f /etc/os-release ] && awk -F'[= "]' '/PRETTY_NAME/{print $3,$4,$5}' /etc/os-release && return
    [ -f /etc/lsb-release ] && awk -F'[="]+' '/DESCRIPTION/{print $2}' /etc/lsb-release && return
}

next() {
    printf "%-70s\n" "-" | sed 's/\s/-/g'
}

speed_test() {
    local nodeName="$2"
    [ -z "$1" ] && ./speedtest-cli/speedtest --progress=no --accept-license --accept-gdpr > ./speedtest-cli/speedtest.log 2>&1 || \
    ./speedtest-cli/speedtest --progress=no --server-id=$1 --accept-license --accept-gdpr > ./speedtest-cli/speedtest.log 2>&1
    if [ $? -eq 0 ]; then
        local dl_speed=$(awk '/Download/{print $3" "$4}' ./speedtest-cli/speedtest.log)
        local up_speed=$(awk '/Upload/{print $3" "$4}' ./speedtest-cli/speedtest.log)
        local latency=$(awk '/Latency/{print $2" "$3}' ./speedtest-cli/speedtest.log)
        if [[ -n "${dl_speed}" && -n "${up_speed}" && -n "${latency}" ]]; then
            printf "\033[0;33m%-18s\033[0;32m%-18s\033[0;31m%-20s\033[0;36m%-12s\033[0m\n" " ${nodeName}" "${up_speed}" "${dl_speed}" "${latency}"
        fi
    fi
}

speed() {
    speed_test '' 'Speedtest.net'
    speed_test '21541' 'Los Angeles, US'
    speed_test '43860' 'Dallas, US'
    speed_test '40879' 'Montreal, CA'
    speed_test '24215' 'Paris, FR'
    speed_test '28922' 'Amsterdam, NL'
    speed_test '24447' 'Shanghai, CN'
    speed_test '26352' 'Nanjing, CN'
    speed_test '27594' 'Guangzhou, CN'
    speed_test '32155' 'Hongkong, CN'
    speed_test '6527'  'Seoul, KR'
    speed_test '7311'  'Singapore, SG'
    speed_test '21569' 'Tokyo, JP'
}

io_test() {
    (LANG=C dd if=/dev/zero of=benchtest_$$ bs=512k count=$1 conv=fdatasync && rm -f benchtest_$$ ) 2>&1 | awk -F, '{io=$NF} END { print io}' | sed 's/^[ \t]*//;s/[ \t]*$//'
}

calc_size() {
    local raw=$1
    local total_size=0
    local num=1
    local unit="KB"
    if ! [[ ${raw} =~ ^[0-9]+$ ]] ; then
        echo ""
        return
    fi
    if [ "${raw}" -ge 1073741824 ]; then
        num=1073741824
        unit="TB"
    elif [ "${raw}" -ge 1048576 ]; then
        num=1048576
        unit="GB"
    elif [ "${raw}" -ge 1024 ]; then
        num=1024
        unit="MB"
    elif [ "${raw}" -eq 0 ]; then
        echo "${total_size}"
        return
    fi
    total_size=$( awk 'BEGIN{printf "%.1f", '$raw' / '$num'}' )
    echo "${total_size} ${unit}"
}

check_virt(){
    _exists "dmesg" && virtualx="$(dmesg 2>/dev/null)"
    if _exists "dmidecode"; then
        sys_manu="$(dmidecode -s system-manufacturer 2>/dev/null)"
        sys_product="$(dmidecode -s system-product-name 2>/dev/null)"
        sys_ver="$(dmidecode -s system-version 2>/dev/null)"
    else
        sys_manu=""
        sys_product=""
        sys_ver=""
    fi
    if   grep -qa docker /proc/1/cgroup; then
        virt="Docker"
    elif grep -qa lxc /proc/1/cgroup; then
        virt="LXC"
    elif grep -qa container=lxc /proc/1/environ; then
        virt="LXC"
    elif [[ -f /proc/user_beancounters ]]; then
        virt="OpenVZ"
    elif [[ "${virtualx}" == *kvm-clock* ]]; then
        virt="KVM"
    elif [[ "${sys_product}" == *KVM* ]]; then
        virt="KVM"
    elif [[ "${cname}" == *KVM* ]]; then
        virt="KVM"
    elif [[ "${cname}" == *QEMU* ]]; then
        virt="KVM"
    elif [[ "${virtualx}" == *"VMware Virtual Platform"* ]]; then
        virt="VMware"
    elif [[ "${sys_product}" == *"VMware Virtual Platform"* ]]; then
        virt="VMware"
    elif [[ "${virtualx}" == *"Parallels Software International"* ]]; then
        virt="Parallels"
    elif [[ "${virtualx}" == *VirtualBox* ]]; then
        virt="VirtualBox"
    elif [[ -e /proc/xen ]]; then
        if grep -q "control_d" "/proc/xen/capabilities" 2>/dev/null; then
            virt="Xen-Dom0"
        else
            virt="Xen-DomU"
        fi
    elif [ -f "/sys/hypervisor/type" ] && grep -q "xen" "/sys/hypervisor/type"; then
        virt="Xen"
    elif [[ "${sys_manu}" == *"Microsoft Corporation"* ]]; then
        if [[ "${sys_product}" == *"Virtual Machine"* ]]; then
            if [[ "${sys_ver}" == *"7.0"* || "${sys_ver}" == *"Hyper-V" ]]; then
                virt="Hyper-V"
            else
                virt="Microsoft Virtual Machine"
            fi
        fi
    else
        virt="Dedicated"
    fi
}

ipv4_info() {
    local org="$(wget -q -T10 -O- ipinfo.io/org)"
    local city="$(wget -q -T10 -O- ipinfo.io/city)"
    local country="$(wget -q -T10 -O- ipinfo.io/country)"
    local region="$(wget -q -T10 -O- ipinfo.io/region)"
    if [[ -n "$org" ]]; then
        echo " Organization       : $(_blue "$org")"
    fi
    if [[ -n "$city" && -n "country" ]]; then
        echo " Location           : $(_blue "$city / $country")"
    fi
    if [[ -n "$region" ]]; then
        echo " Region             : $(_yellow "$region")"
    fi
    if [[ -z "$org" ]]; then
        echo " Region             : $(_red "No ISP detected")"
    fi
}

install_speedtest() {
    if [ ! -e "./speedtest-cli/speedtest" ]; then
        sys_bit=""
        local sysarch="$(uname -m)"
        if [ "${sysarch}" = "unknown" ] || [ "${sysarch}" = "" ]; then
            local sysarch="$(arch)"
        fi
        if [ "${sysarch}" = "x86_64" ]; then
            sys_bit="x86_64"
        fi
        if [ "${sysarch}" = "i386" ] || [ "${sysarch}" = "i686" ]; then
            sys_bit="i386"
        fi
        if [ "${sysarch}" = "armv8" ] || [ "${sysarch}" = "armv8l" ] || [ "${sysarch}" = "aarch64" ] || [ "${sysarch}" = "arm64" ]; then
            sys_bit="aarch64"
        fi
        if [ "${sysarch}" = "armv7" ] || [ "${sysarch}" = "armv7l" ]; then
            sys_bit="armhf"
        fi
        if [ "${sysarch}" = "armv6" ]; then
            sys_bit="armel"
        fi
        [ -z "${sys_bit}" ] && _red "Error: Unsupported system architecture (${sysarch}).\n" && exit 1
        url1="https://install.speedtest.net/app/cli/ookla-speedtest-1.1.1-linux-${sys_bit}.tgz"
        url2="https://dl.lamp.sh/files/ookla-speedtest-1.1.1-linux-${sys_bit}.tgz"
        wget --no-check-certificate -q -T10 -O speedtest.tgz ${url1}
        if [ $? -ne 0 ]; then
            wget --no-check-certificate -q -T10 -O speedtest.tgz ${url2}
            [ $? -ne 0 ] && _red "Error: Failed to download speedtest-cli.\n" && exit 1
        fi
        mkdir -p speedtest-cli && tar zxf speedtest.tgz -C ./speedtest-cli && chmod +x ./speedtest-cli/speedtest
        rm -f speedtest.tgz
    fi
    printf "%-18s%-18s%-20s%-12s\n" " Node Name" "Upload Speed" "Download Speed" "Latency"
}

print_intro() {
    echo "-------------------- A Bench.sh Script By Teddysun -------------------"
    echo " Version            : $(_green v2022-06-01)"
    echo " Usage              : $(_red "wget -qO- bench.sh | bash")"
}

# Get System information
get_system_info() {
    cname=$( awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//' )
    cores=$( awk -F: '/processor/ {core++} END {print core}' /proc/cpuinfo )
    freq=$( awk -F'[ :]' '/cpu MHz/ {print $4;exit}' /proc/cpuinfo )
    ccache=$( awk -F: '/cache size/ {cache=$2} END {print cache}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//' )
    cpu_aes=$( grep -i 'aes' /proc/cpuinfo )
    cpu_virt=$( grep -Ei 'vmx|svm' /proc/cpuinfo )
    tram=$(; free | awk '/Mem/ {print $2}' )
    tram=$( calc_size $tram )
    uram=$(; free | awk '/Mem/ {print $3}' )
    uram=$( calc_size $uram )
    swap=$(; free | awk '/Swap/ {print $2}' )
    swap=$( calc_size $swap )
    uswap=$(; free | awk '/Swap/ {print $3}' )
    uswap=$( calc_size $uswap )
    up=$( awk '{a=$1/86400;b=($1%86400)/3600;c=($1%3600)/60} {printf("%d days, %d hour %d min\n",a,b,c)}' /proc/uptime )
    if _exists "w"; then
        load=$(; w | head -1 | awk -F'load average:' '{print $2}' | sed 's/^[ \t]*//;s/[ \t]*$//' )
    elif _exists "uptime"; then
        load=$(; uptime | head -1 | awk -F'load average:' '{print $2}' | sed 's/^[ \t]*//;s/[ \t]*$//' )
    fi
    opsy=$( get_opsy )
    arch=$( uname -m )
    if _exists "getconf"; then
        lbit=$( getconf LONG_BIT )
    else
        echo ${arch} | grep -q "64" && lbit="64" || lbit="32"
    fi
    kern=$( uname -r )
    disk_total_size=$(; 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 }' )
    disk_total_size=$( calc_size $disk_total_size )
    disk_used_size=$(; 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 $3 }' )
    disk_used_size=$( calc_size $disk_used_size )
    tcpctrl=$( sysctl net.ipv4.tcp_congestion_control | awk -F ' ' '{print $3}' )
}
# Print System information
print_system_info() {
    if [ -n "$cname" ]; then
        echo " CPU Model          : $(_blue "$cname")"
    else
        echo " CPU Model          : $(_blue "CPU model not detected")"
    fi
    if [ -n "$freq" ]; then
        echo " CPU Cores          : $(_blue "$cores @ $freq MHz")"
    else
        echo " CPU Cores          : $(_blue "$cores")"
    fi
    if [ -n "$ccache" ]; then
        echo " CPU Cache          : $(_blue "$ccache")"
    fi
    if [ -n "$cpu_aes" ]; then
        echo " AES-NI             : $(_green "Enabled")"
    else
        echo " AES-NI             : $(_red "Disabled")"
    fi
    if [ -n "$cpu_virt" ]; then
        echo " VM-x/AMD-V         : $(_green "Enabled")"
    else
        echo " VM-x/AMD-V         : $(_red "Disabled")"
    fi
    echo " Total Disk         : $(_yellow "$disk_total_size") $(_blue "($disk_used_size Used)")"
    echo " Total Mem          : $(_yellow "$tram") $(_blue "($uram Used)")"
    if [ "$swap" != "0" ]; then
        echo " Total Swap         : $(_blue "$swap ($uswap Used)")"
    fi
    echo " System uptime      : $(_blue "$up")"
    echo " Load average       : $(_blue "$load")"
    echo " OS                 : $(_blue "$opsy")"
    echo " Arch               : $(_blue "$arch ($lbit Bit)")"
    echo " Kernel             : $(_blue "$kern")"
    echo " TCP CC             : $(_yellow "$tcpctrl")"
    echo " Virtualization     : $(_blue "$virt")"
}

print_io_test() {
    freespace=$( df -m . | awk 'NR==2 {print $4}' )
    if [ -z "${freespace}" ]; then
        freespace=$( df -m . | awk 'NR==3 {print $3}' )
    fi
    if [ ${freespace} -gt 1024 ]; then
        writemb=2048
        io1=$( io_test ${writemb} )
        echo " I/O Speed(1st run) : $(_yellow "$io1")"
        io2=$( io_test ${writemb} )
        echo " I/O Speed(2nd run) : $(_yellow "$io2")"
        io3=$( io_test ${writemb} )
        echo " I/O Speed(3rd run) : $(_yellow "$io3")"
        ioraw1=$( echo $io1 | awk 'NR==1 {print $1}' )
        [ "`echo $io1 | awk 'NR==1 {print $2}'`" == "GB/s" ] && ioraw1=$( awk 'BEGIN{print '$ioraw1' * 1024}' )
        ioraw2=$( echo $io2 | awk 'NR==1 {print $1}' )
        [ "`echo $io2 | awk 'NR==1 {print $2}'`" == "GB/s" ] && ioraw2=$( awk 'BEGIN{print '$ioraw2' * 1024}' )
        ioraw3=$( echo $io3 | awk 'NR==1 {print $1}' )
        [ "`echo $io3 | awk 'NR==1 {print $2}'`" == "GB/s" ] && ioraw3=$( awk 'BEGIN{print '$ioraw3' * 1024}' )
        ioall=$( awk 'BEGIN{print '$ioraw1' + '$ioraw2' + '$ioraw3'}' )
        ioavg=$( awk 'BEGIN{printf "%.1f", '$ioall' / 3}' )
        echo " I/O Speed(average) : $(_yellow "$ioavg MB/s")"
    else
        echo " $(_red "Not enough space for I/O Speed test!")"
    fi
}

print_end_time() {
    end_time=$(date +%s)
    time=$(( ${end_time} - ${start_time} ))
    if [ ${time} -gt 60 ]; then
        min=$(expr $time / 60)
        sec=$(expr $time % 60)
        echo " Finished in        : ${min} min ${sec} sec"
    else
        echo " Finished in        : ${time} sec"
    fi
    date_time=$(date '+%Y-%m-%d %H:%M:%S %Z')
    echo " Timestamp          : $date_time"
}

! _exists "wget" && _red "Error: wget command not found.\n" && exit 1
! _exists "free" && _red "Error: free command not found.\n" && exit 1
start_time=$(date +%s)
get_system_info
check_virt
clear
print_intro
next
print_system_info
ipv4_info
next
print_io_test
next
install_speedtest && speed && rm -fr speedtest-cli
next
print_end_time
next

脚本二:SuperBench.sh

wget -qO- --no-check-certificate https://raw.githubusercontent.com/oooldking/script/master/superbench.sh | bash
#或者
curl -Lso- -no-check-certificate https://raw.githubusercontent.com/oooldking/script/master/superb

老鬼大佬的SuperBench测试脚本

特点

  • 改进了显示的模式,基本参数添加了颜色,方面区分与查找。

  • I/O测试,更改了原来默认的测试的内容,采用小文件,中等文件,大文件,分别测试IO性能,然后取平均值。

  • 速度测试替换成了 Superspeed 里面的测试,第一个默认节点是,Speedtest 默认,其他分别测试到中国电信,联通,移动,各三个不同地区的速度。

#!/usr/bin/env bash
#
# Description: Auto system info & I/O test & network to China script
#
# Copyright (C) 2017 - 2020 Oldking <oooldking@gmail.com>
#
# Thanks: Bench.sh <i@teddysun.com>
#
# URL: https://www.oldking.net/350.html
#

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
SKYBLUE='\033[0;36m'
PLAIN='\033[0m'

about() {
    echo ""
    echo " ========================================================= "
    echo " \                 Superbench.sh  Script                 / "
    echo " \       Basic system info, I/O test and speedtest       / "
    echo " \                   v1.1.7 (7 Apr 2020)                 / "
    echo " \                   Created by Oldking                  / "
    echo " ========================================================= "
    echo ""
    echo " Intro: https://www.oldking.net/350.html"
    echo " Copyright (C) 2020 Oldking oooldking@gmail.com"
    echo ""
}

cancel() {
    echo ""
    next;
    echo " Abort ..."
    echo " Cleanup ..."
    cleanup;
    echo " Done"
    exit
}

trap cancel SIGINT

benchinit() {
    if [ -f /etc/redhat-release ]; then
        release="centos"
    elif cat /etc/issue | grep -Eqi "debian"; then
        release="debian"
    elif cat /etc/issue | grep -Eqi "ubuntu"; then
        release="ubuntu"
    elif cat /etc/issue | grep -Eqi "centos|red hat|redhat"; then
        release="centos"
    elif cat /proc/version | grep -Eqi "debian"; then
        release="debian"
    elif cat /proc/version | grep -Eqi "ubuntu"; then
        release="ubuntu"
    elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then
        release="centos"
    fi

    [[ $EUID -ne 0 ]] && echo -e "${RED}Error:${PLAIN} This script must be run as root!" && exit 1

    if  [ ! -e '/usr/bin/python' ]; then
            echo " Installing Python ..."
                if [ "${release}" == "centos" ]; then
                        yum update > /dev/null 2>&1
                        yum -y install python > /dev/null 2>&1
                    else
                        apt-get update > /dev/null 2>&1
                        apt-get -y install python > /dev/null 2>&1
                    fi
            
    fi

    if  [ ! -e '/usr/bin/curl' ]; then
            echo " Installing Curl ..."
                if [ "${release}" == "centos" ]; then
                    yum update > /dev/null 2>&1
                    yum -y install curl > /dev/null 2>&1
                else
                    apt-get update > /dev/null 2>&1
                    apt-get -y install curl > /dev/null 2>&1
                fi
    fi

    if  [ ! -e '/usr/bin/wget' ]; then
            echo " Installing Wget ..."
                if [ "${release}" == "centos" ]; then
                    yum update > /dev/null 2>&1
                    yum -y install wget > /dev/null 2>&1
                else
                    apt-get update > /dev/null 2>&1
                    apt-get -y install wget > /dev/null 2>&1
                fi
    fi

    if  [ ! -e './speedtest-cli/speedtest' ]; then
        echo " Installing Speedtest-cli ..."
        wget --no-check-certificate -qO speedtest.tgz https://cdn.jsdelivr.net/gh/oooldking/script@1.1.7/speedtest_cli/ookla-speedtest-1.0.0-$(uname -m)-linux.tgz > /dev/null 2>&1
    fi
    mkdir -p speedtest-cli && tar zxvf speedtest.tgz -C ./speedtest-cli/ > /dev/null 2>&1 && chmod a+rx ./speedtest-cli/speedtest

    if  [ ! -e 'tools.py' ]; then
        echo " Installing tools.py ..."
        wget --no-check-certificate https://cdn.jsdelivr.net/gh/oooldking/script@1.1.7/tools.py > /dev/null 2>&1
    fi
    chmod a+rx tools.py

    if  [ ! -e 'fast_com.py' ]; then
        echo " Installing Fast.com-cli ..."
        wget --no-check-certificate https://cdn.jsdelivr.net/gh/sanderjo/fast.com@master/fast_com.py > /dev/null 2>&1
        wget --no-check-certificate https://cdn.jsdelivr.net/gh/sanderjo/fast.com@master/fast_com_example_usage.py > /dev/null 2>&1
    fi
    chmod a+rx fast_com.py
    chmod a+rx fast_com_example_usage.py

    sleep 5

    start=$(date +%s) 
}

get_opsy() {
    [ -f /etc/redhat-release ] && awk '{print ($1,$3~/^[0-9]/?$3:$4)}' /etc/redhat-release && return
    [ -f /etc/os-release ] && awk -F'[= "]' '/PRETTY_NAME/{print $3,$4,$5}' /etc/os-release && return
    [ -f /etc/lsb-release ] && awk -F'[="]+' '/DESCRIPTION/{print $2}' /etc/lsb-release && return
}

next() {
    printf "%-70s\n" "-" | sed 's/\s/-/g' | tee -a $log
}

speed_test(){
    if [[ $1 == '' ]]; then
        speedtest-cli/speedtest -p no --accept-license > $speedLog 2>&1
        is_upload=$(cat $speedLog | grep 'Upload')
        result_speed=$(cat $speedLog | awk -F ' ' '/Result/{print $3}')
        if [[ ${is_upload} ]]; then
            local REDownload=$(cat $speedLog | awk -F ' ' '/Download/{print $3}')
            local reupload=$(cat $speedLog | awk -F ' ' '/Upload/{print $3}')
            local relatency=$(cat $speedLog | awk -F ' ' '/Latency/{print $2}')

            temp=$(echo "$relatency" | awk -F '.' '{print $1}')
            if [[ ${temp} -gt 50 ]]; then
                relatency="(*)"${relatency}
            fi
            local nodeName=$2

            temp=$(echo "${REDownload}" | awk -F ' ' '{print $1}')
            if [[ $(awk -v num1=${temp} -v num2=0 'BEGIN{print(num1>num2)?"1":"0"}') -eq 1 ]]; then
                printf "${YELLOW}%-18s${GREEN}%-18s${RED}%-20s${SKYBLUE}%-12s${PLAIN}\n" " ${nodeName}" "${reupload} Mbit/s" "${REDownload} Mbit/s" "${relatency} ms" | tee -a $log
            fi
        else
            local cerror="ERROR"
        fi
    else
        speedtest-cli/speedtest -p no -s $1 --accept-license > $speedLog 2>&1
        is_upload=$(cat $speedLog | grep 'Upload')
        if [[ ${is_upload} ]]; then
            local REDownload=$(cat $speedLog | awk -F ' ' '/Download/{print $3}')
            local reupload=$(cat $speedLog | awk -F ' ' '/Upload/{print $3}')
            local relatency=$(cat $speedLog | awk -F ' ' '/Latency/{print $2}')
            local nodeName=$2

            temp=$(echo "${REDownload}" | awk -F ' ' '{print $1}')
            if [[ $(awk -v num1=${temp} -v num2=0 'BEGIN{print(num1>num2)?"1":"0"}') -eq 1 ]]; then
                printf "${YELLOW}%-18s${GREEN}%-18s${RED}%-20s${SKYBLUE}%-12s${PLAIN}\n" " ${nodeName}" "${reupload} Mbit/s" "${REDownload} Mbit/s" "${relatency} ms" | tee -a $log
            fi
        else
            local cerror="ERROR"
        fi
    fi
}

print_speedtest() {
    printf "%-18s%-18s%-20s%-12s\n" " Node Name" "Upload Speed" "Download Speed" "Latency" | tee -a $log
    speed_test '' 'Speedtest.net'
    speed_fast_com
    speed_test '27377' 'Beijing 5G   CT'
    speed_test '26352' 'Nanjing 5G   CT'
    speed_test '17145' 'Hefei 5G     CT'
    speed_test '27594' 'Guangzhou 5G CT'
    speed_test '27154' 'TianJin 5G   CU'
    speed_test '24447' 'Shanghai 5G  CU'
    speed_test '26678' 'Guangzhou 5G CU'
    speed_test '17184' 'Tianjin 5G   CM'
    speed_test '26850' 'Wuxi 5G      CM'
    speed_test '27249' 'Nanjing 5G   CM'
    speed_test '26404' 'Hefei 5G     CM'
    speed_test '28491' 'Changsha 5G  CM'

    rm -rf speedtest*
}

print_speedtest_fast() {
    printf "%-18s%-18s%-20s%-12s\n" " Node Name" "Upload Speed" "Download Speed" "Latency" | tee -a $log
    speed_test '' 'Speedtest.net'
    speed_fast_com
    speed_test '27377' 'Beijing 5G   CT'
    speed_test '24447' 'ShangHai 5G  CU'
    speed_test '27249' 'Nanjing 5G   CM'
     
    rm -rf speedtest*
}

speed_fast_com() {
    temp=$(python fast_com_example_usage.py 2>&1)
    is_down=$(echo "$temp" | grep 'Result') 
        if [[ ${is_down} ]]; then
            temp1=$(echo "$temp" | awk -F ':' '/Result/{print $2}')
            temp2=$(echo "$temp1" | awk -F ' ' '/Mbps/{print $1}')
            local REDownload="$temp2 Mbit/s"
            local reupload="0.00 Mbit/s"
            local relatency="-"
            local nodeName="Fast.com"

            printf "${YELLOW}%-18s${GREEN}%-18s${RED}%-20s${SKYBLUE}%-12s${PLAIN}\n" " ${nodeName}" "${reupload}" "${REDownload}" "${relatency}" | tee -a $log
        else
            local cerror="ERROR"
        fi
    rm -rf fast_com_example_usage.py
    rm -rf fast_com.py

}

io_test() {
    (LANG=C dd if=/dev/zero of=test_file_$$ bs=512K count=$1 conv=fdatasync && rm -f test_file_$$ ) 2>&1 | awk -F, '{io=$NF} END { print io}' | sed 's/^[ \t]*//;s/[ \t]*$//'
}

calc_disk() {
    local total_size=0
    local array=$@
    for size in ${array[@]}
    do
        [ "${size}" == "0" ] && size_t=0 || size_t=`echo ${size:0:${#size}-1}`
        [ "`echo ${size:(-1)}`" == "K" ] && size=0
        [ "`echo ${size:(-1)}`" == "M" ] && size=$( awk 'BEGIN{printf "%.1f", '$size_t' / 1024}' )
        [ "`echo ${size:(-1)}`" == "T" ] && size=$( awk 'BEGIN{printf "%.1f", '$size_t' * 1024}' )
        [ "`echo ${size:(-1)}`" == "G" ] && size=${size_t}
        total_size=$( awk 'BEGIN{printf "%.1f", '$total_size' + '$size'}' )
    done
    echo ${total_size}
}

power_time() {

    result=$(smartctl -a $(result=$(cat /proc/mounts) && echo $(echo "$result" | awk '/data=ordered/{print $1}') | awk '{print $1}') 2>&1) && power_time=$(echo "$result" | awk '/Power_On/{print $10}') && echo "$power_time"
}

install_smart() {
    if  [ ! -e '/usr/sbin/smartctl' ]; then
        echo "Installing Smartctl ..."
        if [ "${release}" == "centos" ]; then
            yum update > /dev/null 2>&1
            yum -y install smartmontools > /dev/null 2>&1
        else
            apt-get update > /dev/null 2>&1
            apt-get -y install smartmontools > /dev/null 2>&1
        fi      
    fi
}

ip_info4(){
    ip_date=$(curl -4 -s http://api.ip.la/en?json)
    echo $ip_date > ip_json.json
    isp=$(python tools.py geoip isp)
    as_tmp=$(python tools.py geoip as)
    asn=$(echo $as_tmp | awk -F ' ' '{print $1}')
    org=$(python tools.py geoip org)
    if [ -z "ip_date" ]; then
        echo $ip_date
        echo "hala"
        country=$(python tools.py ipip country_name)
        city=$(python tools.py ipip city)
        countryCode=$(python tools.py ipip country_code)
        region=$(python tools.py ipip province)
    else
        country=$(python tools.py geoip country)
        city=$(python tools.py geoip city)
        countryCode=$(python tools.py geoip countryCode)
        region=$(python tools.py geoip regionName)    
    fi
    if [ -z "$city" ]; then
        city=${region}
    fi

    echo -e " ASN & ISP            : ${SKYBLUE}$asn, $isp${PLAIN}" | tee -a $log
    echo -e " Organization         : ${YELLOW}$org${PLAIN}" | tee -a $log
    echo -e " Location             : ${SKYBLUE}$city, ${YELLOW}$country / $countryCode${PLAIN}" | tee -a $log
    echo -e " Region               : ${SKYBLUE}$region${PLAIN}" | tee -a $log

    rm -rf tools.py
    rm -rf ip_json.json
}

virt_check(){
    if hash ifconfig 2>/dev/null; then
        eth=$(ifconfig)
    fi

    virtualx=$(dmesg) 2>/dev/null

    if  [ $(which dmidecode) ]; then
        sys_manu=$(dmidecode -s system-manufacturer) 2>/dev/null
        sys_product=$(dmidecode -s system-product-name) 2>/dev/null
        sys_ver=$(dmidecode -s system-version) 2>/dev/null
    else
        sys_manu=""
        sys_product=""
        sys_ver=""
    fi
    
    if grep docker /proc/1/cgroup -qa; then
        virtual="Docker"
    elif grep lxc /proc/1/cgroup -qa; then
        virtual="Lxc"
    elif grep -qa container=lxc /proc/1/environ; then
        virtual="Lxc"
    elif [[ -f /proc/user_beancounters ]]; then
        virtual="OpenVZ"
    elif [[ "$virtualx" == *kvm-clock* ]]; then
        virtual="KVM"
    elif [[ "$cname" == *KVM* ]]; then
        virtual="KVM"
    elif [[ "$cname" == *QEMU* ]]; then
        virtual="KVM"
    elif [[ "$virtualx" == *"VMware Virtual Platform"* ]]; then
        virtual="VMware"
    elif [[ "$virtualx" == *"Parallels Software International"* ]]; then
        virtual="Parallels"
    elif [[ "$virtualx" == *VirtualBox* ]]; then
        virtual="VirtualBox"
    elif [[ -e /proc/xen ]]; then
        virtual="Xen"
    elif [[ "$sys_manu" == *"Microsoft Corporation"* ]]; then
        if [[ "$sys_product" == *"Virtual Machine"* ]]; then
            if [[ "$sys_ver" == *"7.0"* || "$sys_ver" == *"Hyper-V" ]]; then
                virtual="Hyper-V"
            else
                virtual="Microsoft Virtual Machine"
            fi
        fi
    else
        virtual="Dedicated"
    fi
}

power_time_check(){
    echo -ne " Power time of disk   : "
    install_smart
    ptime=$(power_time)
    echo -e "${SKYBLUE}$ptime Hours${PLAIN}"
}

freedisk() {
    freespace=$( df -m . | awk 'NR==2 {print $4}' )
    if [[ $freespace == "" ]]; then
        $freespace=$( df -m . | awk 'NR==3 {print $3}' )
    fi
    if [[ $freespace -gt 1024 ]]; then
        printf "%s" $((1024*2))
    elif [[ $freespace -gt 512 ]]; then
        printf "%s" $((512*2))
    elif [[ $freespace -gt 256 ]]; then
        printf "%s" $((256*2))
    elif [[ $freespace -gt 128 ]]; then
        printf "%s" $((128*2))
    else
        printf "1"
    fi
}

print_io() {
    if [[ $1 == "fast" ]]; then
        writemb=$((128*2))
    else
        writemb=$(freedisk)
    fi
    
    writemb_size="$(( writemb / 2 ))MB"
    if [[ $writemb_size == "1024MB" ]]; then
        writemb_size="1.0GB"
    fi

    if [[ $writemb != "1" ]]; then
        echo -n " I/O Speed( $writemb_size )   : " | tee -a $log
        io1=$( io_test $writemb )
        echo -e "${YELLOW}$io1${PLAIN}" | tee -a $log
        echo -n " I/O Speed( $writemb_size )   : " | tee -a $log
        io2=$( io_test $writemb )
        echo -e "${YELLOW}$io2${PLAIN}" | tee -a $log
        echo -n " I/O Speed( $writemb_size )   : " | tee -a $log
        io3=$( io_test $writemb )
        echo -e "${YELLOW}$io3${PLAIN}" | tee -a $log
        ioraw1=$( echo $io1 | awk 'NR==1 {print $1}' )
        [ "`echo $io1 | awk 'NR==1 {print $2}'`" == "GB/s" ] && ioraw1=$( awk 'BEGIN{print '$ioraw1' * 1024}' )
        ioraw2=$( echo $io2 | awk 'NR==1 {print $1}' )
        [ "`echo $io2 | awk 'NR==1 {print $2}'`" == "GB/s" ] && ioraw2=$( awk 'BEGIN{print '$ioraw2' * 1024}' )
        ioraw3=$( echo $io3 | awk 'NR==1 {print $1}' )
        [ "`echo $io3 | awk 'NR==1 {print $2}'`" == "GB/s" ] && ioraw3=$( awk 'BEGIN{print '$ioraw3' * 1024}' )
        ioall=$( awk 'BEGIN{print '$ioraw1' + '$ioraw2' + '$ioraw3'}' )
        ioavg=$( awk 'BEGIN{printf "%.1f", '$ioall' / 3}' )
        echo -e " Average I/O Speed    : ${YELLOW}$ioavg MB/s${PLAIN}" | tee -a $log
    else
        echo -e " ${RED}Not enough space!${PLAIN}"
    fi
}

print_system_info() {
    echo -e " CPU Model            : ${SKYBLUE}$cname${PLAIN}" | tee -a $log
    echo -e " CPU Cores            : ${YELLOW}$cores Cores ${SKYBLUE}$freq MHz $arch${PLAIN}" | tee -a $log
    echo -e " CPU Cache            : ${SKYBLUE}$corescache ${PLAIN}" | tee -a $log
    echo -e " OS                   : ${SKYBLUE}$opsy ($lbit Bit) ${YELLOW}$virtual${PLAIN}" | tee -a $log
    echo -e " Kernel               : ${SKYBLUE}$kern${PLAIN}" | tee -a $log
    echo -e " Total Space          : ${SKYBLUE}$disk_used_size GB / ${YELLOW}$disk_total_size GB ${PLAIN}" | tee -a $log
    echo -e " Total RAM            : ${SKYBLUE}$uram MB / ${YELLOW}$tram MB ${SKYBLUE}($bram MB Buff)${PLAIN}" | tee -a $log
    echo -e " Total SWAP           : ${SKYBLUE}$uswap MB / $swap MB${PLAIN}" | tee -a $log
    echo -e " Uptime               : ${SKYBLUE}$up${PLAIN}" | tee -a $log
    echo -e " Load Average         : ${SKYBLUE}$load${PLAIN}" | tee -a $log
    echo -e " TCP CC               : ${YELLOW}$tcpctrl${PLAIN}" | tee -a $log
}

print_end_time() {
    end=$(date +%s) 
    time=$(( $end - $start ))
    if [[ $time -gt 60 ]]; then
        min=$(expr $time / 60)
        sec=$(expr $time % 60)
        echo -ne " Finished in  : ${min} min ${sec} sec" | tee -a $log
    else
        echo -ne " Finished in  : ${time} sec" | tee -a $log
    fi

    printf '\n' | tee -a $log

    bj_time=$(curl -s http://cgi.im.qq.com/cgi-bin/cgi_svrtime)

    if [[ $(echo $bj_time | grep "html") ]]; then
        bj_time=$(date -u +%Y-%m-%d" "%H:%M:%S -d '+8 hours')
    fi
    echo " Timestamp    : $bj_time GMT+8" | tee -a $log
    echo " Results      : $log"
}

get_system_info() {
    cname=$( awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//' )
    cores=$( awk -F: '/model name/ {core++} END {print core}' /proc/cpuinfo )
    freq=$( awk -F: '/cpu MHz/ {freq=$2} END {print freq}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//' )
    corescache=$( awk -F: '/cache size/ {cache=$2} END {print cache}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//' )
    tram=$( free -m | awk '/Mem/ {print $2}' )
    uram=$( free -m | awk '/Mem/ {print $3}' )
    bram=$( free -m | awk '/Mem/ {print $6}' )
    swap=$( free -m | awk '/Swap/ {print $2}' )
    uswap=$( free -m | awk '/Swap/ {print $3}' )
    up=$( awk '{a=$1/86400;b=($1%86400)/3600;c=($1%3600)/60} {printf("%d days %d hour %d min\n",a,b,c)}' /proc/uptime )
    load=$( w | head -1 | awk -F'load average:' '{print $2}' | sed 's/^[ \t]*//;s/[ \t]*$//' )
    opsy=$( get_opsy )
    arch=$( uname -m )
    lbit=$( getconf LONG_BIT )
    kern=$( uname -r )

    disk_size1=$( LANG=C df -hPl | grep -wvE '\-|none|tmpfs|overlay|shm|udev|devtmpfs|by-uuid|chroot|Filesystem' | awk '{print $2}' )
    disk_size2=$( LANG=C df -hPl | grep -wvE '\-|none|tmpfs|overlay|shm|udev|devtmpfs|by-uuid|chroot|Filesystem' | awk '{print $3}' )
    disk_total_size=$( calc_disk ${disk_size1[@]} )
    disk_used_size=$( calc_disk ${disk_size2[@]} )

    tcpctrl=$( sysctl net.ipv4.tcp_congestion_control | awk -F ' ' '{print $3}' )

    virt_check
}

print_intro() {
    printf ' Superbench.sh -- https://www.oldking.net/350.html\n' | tee -a $log
    printf " Mode  : \e${GREEN}%s\e${PLAIN}    Version : \e${GREEN}%s${PLAIN}\n" $mode_name 1.1.7 | tee -a $log
    printf ' Usage : wget -qO- sb.oldking.net | bash\n' | tee -a $log
}

sharetest() {
    echo " Share result:" | tee -a $log
    echo " · $result_speed" | tee -a $log
    log_preupload
    case $1 in
    'ubuntu')
        share_link="https://paste.ubuntu.com"$( curl -v --data-urlencode "content@$log_up" -d "poster=superbench.sh" -d "syntax=text" "https://paste.ubuntu.com" 2>&1 | \
            grep "Location" | awk '{print $3}' );;
    'haste' )
        share_link=$( curl -X POST -s -d "$(cat $log)" https://hastebin.com/documents | awk -F '"' '{print "https://hastebin.com/"$4}' );;
    'clbin' )
        share_link=$( curl -sF 'clbin=<-' https://clbin.com < $log );;
    'ptpb' )
        share_link=$( curl -sF c=@- https://ptpb.pw/?u=1 < $log );;
    esac

    echo " · $share_link" | tee -a $log
    next
    echo ""
    rm -f $log_up

}

log_preupload() {
    log_up="$HOME/superbench_upload.log"
    true > $log_up
    $(cat superbench.log 2>&1 | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" > $log_up)
}

cleanup() {
    rm -f test_file_*
    rm -rf speedtest*
    rm -f fast_com*
    rm -f tools.py
    rm -f ip_json.json
}

bench_all(){
    mode_name="Standard"
    about;
    benchinit;
    clear
    next;
    print_intro;
    next;
    get_system_info;
    print_system_info;
    ip_info4;
    next;
    print_io;
    next;
    print_speedtest;
    next;
    print_end_time;
    next;
    cleanup;
    sharetest ubuntu;
}

fast_bench(){
    mode_name="Fast"
    about;
    benchinit;
    clear
    next;
    print_intro;
    next;
    get_system_info;
    print_system_info;
    ip_info4;
    next;
    print_io fast;
    next;
    print_speedtest_fast;
    next;
    print_end_time;
    next;
    cleanup;
}

log="./superbench.log"
true > $log
speedLog="./speedtest.log"
true > $speedLog

case $1 in
    'info'|'-i'|'--i'|'-info'|'--info' )
        about;sleep 3;next;get_system_info;print_system_info;next;;
    'version'|'-v'|'--v'|'-version'|'--version')
        next;about;next;;
       'io'|'-io'|'--io'|'-drivespeed'|'--drivespeed' )
        next;print_io;next;;
    'speed'|'-speed'|'--speed'|'-speedtest'|'--speedtest'|'-speedcheck'|'--speedcheck' )
        about;benchinit;next;print_speedtest;next;cleanup;;
    'ip'|'-ip'|'--ip'|'geoip'|'-geoip'|'--geoip' )
        about;benchinit;next;ip_info4;next;cleanup;;
    'bench'|'-a'|'--a'|'-all'|'--all'|'-bench'|'--bench' )
        bench_all;;
    'about'|'-about'|'--about' )
        about;;
    'fast'|'-f'|'--f'|'-fast'|'--fast' )
        fast_bench;;
    'share'|'-s'|'--s'|'-share'|'--share' )
        bench_all;
        is_share="share"
        if [[ $2 == "" ]]; then
            sharetest ubuntu;
        else
            sharetest $2;
        fi
        ;;
    'debug'|'-d'|'--d'|'-debug'|'--debug' )
        get_ip_whois_org_name;;
*)
    bench_all;;
esac

if [[  ! $is_share == "share" ]]; then
    case $2 in
        'share'|'-s'|'--s'|'-share'|'--share' )
            if [[ $3 == '' ]]; then
                sharetest ubuntu;
            else
                sharetest $3;
            fi
            ;;
    esac
fi

脚本三:UnixBench.sh

wget --no-check-certificate https://github.com/teddysun/across/raw/master/unixbench.sh
chmod +x unixbench.sh
./unixbench.sh

秋水逸冰大佬的作品,UnixBench是一个类unix系(Unix,BSD,Linux)统下的性能测试工具,一个开源工具,被广泛用与测试Linux系统主机的性能。Unixbench的主要测试项目有:系统调用、读写、进程、图形化测试、2D、3D、管道、运算、C库等系统基准性能提供测试数据。

特点

  • 自动安装UnixBench和测试脚本

  • 系统调用、读写、进程、图形化测试、2D、3D、管道、运算、C库等系统基准性能

#! /bin/bash
#==============================================================#
#   Description:  Unixbench script                             #
#   Author: Teddysun <i@teddysun.com>                          #
#   Intro:  https://teddysun.com/245.html                      #
#==============================================================#
cur_dir=/opt/unixbench

# Check System
[[ $EUID -ne 0 ]] && echo 'Error: This script must be run as root!' && exit 1
[[ -f /etc/redhat-release ]] && os='centos'
[[ ! -z "`egrep -i debian /etc/issue`" ]] && os='debian'
[[ ! -z "`egrep -i ubuntu /etc/issue`" ]] && os='ubuntu'
[[ "$os" == '' ]] && echo 'Error: Your system is not supported to run it!' && exit 1

# Install necessary libaries
if [ "$os" == 'centos' ]; then
    yum -y install make automake gcc autoconf gcc-c++ time perl-Time-HiRes
else
    apt-get -y update
    apt-get -y install make automake gcc autoconf time perl
fi

# Create new soft download dir
mkdir -p ${cur_dir}
cd ${cur_dir}

# Download UnixBench5.1.3
if [ -s UnixBench5.1.3.tgz ]; then
    echo "UnixBench5.1.3.tgz [found]"
else
    echo "UnixBench5.1.3.tgz not found!!!download now..."
    if ! wget -c https://dl.lamp.sh/files/UnixBench5.1.3.tgz; then
        echo "Failed to download UnixBench5.1.3.tgz, please download it to ${cur_dir} directory manually and try again."
        exit 1
    fi
fi
tar -zxvf UnixBench5.1.3.tgz && rm -f UnixBench5.1.3.tgz
cd UnixBench/

#Run unixbench
make
./Run

echo
echo
echo "======= Script description and score comparison completed! ======= "
echo
echo

脚本四:LemonBench.sh

curl -fsL https://ilemonra.in/LemonBenchIntl | bash -s fast

LemonBench工具(别名LBench、柠檬Bench),是一款针对Linux服务器设计的服务器性能测试工具。通过综合测试,可以快速评估服务器的综合性能,为使用者提供服务器硬件配置信息。

特点

  • 服务器基础信息(CPU信息/内存信息/Swap信息/磁盘空间信息等)

  • Speedtest网速测试 (本地到最近源及国内各地域不同线路的网速)

  • 磁盘测试(4K块/1M块 直接写入测试)

  • 路由追踪测试(追踪到国内和海外不同线路的路由信息)

  • Spoofer测试(获取详细网络信息,快速判断服务器接入线路)

#!/usr/bin/env bash
#
# #------------------------------------------------------------------#
# |   LemonBench 服务器测试工具      LemonBench Server Test Utility   |
# #------------------------------------------------------------------#
# | Written by iLemonrain <ilemonrain@ilemonrain.com>                |
# | My Blog: https://ilemonrain.com                                  |
# | Telegram: https://t.me/ilemonrain                                |
# | Telegram (For +86 User): https://t.me/ilemonrain_chatbot         |
# | Telegram Channel: https://t.me/ilemonrain_channel                |
# #------------------------------------------------------------------#
# | If you like this project, feel free to donate!                   |
# | 如果你喜欢这个项目, 欢迎投喂打赏!                                  |
# |                                                                  |
# | Donate Method 打赏方式:                                          |
# | Alipay QR Code: http://t.cn/EA3pZNt                              |
# | 支付宝二维码:http://t.cn/EA3pZNt                                 |
# | Wechat QR Code: http://t.cn/EA3p639                              |
# | 微信二维码: http://t.cn/EA3p639                                   |
# #------------------------------------------------------------------#
#
# 使用方法 (任选其一):
# (1) wget -O- https://ilemonrain.com/download/shell/LemonBench.sh | bash
# (2) curl -fsL https://ilemonrain.com/download/shell/LemonBench.sh | bash
#
# === 全局定义 =====================================

# 全局参数定义
BuildTime="20201005 Intl BetaVersion"
WorkDir="/tmp/.LemonBench"
UA_LemonBench="LemonBench/${BuildTime}"
UA_Browser="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36"
UA_Dalvik="Dalvik/2.1.0 (Linux; U; Android 9; ALP-AL00 Build/HUAWEIALP-AL00)"

# 字体颜色定义
Font_Black="\033[30m"
Font_Red="\033[31m"
Font_Green="\033[32m"
Font_Yellow="\033[33m"
Font_Blue="\033[34m"
Font_Purple="\033[35m"
Font_SkyBlue="\033[36m"
Font_White="\033[37m"
Font_Suffix="\033[0m"

# 消息提示定义
Msg_Info="${Font_Blue}[Info] ${Font_Suffix}"
Msg_Warning="${Font_Yellow}[Warning] ${Font_Suffix}"
Msg_Debug="${Font_Yellow}[Debug] ${Font_Suffix}"
Msg_Error="${Font_Red}[Error] ${Font_Suffix}"
Msg_Success="${Font_Green}[Success] ${Font_Suffix}"
Msg_Fail="${Font_Red}[Failed] ${Font_Suffix}"

# =================================================

# === 全局模块 =====================================

# Trap终止信号捕获
trap "Global_TrapSigExit_Sig1" 1
trap "Global_TrapSigExit_Sig2" 2
trap "Global_TrapSigExit_Sig3" 3
trap "Global_TrapSigExit_Sig15" 15

# Trap终止信号1 - 处理
Global_TrapSigExit_Sig1() {
    echo -e "\n\n${Msg_Error}Caught Signal SIGHUP, Exiting ...\n"
    Global_TrapSigExit_Action
    exit 1
}

# Trap终止信号2 - 处理 (Ctrl+C)
Global_TrapSigExit_Sig2() {
    echo -e "\n\n${Msg_Error}Caught Signal SIGINT (or Ctrl+C), Exiting ...\n"
    Global_TrapSigExit_Action
    exit 1
}

# Trap终止信号3 - 处理
Global_TrapSigExit_Sig3() {
    echo -e "\n\n${Msg_Error}Caught Signal SIGQUIT, Exiting ...\n"
    Global_TrapSigExit_Action
    exit 1
}

# Trap终止信号15 - 处理 (进程被杀)
Global_TrapSigExit_Sig15() {
    echo -e "\n\n${Msg_Error}Caught Signal SIGTERM, Exiting ...\n"
    Global_TrapSigExit_Action
    exit 1
}

# 新版JSON解析
PharseJSON() {
    # 使用方法: PharseJSON "要解析的原JSON文本" "要解析的键值"
    # Example: PharseJSON ""Value":"123456"" "Value" [返回结果: 123456]
    echo -n $1 | jq -r .$2
}

# Ubuntu PasteBin 提交工具
# 感谢 @metowolf 提供思路
PasteBin_Upload() {
    local uploadresult="$(curl -fsL -X POST \
        --url https://paste.ubuntu.com \
        --output /dev/null \
        --write-out "%{url_effective}\n" \
        --data-urlencode "content@${PASTEBIN_CONTENT:-/dev/stdin}" \
        --data "poster=${PASTEBIN_POSTER:-LemonBench}" \
        --data "expiration=${PASTEBIN_EXPIRATION:-}" \
        --data "syntax=${PASTEBIN_SYNTAX:-text}")"
    if [ "$?" = "0" ]; then
        echo -e "${Msg_Success}Report Generate Success!Please save the follwing link:"
        echo -e "${Msg_Info}Report URL: ${uploadresult}"
    else
        echo -e "${Msg_Warning}Report Generate Failure, But you can still read $HOME/LemonBench.Result.txt to get this result!"
    fi
}

# 读取配置文件
ReadConfig() {
    # 使用方法: ReadConfig <配置文件> <读取参数>
    # Example: ReadConfig "/etc/config.cfg" "Parameter"
    cat $1 | sed '/^'$2'=/!d;s/.*=//'
}

# 程序启动动作
Global_StartupInit_Action() {
    Global_Startup_Header
    echo -e "${Msg_Info}Loaded Testmode:${Font_SkyBlue}${Global_TestModeTips}${Font_Suffix}"
    Function_CheckTracemode
    # 清理残留, 为新一次的运行做好准备
    echo -e "${Msg_Info}Initializing Running Enviorment, Please wait ..."
    rm -rf ${WorkDir}
    rm -rf /.tmp_LBench/
    mkdir ${WorkDir}/
    echo -e "${Msg_Info}Checking Dependency ..."
    Check_Virtwhat
    Check_JSONQuery
    Check_Speedtest
    Check_BestTrace
    Check_Spoofer
    Check_SysBench
    echo -e "${Msg_Info}Starting Test ...\n\n"
    clear
}



Global_Exit_Action() {
    rm -rf ${WorkDir}/
}

# 捕获异常信号后的动作
Global_TrapSigExit_Action() {
    rm -rf ${WorkDir}
    rm -rf /.tmp_LBench/
}

# ==================================================

# =============== -> 主程序开始 <- ==================

# =============== SystemInfo模块 部分 ===============
SystemInfo_GetHostname() {
    LBench_Result_Hostname="$(hostname)"
}


SystemInfo_GetCPUInfo() {
    mkdir -p ${WorkDir}/data >/dev/null 2>&1
    cat /proc/cpuinfo >${WorkDir}/data/cpuinfo
    local ReadCPUInfo="cat ${WorkDir}/data/cpuinfo"
    LBench_Result_CPUModelName="$($ReadCPUInfo | awk -F ': ' '/model name/{print $2}' | sort -u)"
    local CPUFreqCount="$($ReadCPUInfo | awk -F ': ' '/cpu MHz/{print $2}' | sort -run | wc -l)"
    if [ "${CPUFreqCount}" -ge "2" ]; then
        local CPUFreqArray="$(cat /proc/cpuinfo | awk -F ': ' '/cpu MHz/{print $2}' | sort -run)"
        local CPUFreq_Min="$(echo "$CPUFreqArray" | grep -oE '[0-9]+.[0-9]{3}' | awk 'BEGIN {min = 2147483647} {if ($1+0 < min+0) min=$1} END {print min}')"
        local CPUFreq_Max="$(echo "$CPUFreqArray" | grep -oE '[0-9]+.[0-9]{3}' | awk 'BEGIN {max = 0} {if ($1+0 > max+0) max=$1} END {print max}')"
        LBench_Result_CPUFreqMinGHz="$(echo $CPUFreq_Min | awk '{printf "%.2f\n",$1/1000}')"
        LBench_Result_CPUFreqMaxGHz="$(echo $CPUFreq_Max | awk '{printf "%.2f\n",$1/1000}')"
        Flag_DymanicCPUFreqDetected="1"
    else
        LBench_Result_CPUFreqMHz="$($ReadCPUInfo | awk -F ': ' '/cpu MHz/{print $2}' | sort -u)"
        LBench_Result_CPUFreqGHz="$(echo $LBench_Result_CPUFreqMHz | awk '{printf "%.2f\n",$1/1000}')"
        Flag_DymanicCPUFreqDetected="0"
    fi
    LBench_Result_CPUCacheSize="$($ReadCPUInfo | awk -F ': ' '/cache size/{print $2}' | sort -u)"
    LBench_Result_CPUPhysicalNumber="$($ReadCPUInfo | awk -F ': ' '/physical id/{print $2}' | sort -u | wc -l)"
    LBench_Result_CPUCoreNumber="$($ReadCPUInfo | awk -F ': ' '/cpu cores/{print $2}' | sort -u)"
    LBench_Result_CPUThreadNumber="$($ReadCPUInfo | awk -F ': ' '/cores/{print $2}' | wc -l)"
    LBench_Result_CPUProcessorNumber="$($ReadCPUInfo | awk -F ': ' '/processor/{print $2}' | wc -l)"
    LBench_Result_CPUSiblingsNumber="$($ReadCPUInfo | awk -F ': ' '/siblings/{print $2}' | sort -u)"
    LBench_Result_CPUTotalCoreNumber="$($ReadCPUInfo | awk -F ': ' '/physical id/&&/0/{print $2}' | wc -l)"
    
    # 虚拟化能力检测
    SystemInfo_GetVirtType
    if [ "${Var_VirtType}" = "dedicated" ] || [ "${Var_VirtType}" = "wsl" ]; then
        LBench_Result_CPUIsPhysical="1"
        local VirtCheck="$(cat /proc/cpuinfo | grep -oE 'vmx|svm' | uniq)"
        if [ "${VirtCheck}" != "" ]; then
            LBench_Result_CPUVirtualization="1"
            local VirtualizationType="$(lscpu | awk /Virtualization:/'{print $2}')"
            LBench_Result_CPUVirtualizationType="${VirtualizationType}"
        else
            LBench_Result_CPUVirtualization="0"
        fi
    elif [ "${Var_VirtType}" = "kvm" ] || [ "${Var_VirtType}" = "hyperv" ] || [ "${Var_VirtType}" = "microsoft" ] || [ "${Var_VirtType}" = "vmware" ]; then
        LBench_Result_CPUIsPhysical="0"
        local VirtCheck="$(cat /proc/cpuinfo | grep -oE 'vmx|svm' | uniq)"
        if [ "${VirtCheck}" = "vmx" ] || [ "${VirtCheck}" = "svm" ]; then
            LBench_Result_CPUVirtualization="2"
            local VirtualizationType="$(lscpu | awk /Virtualization:/'{print $2}')"
            LBench_Result_CPUVirtualizationType="${VirtualizationType}"
        else
            LBench_Result_CPUVirtualization="0"
        fi        
    else
        LBench_Result_CPUIsPhysical="0"
    fi
}

SystemInfo_GetCPUStat() {
    local CPUStat_Result="$(top -bn1 | grep Cpu)"
    # 原始数据
    LBench_Result_CPUStat_user="$(Function_ReadCPUStat "${CPUStat_Result}" "us")"
    LBench_Result_CPUStat_system="$(Function_ReadCPUStat "${CPUStat_Result}" "sy")"
    LBench_Result_CPUStat_anice="$(Function_ReadCPUStat "${CPUStat_Result}" "ni")"
    LBench_Result_CPUStat_idle="$(Function_ReadCPUStat "${CPUStat_Result}" "id")"
    LBench_Result_CPUStat_iowait="$(Function_ReadCPUStat "${CPUStat_Result}" "wa")"
    LBench_Result_CPUStat_hardint="$(Function_ReadCPUStat "${CPUStat_Result}" "hi")"
    LBench_Result_CPUStat_softint="$(Function_ReadCPUStat "${CPUStat_Result}" "si")"
    LBench_Result_CPUStat_steal="$(Function_ReadCPUStat "${CPUStat_Result}" "st")"
    # 加工后的数据
    LBench_Result_CPUStat_UsedAll="$(echo ${LBench_Result_CPUStat_user} ${LBench_Result_CPUStat_system} ${LBench_Result_CPUStat_nice} | awk '{printf "%.1f\n",$1+$2+$3}')"
}

Function_ReadCPUStat() {
    if [ "$1" == "" ]; then
        echo -n "nil"
    else
        local result="$(echo $1 | grep -oE "[0-9]{1,2}.[0-9]{1} $2" | awk '{print $1}')"
        echo $result
    fi
}

SystemInfo_GetKernelVersion() {
    local version="$(uname -r)"
    LBench_Result_KernelVersion="${version}"
}

SystemInfo_GetNetworkCCMethod() {
    local val_cc="$(sysctl -n net.ipv4.tcp_congestion_control)"
    local val_qdisc="$(sysctl -n net.core.default_qdisc)"
    LBench_Result_NetworkCCMethod="${val_cc} + ${val_qdisc}"
}

SystemInfo_GetSystemBit() {
    local sysarch="$(uname -m)"
    if [ "${sysarch}" = "unknown" ] || [ "${sysarch}" = "" ]; then
        local sysarch="$(arch)"
    fi
    if [ "${sysarch}" = "x86_64" ]; then
        # X86平台 64位
        LBench_Result_SystemBit_Short="64"
        LBench_Result_SystemBit_Full="amd64"
    elif [ "${sysarch}" = "i386" ] || [ "${sysarch}" = "i686" ]; then
        # X86平台 32位
        LBench_Result_SystemBit_Short="32"
        LBench_Result_SystemBit_Full="i386"
    elif [ "${sysarch}" = "armv7l" ] || [ "${sysarch}" = "armv8" ] || [ "${sysarch}" = "armv8l" ] || [ "${sysarch}" = "aarch64" ]; then
        # ARM平台 暂且将32位/64位统一对待
        LBench_Result_SystemBit_Short="arm"
        LBench_Result_SystemBit_Full="arm"
    else
        LBench_Result_SystemBit_Short="unknown"
        LBench_Result_SystemBit_Full="unknown"                
    fi
}

SystemInfo_GetMemInfo() {
    mkdir -p ${WorkDir}/data >/dev/null 2>&1
    cat /proc/meminfo >${WorkDir}/data/meminfo
    local ReadMemInfo="cat ${WorkDir}/data/meminfo"
    # 获取总内存
    LBench_Result_MemoryTotal_KB="$($ReadMemInfo | awk '/MemTotal/{print $2}')"
    LBench_Result_MemoryTotal_MB="$(echo $LBench_Result_MemoryTotal_KB | awk '{printf "%.2f\n",$1/1024}')"
    LBench_Result_MemoryTotal_GB="$(echo $LBench_Result_MemoryTotal_KB | awk '{printf "%.2f\n",$1/1048576}')"
    # 获取可用内存
    local MemFree="$($ReadMemInfo | awk '/MemFree/{print $2}')"
    local Buffers="$($ReadMemInfo | awk '/Buffers/{print $2}')"
    local Cached="$($ReadMemInfo | awk '/Cached/{print $2}')"
    LBench_Result_MemoryFree_KB="$(echo $MemFree $Buffers $Cached | awk '{printf $1+$2+$3}')"
    LBench_Result_MemoryFree_MB="$(echo $LBench_Result_MemoryFree_KB | awk '{printf "%.2f\n",$1/1024}')"
    LBench_Result_MemoryFree_GB="$(echo $LBench_Result_MemoryFree_KB | awk '{printf "%.2f\n",$1/1048576}')"
    # 获取已用内存
    local MemUsed="$(echo $LBench_Result_MemoryTotal_KB $LBench_Result_MemoryFree_KB | awk '{printf $1-$2}')"
    LBench_Result_MemoryUsed_KB="$MemUsed"
    LBench_Result_MemoryUsed_MB="$(echo $LBench_Result_MemoryUsed_KB | awk '{printf "%.2f\n",$1/1024}')"
    LBench_Result_MemoryUsed_GB="$(echo $LBench_Result_MemoryUsed_KB | awk '{printf "%.2f\n",$1/1048576}')"
    # 获取Swap总量
    LBench_Result_SwapTotal_KB="$($ReadMemInfo | awk '/SwapTotal/{print $2}')"
    LBench_Result_SwapTotal_MB="$(echo $LBench_Result_SwapTotal_KB | awk '{printf "%.2f\n",$1/1024}')"
    LBench_Result_SwapTotal_GB="$(echo $LBench_Result_SwapTotal_KB | awk '{printf "%.2f\n",$1/1048576}')"
    # 获取可用Swap
    LBench_Result_SwapFree_KB="$($ReadMemInfo | awk '/SwapFree/{print $2}')"
    LBench_Result_SwapFree_MB="$(echo $LBench_Result_SwapFree_KB | awk '{printf "%.2f\n",$1/1024}')"
    LBench_Result_SwapFree_GB="$(echo $LBench_Result_SwapFree_KB | awk '{printf "%.2f\n",$1/1048576}')"
    # 获取已用Swap
    local SwapUsed="$(echo $LBench_Result_SwapTotal_KB $LBench_Result_SwapFree_KB | awk '{printf $1-$2}')"
    LBench_Result_SwapUsed_KB="$SwapUsed"
    LBench_Result_SwapUsed_MB="$(echo $LBench_Result_SwapUsed_KB | awk '{printf "%.2f\n",$1/1024}')"
    LBench_Result_SwapUsed_GB="$(echo $LBench_Result_SwapUsed_KB | awk '{printf "%.2f\n",$1/1048576}')"
}

SystemInfo_GetOSRelease() {
    if [ -f "/etc/centos-release" ]; then # CentOS
        Var_OSRelease="centos"
        local Var_OSReleaseFullName="$(cat /etc/os-release | awk -F '[= "]' '/PRETTY_NAME/{print $3,$4}')"
        if [ "$(rpm -qa | grep -o el6 | sort -u)" = "el6" ]; then
            Var_CentOSELRepoVersion="6"
            local Var_OSReleaseVersion="$(cat /etc/centos-release | awk '{print $3}')"
        elif [ "$(rpm -qa | grep -o el7 | sort -u)" = "el7" ]; then
            Var_CentOSELRepoVersion="7"
            local Var_OSReleaseVersion="$(cat /etc/centos-release | awk '{print $4}')"
        elif [ "$(rpm -qa | grep -o el8 | sort -u)" = "el8" ]; then
            Var_CentOSELRepoVersion="8"
            local Var_OSReleaseVersion="$(cat /etc/centos-release | awk '{print $4}')"
        else
            local Var_CentOSELRepoVersion="unknown"
            local Var_OSReleaseVersion="<Unknown Release>"
        fi
        local Var_OSReleaseArch="$(arch)"
        LBench_Result_OSReleaseFullName="$Var_OSReleaseFullName $Var_OSReleaseVersion ($Var_OSReleaseArch)"
    elif [ -f "/etc/redhat-release" ]; then # RedHat
        Var_OSRelease="rhel"
        local Var_OSReleaseFullName="$(cat /etc/os-release | awk -F '[= "]' '/PRETTY_NAME/{print $3,$4}')"
        if [ "$(rpm -qa | grep -o el6 | sort -u)" = "el6" ]; then
            Var_RedHatELRepoVersion="6"
            local Var_OSReleaseVersion="$(cat /etc/redhat-release | awk '{print $3}')"
        elif [ "$(rpm -qa | grep -o el7 | sort -u)" = "el7" ]; then
            Var_RedHatELRepoVersion="7"
            local Var_OSReleaseVersion="$(cat /etc/redhat-release | awk '{print $4}')"
        elif [ "$(rpm -qa | grep -o el8 | sort -u)" = "el8" ]; then
            Var_RedHatELRepoVersion="8"
            local Var_OSReleaseVersion="$(cat /etc/redhat-release | awk '{print $4}')"
        else
            local Var_RedHatELRepoVersion="unknown"
            local Var_OSReleaseVersion="<Unknown Release>"
        fi
        local Var_OSReleaseArch="$(arch)"
        LBench_Result_OSReleaseFullName="$Var_OSReleaseFullName $Var_OSReleaseVersion ($Var_OSReleaseArch)"
    elif [ -f "/etc/fedora-release" ]; then # Fedora
        Var_OSRelease="fedora"
        local Var_OSReleaseFullName="$(cat /etc/os-release | awk -F '[= "]' '/PRETTY_NAME/{print $3}')"
        local Var_OSReleaseVersion="$(cat /etc/fedora-release | awk '{print $3,$4,$5,$6,$7}')"
        local Var_OSReleaseArch="$(arch)"
        LBench_Result_OSReleaseFullName="$Var_OSReleaseFullName $Var_OSReleaseVersion ($Var_OSReleaseArch)"
    elif [ -f "/etc/lsb-release" ]; then # Ubuntu
        Var_OSRelease="ubuntu"
        local Var_OSReleaseFullName="$(cat /etc/os-release | awk -F '[= "]' '/NAME/{print $3}' | head -n1)"
        local Var_OSReleaseVersion="$(cat /etc/os-release | awk -F '[= "]' '/VERSION/{print $3,$4,$5,$6,$7}' | head -n1)"
        local Var_OSReleaseArch="$(arch)"
        LBench_Result_OSReleaseFullName="$Var_OSReleaseFullName $Var_OSReleaseVersion ($Var_OSReleaseArch)"
        Var_OSReleaseVersion_Short="$(cat /etc/lsb-release | awk -F '[= "]' '/DISTRIB_RELEASE/{print $2}')"
    elif [ -f "/etc/debian_version" ]; then # Debian
        Var_OSRelease="debian"
        local Var_OSReleaseFullName="$(cat /etc/os-release | awk -F '[= "]' '/PRETTY_NAME/{print $3,$4}')"
        local Var_OSReleaseVersion="$(cat /etc/debian_version | awk '{print $1}')"
        local Var_OSReleaseVersionShort="$(cat /etc/debian_version | awk '{printf "%d\n",$1}')"
        if [ "${Var_OSReleaseVersionShort}" = "7" ]; then
            Var_OSReleaseVersion_Short="7"
            Var_OSReleaseVersion_Codename="wheezy"
            local Var_OSReleaseFullName="${Var_OSReleaseFullName} \"Wheezy\""
        elif [ "${Var_OSReleaseVersionShort}" = "8" ]; then
            Var_OSReleaseVersion_Short="8"
            Var_OSReleaseVersion_Codename="jessie"
            local Var_OSReleaseFullName="${Var_OSReleaseFullName} \"Jessie\""
        elif [ "${Var_OSReleaseVersionShort}" = "9" ]; then
            Var_OSReleaseVersion_Short="9"
            Var_OSReleaseVersion_Codename="stretch"
            local Var_OSReleaseFullName="${Var_OSReleaseFullName} \"Stretch\""
        elif [ "${Var_OSReleaseVersionShort}" = "10" ]; then
            Var_OSReleaseVersion_Short="10"
            Var_OSReleaseVersion_Codename="buster"
            local Var_OSReleaseFullName="${Var_OSReleaseFullName} \"Buster\""
        else
            Var_OSReleaseVersion_Short="sid"
            Var_OSReleaseVersion_Codename="sid"
            local Var_OSReleaseFullName="${Var_OSReleaseFullName} \"Sid (Testing)\""
        fi
        local Var_OSReleaseArch="$(arch)"
        LBench_Result_OSReleaseFullName="$Var_OSReleaseFullName $Var_OSReleaseVersion ($Var_OSReleaseArch)"
    elif [ -f "/etc/alpine-release" ]; then # Alpine Linux
        Var_OSRelease="alpinelinux"
        local Var_OSReleaseFullName="$(cat /etc/os-release | awk -F '[= "]' '/NAME/{print $3,$4}' | head -n1)"
        local Var_OSReleaseVersion="$(cat /etc/alpine-release | awk '{print $1}')"
        local Var_OSReleaseArch="$(arch)"
        LBench_Result_OSReleaseFullName="$Var_OSReleaseFullName $Var_OSReleaseVersion ($Var_OSReleaseArch)"
    else
        Var_OSRelease="unknown" # 未知系统分支
        LBench_Result_OSReleaseFullName="[Error: Unknown Linux Branch !]"
    fi
}

SystemInfo_GetVirtType() {
    if [ -f "/usr/bin/systemd-detect-virt" ]; then
        Var_VirtType="$(/usr/bin/systemd-detect-virt)"
        # 虚拟机检测
        if [ "${Var_VirtType}" = "qemu" ]; then
            LBench_Result_VirtType="QEMU"
        elif [ "${Var_VirtType}" = "kvm" ]; then
            LBench_Result_VirtType="KVM"
        elif [ "${Var_VirtType}" = "zvm" ]; then
            LBench_Result_VirtType="S390 Z/VM"
        elif [ "${Var_VirtType}" = "vmware" ]; then
            LBench_Result_VirtType="VMware"
        elif [ "${Var_VirtType}" = "microsoft" ]; then
            LBench_Result_VirtType="Microsoft Hyper-V"
        elif [ "${Var_VirtType}" = "xen" ]; then
            LBench_Result_VirtType="Xen Hypervisor"
        elif [ "${Var_VirtType}" = "bochs" ]; then
            LBench_Result_VirtType="BOCHS"   
        elif [ "${Var_VirtType}" = "uml" ]; then
            LBench_Result_VirtType="User-mode Linux"   
        elif [ "${Var_VirtType}" = "parallels" ]; then
            LBench_Result_VirtType="Parallels"   
        elif [ "${Var_VirtType}" = "bhyve" ]; then
            LBench_Result_VirtType="FreeBSD Hypervisor"
        # 容器虚拟化检测
        elif [ "${Var_VirtType}" = "openvz" ]; then
            LBench_Result_VirtType="OpenVZ"
        elif [ "${Var_VirtType}" = "lxc" ]; then
            LBench_Result_VirtType="LXC"        
        elif [ "${Var_VirtType}" = "lxc-libvirt" ]; then
            LBench_Result_VirtType="LXC (libvirt)"        
        elif [ "${Var_VirtType}" = "systemd-nspawn" ]; then
            LBench_Result_VirtType="Systemd nspawn"        
        elif [ "${Var_VirtType}" = "docker" ]; then
            LBench_Result_VirtType="Docker"        
        elif [ "${Var_VirtType}" = "rkt" ]; then
            LBench_Result_VirtType="RKT"
        # 特殊处理
        elif [ -c "/dev/lxss" ]; then # 处理WSL虚拟化
            Var_VirtType="wsl"
            LBench_Result_VirtType="Windows Subsystem for Linux (WSL)"
        # 未匹配到任何结果, 或者非虚拟机 
        elif [ "${Var_VirtType}" = "none" ]; then
            Var_VirtType="dedicated"
            LBench_Result_VirtType="None"
            local Var_BIOSVendor="$(dmidecode -s bios-vendor)"
            if [ "${Var_BIOSVendor}" = "SeaBIOS" ]; then
                Var_VirtType="Unknown"
                LBench_Result_VirtType="Unknown with SeaBIOS BIOS"
            else
                Var_VirtType="dedicated"
                LBench_Result_VirtType="Dedicated with ${Var_BIOSVendor} BIOS"
            fi
        fi
    elif [ ! -f "/usr/sbin/virt-what" ]; then
        Var_VirtType="Unknown"
        LBench_Result_VirtType="[Error: virt-what not found !]"
    elif [ -f "/.dockerenv" ]; then # 处理Docker虚拟化
        Var_VirtType="docker"
        LBench_Result_VirtType="Docker"
    elif [ -c "/dev/lxss" ]; then # 处理WSL虚拟化
        Var_VirtType="wsl"
        LBench_Result_VirtType="Windows Subsystem for Linux (WSL)"
    else # 正常判断流程
        Var_VirtType="$(virt-what | xargs)"
        local Var_VirtTypeCount="$(echo $Var_VirtTypeCount | wc -l)"
        if [ "${Var_VirtTypeCount}" -gt "1" ]; then # 处理嵌套虚拟化
            LBench_Result_VirtType="echo ${Var_VirtType}"
            Var_VirtType="$(echo ${Var_VirtType} | head -n1)" # 使用检测到的第一种虚拟化继续做判断
        elif [ "${Var_VirtTypeCount}" -eq "1" ] && [ "${Var_VirtType}" != "" ]; then # 只有一种虚拟化
            LBench_Result_VirtType="${Var_VirtType}"
        else
            local Var_BIOSVendor="$(dmidecode -s bios-vendor)"
            if [ "${Var_BIOSVendor}" = "SeaBIOS" ]; then
                Var_VirtType="Unknown"
                LBench_Result_VirtType="Unknown with SeaBIOS BIOS"
            else
                Var_VirtType="dedicated"
                LBench_Result_VirtType="Dedicated with ${Var_BIOSVendor} BIOS"
            fi
        fi
    fi
}

SystemInfo_GetLoadAverage() {
    local Var_LoadAverage="$(cat /proc/loadavg)"
    LBench_Result_LoadAverage_1min="$(echo ${Var_LoadAverage} | awk '{print $1}')"
    LBench_Result_LoadAverage_5min="$(echo ${Var_LoadAverage} | awk '{print $2}')"
    LBench_Result_LoadAverage_15min="$(echo ${Var_LoadAverage} | awk '{print $3}')"
}

SystemInfo_GetUptime() {
    local ut="$(cat /proc/uptime | awk '{printf "%d\n",$1}')"
    local ut_day="$(echo $result | awk -v ut="$ut" '{printf "%d\n",ut/86400}')"
    local ut_hour="$(echo $result | awk -v ut="$ut" -v ut_day="$ut_day" '{printf "%d\n",(ut-(86400*ut_day))/3600}')"
    local ut_minute="$(echo $result | awk -v ut="$ut" -v ut_day="$ut_day" -v ut_hour="$ut_hour" '{printf "%d\n",(ut-(86400*ut_day)-(3600*ut_hour))/60}')"
    local ut_second="$(echo $result | awk -v ut="$ut" -v ut_day="$ut_day" -v ut_hour="$ut_hour" -v ut_minute="$ut_minute" '{printf "%d\n",(ut-(86400*ut_day)-(3600*ut_hour)-(60*ut_minute))}')"
    LBench_Result_SystemInfo_Uptime_Day="$ut_day"
    LBench_Result_SystemInfo_Uptime_Hour="$ut_hour"
    LBench_Result_SystemInfo_Uptime_Minute="$ut_minute"
    LBench_Result_SystemInfo_Uptime_Second="$ut_second"
}


SystemInfo_GetDiskStat() {
    LBench_Result_DiskRootPath="$(df -x tmpfs / | awk "NR>1" | sed ":a;N;s/\\n//g;ta" | awk '{print $1}')"
    local Var_DiskTotalSpace_KB="$(df -x tmpfs / | grep -oE "[0-9]{4,}" | awk 'NR==1 {print $1}')"
    LBench_Result_DiskTotal_KB="${Var_DiskTotalSpace_KB}"
    LBench_Result_DiskTotal_MB="$(echo ${Var_DiskTotalSpace_KB} | awk '{printf "%.2f\n",$1/1000}')"
    LBench_Result_DiskTotal_GB="$(echo ${Var_DiskTotalSpace_KB} | awk '{printf "%.2f\n",$1/1000000}')"
    LBench_Result_DiskTotal_TB="$(echo ${Var_DiskTotalSpace_KB} | awk '{printf "%.2f\n",$1/1000000000}')"
    local Var_DiskUsedSpace_KB="$(df -x tmpfs / | grep -oE "[0-9]{4,}" | awk 'NR==2 {print $1}')"
    LBench_Result_DiskUsed_KB="${Var_DiskUsedSpace_KB}"
    LBench_Result_DiskUsed_MB="$(echo ${LBench_Result_DiskUsed_KB} | awk '{printf "%.2f\n",$1/1000}')"
    LBench_Result_DiskUsed_GB="$(echo ${LBench_Result_DiskUsed_KB} | awk '{printf "%.2f\n",$1/1000000}')"
    LBench_Result_DiskUsed_TB="$(echo ${LBench_Result_DiskUsed_KB} | awk '{printf "%.2f\n",$1/1000000000}')"
    local Var_DiskFreeSpace_KB="$(df -x tmpfs / | grep -oE "[0-9]{4,}" | awk 'NR==3 {print $1}')"
    LBench_Result_DiskFree_KB="${Var_DiskFreeSpace_KB}"
    LBench_Result_DiskFree_MB="$(echo ${LBench_Result_DiskFree_KB} | awk '{printf "%.2f\n",$1/1000}')"
    LBench_Result_DiskFree_GB="$(echo ${LBench_Result_DiskFree_KB} | awk '{printf "%.2f\n",$1/1000000}')"
    LBench_Result_DiskFree_TB="$(echo ${LBench_Result_DiskFree_KB} | awk '{printf "%.2f\n",$1/1000000000}')"
}

SystemInfo_GetNetworkInfo() {
    local Result_IPV4="$(curl --user-agent "${UA_LemonBench}" --connect-timeout 10 -fsL4 https://lemonbench-api.ilemonrain.com/ipapi/ipapi.php)"
    local Result_IPV6="$(curl --user-agent "${UA_LemonBench}" --connect-timeout 10 -fsL6 https://lemonbench-api.ilemonrain.com/ipapi/ipapi.php)"
    if [ "${Result_IPV4}" != "" ] && [ "${Result_IPV6}" = "" ]; then
        LBench_Result_NetworkStat="ipv4only"
    elif [ "${Result_IPV4}" = "" ] && [ "${Result_IPV6}" != "" ]; then
        LBench_Result_NetworkStat="ipv6only"
    elif [ "${Result_IPV4}" != "" ] && [ "${Result_IPV6}" != "" ]; then
        LBench_Result_NetworkStat="dualstack"
    else
        LBench_Result_NetworkStat="unknown"
    fi
    if [ "${LBench_Result_NetworkStat}" = "ipv4only" ] || [ "${LBench_Result_NetworkStat}" = "dualstack" ]; then
        IPAPI_IPV4_ip="$(PharseJSON "${Result_IPV4}" "data.ip")"
        local IPAPI_IPV4_country_name="$(PharseJSON "${Result_IPV4}" "data.country")"
        local IPAPI_IPV4_region_name="$(PharseJSON "${Result_IPV4}" "data.province")"
        local IPAPI_IPV4_city_name="$(PharseJSON "${Result_IPV4}" "data.city")"
        IPAPI_IPV4_location="${IPAPI_IPV4_country_name} ${IPAPI_IPV4_region_name} ${IPAPI_IPV4_city_name}"
        IPAPI_IPV4_country_code="$(PharseJSON "${Result_IPV4}" "data.country_code")"
        IPAPI_IPV4_asn="$(PharseJSON "${Result_IPV4}" "data.asn.number")"
        IPAPI_IPV4_organization="$(PharseJSON "${Result_IPV4}" "data.asn.desc")"
    fi
    if [ "${LBench_Result_NetworkStat}" = "ipv6only" ] || [ "${LBench_Result_NetworkStat}" = "dualstack" ]; then
        IPAPI_IPV6_ip="$(PharseJSON "${Result_IPV6}" "data.ip")"
        local IPAPI_IPV6_country_name="$(PharseJSON "${Result_IPV6}" "data.country")"
        local IPAPI_IPV6_region_name="$(PharseJSON "${Result_IPV6}" "data.province")"
        local IPAPI_IPV6_city_name="$(PharseJSON "${Result_IPV6}" "data.city")"
        IPAPI_IPV6_location="${IPAPI_IPV6_country_name} ${IPAPI_IPV6_region_name} ${IPAPI_IPV6_city_name}"
        IPAPI_IPV6_country_code="$(PharseJSON "${Result_IPV6}" "data.country_code")"
        IPAPI_IPV6_asn="$(PharseJSON "${Result_IPV6}" "data.asn.number")"
        IPAPI_IPV6_organization="$(PharseJSON "${Result_IPV6}" "data.asn.desc")"
    fi
    if [ "${LBench_Result_NetworkStat}" = "unknown" ]; then
        IPAPI_IPV4_ip="-"
        IPAPI_IPV4_location="-"
        IPAPI_IPV4_country_code="-"
        IPAPI_IPV4_asn="-"
        IPAPI_IPV4_organization="-"
        IPAPI_IPV6_ip="-"
        IPAPI_IPV6_location="-"
        IPAPI_IPV6_country_code="-"
        IPAPI_IPV6_asn="-"
        IPAPI_IPV6_organization="-"
    fi
}

Function_GetSystemInfo() {
    clear
    echo -e "${Msg_Info}LemonBench Server Test Toolkit Build ${BuildTime}"
    echo -e "${Msg_Info}SystemInfo - Collecting System Information ..."
    Check_Virtwhat
    echo -e "${Msg_Info}Collecting CPU Info ..."
    SystemInfo_GetCPUInfo
    SystemInfo_GetLoadAverage
    SystemInfo_GetSystemBit
    SystemInfo_GetCPUStat
    echo -e "${Msg_Info}Collecting Memory Info ..."
    SystemInfo_GetMemInfo
    echo -e "${Msg_Info}Collecting Virtualization Info ..."
    SystemInfo_GetVirtType
    echo -e "${Msg_Info}Collecting System Info ..."
    SystemInfo_GetUptime
    SystemInfo_GetKernelVersion
    echo -e "${Msg_Info}Collecting OS Release Info ..."
    SystemInfo_GetOSRelease
    echo -e "${Msg_Info}Collecting Disk Info ..."
    SystemInfo_GetDiskStat
    echo -e "${Msg_Info}Collecting Network Info ..."
    SystemInfo_GetNetworkCCMethod
    SystemInfo_GetNetworkInfo
    echo -e "${Msg_Info}Starting Test ..."
    clear
}

Function_ShowSystemInfo() {
    echo -e "\n ${Font_Yellow}-> System Information${Font_Suffix}\n"
    if [ "${Var_OSReleaseVersion_Codename}" != "" ]; then
        echo -e " ${Font_Yellow}OS Release:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_OSReleaseFullName}${Font_Suffix}"
    else
        echo -e " ${Font_Yellow}OS Release:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_OSReleaseFullName}${Font_Suffix}"
    fi
    if [ "${Flag_DymanicCPUFreqDetected}" = "1" ]; then
        echo -e " ${Font_Yellow}CPU Model:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_CPUModelName}${Font_Suffix}  ${Font_White}${LBench_Result_CPUFreqMinGHz}~${LBench_Result_CPUFreqMaxGHz}${Font_Suffix}${Font_SkyBlue} GHz${Font_Suffix}"
    elif [ "${Flag_DymanicCPUFreqDetected}" = "0" ]; then
        echo -e " ${Font_Yellow}CPU Model:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_CPUModelName}  ${LBench_Result_CPUFreqGHz} GHz${Font_Suffix}"
    fi
    if [ "${LBench_Result_CPUCacheSize}" != "" ]; then
        echo -e " ${Font_Yellow}CPU Cache Size:${Font_Suffix}\t${Font_SkyBlue}${LBench_Result_CPUCacheSize}${Font_Suffix}"
    else
        echo -e " ${Font_Yellow}CPU Cache Size:${Font_Suffix}\t${Font_SkyBlue}None${Font_Suffix}"
    fi
    # CPU数量 分支判断
    if [ "${LBench_Result_CPUIsPhysical}" = "1" ]; then
        # 如果只存在1个物理CPU (单路物理服务器)
        if [ "${LBench_Result_CPUPhysicalNumber}" -eq "1" ]; then
            echo -e " ${Font_Yellow}CPU Number:${Font_Suffix}\t\t${LBench_Result_CPUPhysicalNumber} ${Font_SkyBlue}Physical CPU${Font_Suffix}, ${LBench_Result_CPUCoreNumber} ${Font_SkyBlue}Cores${Font_Suffix}, ${LBench_Result_CPUThreadNumber} ${Font_SkyBlue}Threads${Font_Suffix}"
        # 存在多个CPU, 继续深入分析检测 (多路物理服务器)
        elif [ "${LBench_Result_CPUPhysicalNumber}" -ge "2" ]; then
            echo -e " ${Font_Yellow}CPU Number:${Font_Suffix}\t\t${LBench_Result_CPUPhysicalNumber} ${Font_SkyBlue}Physical CPU(s)${Font_Suffix}, ${LBench_Result_CPUCoreNumber} ${Font_SkyBlue}Cores/CPU${Font_Suffix}, ${LBench_Result_CPUSiblingsNumber} ${Font_SkyBlue}Threads/CPU${Font_Suffix} (Total ${Font_SkyBlue}${LBench_Result_CPUTotalCoreNumber}${Font_Suffix} Cores, ${Font_SkyBlue}${LBench_Result_CPUProcessorNumber}${Font_Suffix} Threads)"
        # 针对树莓派等特殊情况做出检测优化
        elif [ "${LBench_Result_CPUThreadNumber}" = "0" ] && [ "${LBench_Result_CPUProcessorNumber} " -ge "1" ]; then
             echo -e " ${Font_Yellow}CPU Number:${Font_Suffix}\t\t${LBench_Result_CPUProcessorNumber} ${Font_SkyBlue}Cores${Font_Suffix}"
        fi
        if [ "${LBench_Result_CPUVirtualization}" = "1" ]; then
            echo -e " ${Font_Yellow}VirtReady:${Font_Suffix}\t\t${Font_SkyBlue}Yes${Font_Suffix} ${Font_SkyBlue}(Based on${Font_Suffix} ${LBench_Result_CPUVirtualizationType}${Font_SkyBlue})${Font_Suffix}"
        else
            echo -e " ${Font_Yellow}VirtReady:${Font_Suffix}\t\t${Font_SkyRed}No${Font_Suffix}"
        fi
    elif [ "${Var_VirtType}" = "openvz" ]; then
        echo -e " ${Font_Yellow}CPU Number:${Font_Suffix}\t\t${LBench_Result_CPUThreadNumber} ${Font_SkyBlue}vCPU${Font_Suffix} (${LBench_Result_CPUCoreNumber} ${Font_SkyBlue}Host Core/Thread${Font_Suffix})"
    else
        if [ "${LBench_Result_CPUVirtualization}" = "2" ]; then
            echo -e " ${Font_Yellow}CPU Number:${Font_Suffix}\t\t${LBench_Result_CPUThreadNumber} ${Font_SkyBlue}vCPU${Font_Suffix}"
            echo -e " ${Font_Yellow}VirtReady:${Font_Suffix}\t\t${Font_SkyBlue}Yes${Font_Suffix} ${Font_SkyBlue}(Nested Virtualization)${Font_Suffix}"
        else
            echo -e " ${Font_Yellow}CPU Number:${Font_Suffix}\t\t${LBench_Result_CPUThreadNumber} ${Font_SkyBlue}vCPU${Font_Suffix}"
        fi
    fi
    echo -e " ${Font_Yellow}Virt Type:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_VirtType}${Font_Suffix}"
    # 内存使用率 分支判断
    if [ "${LBench_Result_MemoryUsed_KB}" -lt "1024" ] && [ "${LBench_Result_MemoryTotal_KB}" -lt "1048576" ]; then
        LBench_Result_Memory="${LBench_Result_MemoryUsed_KB} KB / ${LBench_Result_MemoryTotal_MB} MB"
        echo -e " ${Font_Yellow}Memory Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_MemoryUsed_MB} KB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_MemoryTotal_MB} MB${Font_Suffix}"
    elif [ "${LBench_Result_MemoryUsed_KB}" -lt "1048576" ] && [ "${LBench_Result_MemoryTotal_KB}" -lt "1048576" ]; then
        LBench_Result_Memory="${LBench_Result_MemoryUsed_MB} MB / ${LBench_Result_MemoryTotal_MB} MB"
        echo -e " ${Font_Yellow}Memory Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_MemoryUsed_MB} MB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_MemoryTotal_MB} MB${Font_Suffix}"
    elif [ "${LBench_Result_MemoryUsed_KB}" -lt "1048576" ] && [ "${LBench_Result_MemoryTotal_KB}" -lt "1073741824" ]; then
        LBench_Result_Memory="${LBench_Result_MemoryUsed_MB} MB / ${LBench_Result_MemoryTotal_GB} GB"
        echo -e " ${Font_Yellow}Memory Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_MemoryUsed_MB} MB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_MemoryTotal_GB} GB${Font_Suffix}"
    else
        LBench_Result_Memory="${LBench_Result_MemoryUsed_GB} GB / ${LBench_Result_MemoryTotal_GB} GB"
        echo -e " ${Font_Yellow}Memory Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_MemoryUsed_GB} GB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_MemoryTotal_GB} GB${Font_Suffix}"
    fi
    # Swap使用率 分支判断
    if [ "${LBench_Result_SwapTotal_KB}" -eq "0" ]; then
        LBench_Result_Swap="[ No Swapfile / Swap partition ]"
        echo -e " ${Font_Yellow}Swap Usage:${Font_Suffix}\t\t${Font_SkyBlue}[ No Swapfile/Swap Partition ]${Font_Suffix}"
    elif [ "${LBench_Result_SwapUsed_KB}" -lt "1024" ] && [ "${LBench_Result_SwapTotal_KB}" -lt "1048576" ]; then
        LBench_Result_Swap="${LBench_Result_SwapUsed_KB} KB / ${LBench_Result_SwapTotal_MB} MB"
        echo -e " ${Font_Yellow}Swap Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_SwapUsed_KB} KB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_SwapTotal_MB} MB${Font_Suffix}"
    elif [ "${LBench_Result_SwapUsed_KB}" -lt "1024" ] && [ "${LBench_Result_SwapTotal_KB}" -lt "1073741824" ]; then
        LBench_Result_Swap="${LBench_Result_SwapUsed_KB} KB / ${LBench_Result_SwapTotal_GB} GB"
        echo -e " ${Font_Yellow}Swap Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_SwapUsed_KB} KB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_SwapTotal_GB} GB${Font_Suffix}"
    elif [ "${LBench_Result_SwapUsed_KB}" -lt "1048576" ] && [ "${LBench_Result_SwapTotal_KB}" -lt "1048576" ]; then
        LBench_Result_Swap="${LBench_Result_SwapUsed_MB} MB / ${LBench_Result_SwapTotal_MB} MB"
        echo -e " ${Font_Yellow}Swap Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_SwapUsed_MB} MB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_SwapTotal_MB} MB${Font_Suffix}"
    elif [ "${LBench_Result_SwapUsed_KB}" -lt "1048576" ] && [ "${LBench_Result_SwapTotal_KB}" -lt "1073741824" ]; then
        LBench_Result_Swap="${LBench_Result_SwapUsed_MB} MB / ${LBench_Result_SwapTotal_GB} GB"
        echo -e " ${Font_Yellow}Swap Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_SwapUsed_MB} MB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_SwapTotal_GB} GB${Font_Suffix}"
    else
        LBench_Result_Swap="${LBench_Result_SwapUsed_GB} GB / ${LBench_Result_SwapTotal_GB} GB"
        echo -e " ${Font_Yellow}Swap Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_SwapUsed_GB} GB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_SwapTotal_GB} GB${Font_Suffix}"
    fi
    # 启动磁盘
    echo -e " ${Font_Yellow}Boot Device:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_DiskRootPath}${Font_Suffix}"
    # 磁盘使用率 分支判断
    if [ "${LBench_Result_DiskUsed_KB}" -lt "1000000" ]; then
        LBench_Result_Disk="${LBench_Result_DiskUsed_MB} MB / ${LBench_Result_DiskTotal_MB} MB"
        echo -e " ${Font_Yellow}Disk Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_DiskUsed_MB} MB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_DiskTotal_MB} MB${Font_Suffix}"
    elif [ "${LBench_Result_DiskUsed_KB}" -lt "1000000" ] && [ "${LBench_Result_DiskTotal_KB}" -lt "1000000000" ]; then
        LBench_Result_Disk="${LBench_Result_DiskUsed_MB} MB / ${LBench_Result_DiskTotal_GB} GB"
        echo -e " ${Font_Yellow}Disk Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_DiskUsed_MB} MB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_DiskTotal_GB} GB${Font_Suffix}"
    elif [ "${LBench_Result_DiskUsed_KB}" -lt "1000000000" ] && [ "${LBench_Result_DiskTotal_KB}" -lt "1000000000" ]; then
        LBench_Result_Disk="${LBench_Result_DiskUsed_GB} GB / ${LBench_Result_DiskTotal_GB} GB"
        echo -e " ${Font_Yellow}Disk Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_DiskUsed_GB} GB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_DiskTotal_GB} GB${Font_Suffix}"
    elif [ "${LBench_Result_DiskUsed_KB}" -lt "1000000000" ] && [ "${LBench_Result_DiskTotal_KB}" -ge "1000000000" ]; then
        LBench_Result_Disk="${LBench_Result_DiskUsed_GB} GB / ${LBench_Result_DiskTotal_TB} TB"
        echo -e " ${Font_Yellow}Disk Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_DiskUsed_GB} GB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_DiskTotal_TB} TB${Font_Suffix}"
    else
        LBench_Result_Disk="${LBench_Result_DiskUsed_TB} TB / ${LBench_Result_DiskTotal_TB} TB"
        echo -e " ${Font_Yellow}Disk Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_DiskUsed_TB} TB${Font_Suffix} / ${Font_SkyBlue}${LBench_Result_DiskTotal_TB} TB${Font_Suffix}"
    fi
    # CPU状态
    echo -e " ${Font_Yellow}CPU Usage:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_CPUStat_UsedAll}% used${Font_Suffix}, ${Font_SkyBlue}${LBench_Result_CPUStat_iowait}% iowait${Font_Suffix}, ${Font_SkyBlue}${LBench_Result_CPUStat_steal}% steal${Font_Suffix}"
    # 系统负载
    echo -e " ${Font_Yellow}Load (1/5/15min):${Font_Suffix}\t${Font_SkyBlue}${LBench_Result_LoadAverage_1min} ${LBench_Result_LoadAverage_5min} ${LBench_Result_LoadAverage_15min} ${Font_Suffix}"
    # 系统开机时间
    echo -e " ${Font_Yellow}Uptime:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_SystemInfo_Uptime_Day} Days, ${LBench_Result_SystemInfo_Uptime_Hour} Hours, ${LBench_Result_SystemInfo_Uptime_Minute} Minutes, ${LBench_Result_SystemInfo_Uptime_Second} Seconds${Font_Suffix}"
    # 内核版本
    echo -e " ${Font_Yellow}Kernel Version:${Font_Suffix}\t${Font_SkyBlue}${LBench_Result_KernelVersion}${Font_Suffix}"
    # 网络拥塞控制方式
    echo -e " ${Font_Yellow}Network CC Method:${Font_Suffix}\t${Font_SkyBlue}${LBench_Result_NetworkCCMethod}${Font_Suffix}"
    # 执行完成, 标记FLAG
    LBench_Flag_FinishSystemInfo="1"
}

Function_ShowNetworkInfo() {
    echo -e "\n ${Font_Yellow}-> Network Infomation${Font_Suffix}\n"
    if [ "${LBench_Result_NetworkStat}" = "ipv4only" ] || [ "${LBench_Result_NetworkStat}" = "dualstack" ]; then
        if [ "${IPAPI_IPV4_ip}" != "" ]; then
            echo -e " ${Font_Yellow}IPV4 - IP Address:${Font_Suffix}\t${Font_SkyBlue}[${IPAPI_IPV4_country_code}] ${IPAPI_IPV4_ip}${Font_Suffix}"
            echo -e " ${Font_Yellow}IPV4 - ASN Info:${Font_Suffix}\t${Font_SkyBlue}AS${IPAPI_IPV4_asn} (${IPAPI_IPV4_organization})${Font_Suffix}"
            echo -e " ${Font_Yellow}IPV4 - Region:${Font_Suffix}\t\t${Font_SkyBlue}${IPAPI_IPV4_location}${Font_Suffix}"
        else
            echo -e " ${Font_Yellow}IPV6 - IP Address:${Font_Suffix}\t${Font_Red}Error: API Query Failed${Font_Suffix}"
        fi
    fi
    if [ "${LBench_Result_NetworkStat}" = "ipv6only" ] || [ "${LBench_Result_NetworkStat}" = "dualstack" ]; then
        if [ "${IPAPI_IPV6_ip}" != "" ]; then
            echo -e " ${Font_Yellow}IPV6 - IP Address:${Font_Suffix}\t${Font_SkyBlue}[${IPAPI_IPV6_country_code}] ${IPAPI_IPV6_ip}${Font_Suffix}"
            echo -e " ${Font_Yellow}IPV6 - ASN Info:${Font_Suffix}\t${Font_SkyBlue}AS${IPAPI_IPV6_asn} (${IPAPI_IPV6_organization})${Font_Suffix}"
            echo -e " ${Font_Yellow}IPV6 - Region:${Font_Suffix}\t\t${Font_SkyBlue}${IPAPI_IPV6_location}${Font_Suffix}"
        else
            echo -e " ${Font_Yellow}IPV6 - IP Address:${Font_Suffix}\t${Font_Red}Error: API Query Failed${Font_Suffix}"
        fi
    fi
    # 执行完成, 标记FLAG
    LBench_Flag_FinishNetworkInfo="1"
}

# =============== 测试启动与结束动作 ===============
Function_BenchStart() {
    clear
    LBench_Result_BenchStartTime="$(date +"%Y-%m-%d %H:%M:%S")"
    LBench_Result_BenchStartTimestamp="$(date +%s)"
    echo -e "${Font_SkyBlue}LemonBench${Font_Suffix} ${Font_Yellow}Server Test Tookit${Font_Suffix} ${BuildTime} ${Font_SkyBlue}(C)iLemonrain. All Rights Reserved.${Font_Suffix}"
    echo -e "=========================================================================================="
    echo -e " "
    echo -e " ${Msg_Info}${Font_Yellow}Bench Start Time:${Font_Suffix} ${Font_SkyBlue}${LBench_Result_BenchStartTime}${Font_Suffix}"
    echo -e " ${Msg_Info}${Font_Yellow}Test Mode:${Font_Suffix} ${Font_SkyBlue}${Global_TestModeTips}${Font_Suffix}"
    echo -e " "
}

Function_BenchFinish() {
    # 清理临时文件
    LBench_Result_BenchFinishTime="$(date +"%Y-%m-%d %H:%M:%S")"
    LBench_Result_BenchFinishTimestamp="$(date +%s)"
    LBench_Result_TimeElapsedSec="$(echo "$LBench_Result_BenchFinishTimestamp $LBench_Result_BenchStartTimestamp" | awk '{print $1-$2}')"
    echo -e ""
    echo -e "=========================================================================================="
    echo -e " "
    echo -e " ${Msg_Info}${Font_Yellow}Bench Finish Time:${Font_Suffix} ${Font_SkyBlue}${LBench_Result_BenchFinishTime}${Font_Suffix}"
    echo -e " ${Msg_Info}${Font_Yellow}Time Elapsed:${Font_Suffix} ${Font_SkyBlue}${LBench_Result_TimeElapsedSec} seconds${Font_Suffix}"
    echo -e " "
}

#  =============== 流媒体解锁测试 部分 ===============

# 流媒体解锁测试
Function_MediaUnlockTest() {
    echo -e " "
    echo -e "${Font_Yellow} -> Media Unlock Test ${Font_Suffix}"
    echo -e " "
    Function_MediaUnlockTest_HBONow
    Function_MediaUnlockTest_BahamutAnime
    Function_MediaUnlockTest_AbemaTV_IPTest
    Function_MediaUnlockTest_PCRJP
    #Function_MediaUnlockTest_IQiYi_Taiwan
    Function_MediaUnlockTest_BBC
    Function_MediaUnlockTest_BilibiliChinaMainland
    Function_MediaUnlockTest_BilibiliHKMCTW
    Function_MediaUnlockTest_BilibiliTW
    LBench_Flag_FinishMediaUnlockTest="1"
}

# 流媒体解锁测试-HBO Now
Function_MediaUnlockTest_HBONow() {
    echo -n -e " HBO Now:\t\t\t\t->\c"
    # 尝试获取成功的结果
    local result="$(curl --user-agent "${UA_Browser}" -4 -fsL --max-time 30 --write-out "%{url_effective}\n" --output /dev/null https://play.hbonow.com/)"
    if [ "$?" = "0" ]; then
        # 下载页面成功,开始解析跳转
        if [ "${result}" = "https://play.hbonow.com" ] || [ "${result}" = "https://play.hbonow.com/" ]; then
            echo -n -e "\r HBO Now:\t\t\t\t${Font_Green}Yes${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_HBONow="Yes"
        elif [ "${result}" = "http://hbogeo.cust.footprint.net/hbonow/geo.html" ] || [ "${result}" = "http://geocust.hbonow.com/hbonow/geo.html" ]; then
            echo -n -e "\r HBO Now:\t\t\t\t${Font_Red}No${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_HBONow="No"
        else
            echo -n -e "\r HBO Now:\t\t\t\t${Font_Yellow}Failed (due to parse fail)${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_HBONow="Failed (due to parse fail)"
        fi
    else
        # 下载页面失败,返回错误代码
        echo -e "\r HBO Now:\t\t\t\t${Font_Yellow}Failed (due to network fail)${Font_Suffix}\n"
        LemonBench_Result_MediaUnlockTest_HBONow="Failed (due to network fail)"
    fi
}

# 流媒体解锁测试-动画疯
Function_MediaUnlockTest_BahamutAnime() {
    echo -n -e " Bahamut Anime:\t\t\t\t->\c"
    # 尝试获取成功的结果
    # local result="$(curl -4 --user-agent "${UA_Browser}" --output /dev/null --write-out "%{url_effective}" --max-time 30 -fsL https://ani.gamer.com.tw/animePay.php)"
    local tmpresult="$(curl -4 --user-agent "${UA_Browser}" --max-time 30 -fsL 'https://ani.gamer.com.tw/ajax/token.php?adID=89422&sn=14667')"
    if [ "$?" != "0" ]; then
        echo -n -e "\r Bahamut Anime:\t\t\t\t${Font_Red}Failed (due to network fail)${Font_Suffix}\n"
        LemonBench_Result_MediaUnlockTest_BahamutAnime="Failed (due to network fail)" 
        return 1
    fi
    local result="$(echo $tmpresult | jq -r .animeSn)"
    if [ "$result" != "null" ]; then
        resultverify="$(echo $result | grep -oE '[0-9]{1,}')"
        if [ "$?" = "0" ]; then
            echo -n -e "\r Bahamut Anime:\t\t\t\t${Font_Green}Yes${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_BahamutAnime="Yes"
        else
            echo -n -e "\r Bahamut Anime:\t\t\t\t${Font_Red}Failed (due to parse fail)${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_BahamutAnime="Failed (due to parse fail)"            
        fi
    else
        local result="$(echo $tmpresult | jq -r .error.code)"
        if [ "$result" != "null" ]; then
            resultverify="$(echo $result | grep -oE '[0-9]{1,}')"
            if [ "$?" = "0" ]; then
                echo -n -e "\r Bahamut Anime:\t\t\t\t${Font_Red}No${Font_Suffix}\n"
                LemonBench_Result_MediaUnlockTest_BahamutAnime="No"
            else
                echo -n -e "\r Bahamut Anime:\t\t\t\t${Font_Red}Failed (due to parse fail)${Font_Suffix}\n"
                LemonBench_Result_MediaUnlockTest_BahamutAnime="Failed (due to parse fail)"                 
            fi
        else
            echo -n -e "\r Bahamut Anime:\t\t\t\t${Font_Red}Failed (due to parse fail)${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_BahamutAnime="Failed (due to parse fail)"    
        fi
    fi
}

# 流媒体解锁测试-哔哩哔哩大陆限定
Function_MediaUnlockTest_BilibiliChinaMainland() {
    echo -n -e " BiliBili China Mainland Only:\t\t->\c"
    local randsession="$(cat /dev/urandom | head -n 32 | md5sum | head -c 32)"
    # 尝试获取成功的结果
    local result="$(curl --user-agent "${UA_Browser}" -4 -fsL --max-time 30 "https://api.bilibili.com/pgc/player/web/playurl?avid=82846771&qn=0&type=&otype=json&ep_id=307247&fourk=1&fnver=0&fnval=16&session=${randsession}&module=bangumi")"
    if [ "$?" = "0" ]; then
        local result="$(PharseJSON "${result}" "code")"
        if [ "$?" = "0" ]; then
            if [ "${result}" = "0" ]; then
                echo -n -e "\r BiliBili China Mainland Only:\t\t${Font_Green}Yes${Font_Suffix}\n"
                LemonBench_Result_MediaUnlockTest_ChinaMainland="Yes"
            elif [ "${result}" = "-10403" ]; then
                echo -n -e "\r BiliBili China Mainland Only:\t\t${Font_Red}No${Font_Suffix}\n"
                LemonBench_Result_MediaUnlockTest_ChinaMainland="No"
            else
                echo -n -e "\r BiliBili China Mainland Only:\t\t${Font_Red}Failed (due to unknown return)${Font_Suffix} ${Font_SkyBlue}(${result})${Font_Suffix}\n"
                LemonBench_Result_MediaUnlockTest_ChinaMainland="Failed (due to unknown return)" 
            fi
        else
            echo -n -e "\r BiliBili China Mainland Only:\t\t${Font_Red}Failed (due to parse fail)${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_ChinaMainland="Failed (due to parse fail)"
        fi
    else
        echo -n -e "\r BiliBili China Mainland Only:\t\t${Font_Red}Failed (due to network fail)${Font_Suffix}\n"
        LemonBench_Result_MediaUnlockTest_ChinaMainland="Failed (due to network fail)"        
    fi   
}

# 流媒体解锁测试-哔哩哔哩港澳台限定
Function_MediaUnlockTest_BilibiliHKMCTW() {
    echo -n -e " BiliBili Hongkong/Macau/Taiwan:\t->\c"
    local randsession="$(cat /dev/urandom | head -n 32 | md5sum | head -c 32)"
    # 尝试获取成功的结果
    local result="$(curl --user-agent "${UA_Browser}" -4 -fsL --max-time 30 "https://api.bilibili.com/pgc/player/web/playurl?avid=18281381&cid=29892777&qn=0&type=&otype=json&ep_id=183799&fourk=1&fnver=0&fnval=16&session=${randsession}&module=bangumi")"
    if [ "$?" = "0" ]; then
        local result="$(PharseJSON "${result}" "code")"
        if [ "$?" = "0" ]; then
            if [ "${result}" = "0" ]; then
                echo -n -e "\r BiliBili Hongkong/Macau/Taiwan:\t${Font_Green}Yes${Font_Suffix}\n"
                LemonBench_Result_MediaUnlockTest_BilibiliHKMCTW="Yes"
            elif [ "${result}" = "-10403" ]; then
                echo -n -e "\r BiliBili Hongkong/Macau/Taiwan:\t${Font_Red}No${Font_Suffix}\n"
                LemonBench_Result_MediaUnlockTest_BilibiliHKMCTW="No"
            else
                echo -n -e "\r BiliBili Hongkong/Macau/Taiwan:\t${Font_Red}Failed (due to unknown return)${Font_Suffix} ${Font_SkyBlue}(${result})${Font_Suffix}\n"
                LemonBench_Result_MediaUnlockTest_BilibiliHKMCTW="Failed (due to unknown return)" 
            fi
        else
            echo -n -e "\r BiliBili Hongkong/Macau/Taiwan:\t${Font_Red}Failed (due to parse fail)${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_BilibiliHKMCTW="Failed (due to parse fail)"
        fi
    else
        echo -n -e "\r BiliBili Hongkong/Macau/Taiwan:\t${Font_Red}Failed (due to network fail)${Font_Suffix}\n"
        LemonBench_Result_MediaUnlockTest_BilibiliHKMCTW="Failed (due to network fail)"        
    fi   
}

# 流媒体解锁测试-哔哩哔哩台湾限定
Function_MediaUnlockTest_BilibiliTW() {
    echo -n -e " Bilibili Taiwan Only:\t\t\t->\c"
    local randsession="$(cat /dev/urandom | head -n 32 | md5sum | head -c 32)"
    # 尝试获取成功的结果
    local result="$(curl --user-agent "${UA_Browser}" -4 -fsL --max-time 30 "https://api.bilibili.com/pgc/player/web/playurl?avid=50762638&cid=100279344&qn=0&type=&otype=json&ep_id=268176&fourk=1&fnver=0&fnval=16&session=${randsession}&module=bangumi")"
    if [ "$?" = "0" ]; then
        local result="$(PharseJSON "${result}" "code")"
        if [ "$?" = "0" ]; then
            if [ "${result}" = "0" ]; then
                echo -n -e "\r Bilibili Taiwan Only:\t\t\t${Font_Green}Yes${Font_Suffix}\n"
                LemonBench_Result_MediaUnlockTest_BilibiliTW="Yes"
            elif [ "${result}" = "-10403" ]; then
                echo -n -e "\r Bilibili Taiwan Only:\t\t\t${Font_Red}No${Font_Suffix}\n"
                LemonBench_Result_MediaUnlockTest_BilibiliTW="No"
            else
                echo -n -e "\r Bilibili Taiwan Only:\t\t\t${Font_Red}Failed (due to unknown return)${Font_Suffix} ${Font_SkyBlue}(${result})${Font_Suffix}\n"
                LemonBench_Result_MediaUnlockTest_BilibiliTW="Failed (due to unknown return)" 
            fi
        else
            echo -n -e "\r Bilibili Taiwan Only:\t\t\t${Font_Red}Failed (due to parse fail)${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_BilibiliTW="Failed (due to parse fail)"
        fi
    else
        echo -n -e "\r 哔哩哔哩-台湾限定:\t${Font_Red}Failed (due to network fail)${Font_Suffix}\n"
        LemonBench_Result_MediaUnlockTest_BilibiliTW="Failed (due to network fail)"        
    fi   
}

# 流媒体解锁测试-Abema.TV
#
Function_MediaUnlockTest_AbemaTV_IPTest() {
    echo -n -e " Abema.TV:\t\t\t\t\c"
    # 
    local result="$(curl --user-agent "${UA_Dalvik}" -4 -fsL --max-time 30 https://api.abema.io/v1/ip/check?device=android | jq -r .cdnRegionUrl)"
    if [ "${result}" = "https://ds-linear-abematv.akamaized.net/region" ] || [ "${result}" = "https://ds-glb-linear-abematv.akamaized.net/region" ]; then
        echo -n -e "\r Abema.TV:\t\t\t\t${Font_Green}Yes${Font_Suffix}\n"
        LemonBench_Result_MediaUnlockTest_AbemaTV_IPTest="Yes"
    elif [ "${result}" = "" ] || [ "${result}" = "null" ]; then
        echo -n -e "\r Abema.TV:\t\t\t\t${Font_Red}No${Font_Suffix}\n"
        LemonBench_Result_MediaUnlockTest_AbemaTV_IPTest="No"
    else
        echo -n -e "\r Abema.TV:\t\t\t\t${Font_Red}Failed (Unexpected Return Value: ${result})${Font_Suffix}\n"
        LemonBench_Result_MediaUnlockTest_AbemaTV_IPTest="Failed (Unexpected Return Value: ${result})"      
    fi
}

Function_MediaUnlockTest_PCRJP() {
    echo -n -e " Princess Connect Re:Dive Japan:\t\c"
    # 测试,连续请求两次 (单独请求一次可能会返回35, 第二次开始变成0)
    local result="$(curl --user-agent "${UA_Dalvik}" -4 -fsL --write-out %{http_code} --max-time 30 --output /dev/null https://api-priconne-redive.cygames.jp/)"
    local retval="$?"
    if [ "$retval" = "0" ]; then
        if [ "$result" = "404" ]; then
            echo -n -e "\r Princess Connect Re:Dive Japan:\t${Font_Green}Yes${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_PCRJP="Yes"
        elif [ "$result" = "403" ] || [ "$result" = "000" ]; then
            echo -n -e "\r Princess Connect Re:Dive Japan:\t${Font_Red}No${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_PCRJP="No"
        else
            echo -n -e "\r Princess Connect Re:Dive Japan:\t${Font_Red}Failed (Unexpected Result: $result)${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_PCRJP="Failed (Unexpected Result: $result)"
        fi
    else
        echo -n -e "\r Princess Connect Re:Dive Japan:\t${Font_Red}Failed (Unexpected Retval: $retval)${Font_Suffix}\n"
        LemonBench_Result_MediaUnlockTest_PCRJP="Failed (Unexpected Retval: $retval)"
    fi
}

Function_MediaUnlockTest_BBC() {
    local result="$(curl --user-agent "${UA_Browser}" -4 -fsL --write-out %{http_code} --max-time 30 --output /dev/null http://ve-dash-uk.live.cf.md.bbci.co.uk/)"
    if [ "$?" = "0" ]; then
        if [ "${result}" = "403" ] || [ "${result}" = "000" ]; then
            echo -n -e "\r BBC:\t\t\t\t\t${Font_Red}No${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_BBC="No"
        elif [ "${result}" = "404" ]; then
            echo -n -e "\r BBC:\t\t\t\t\t${Font_Green}Yes${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_BBC="Yes"
        else
            echo -n -e "\r BBC:\t\t\t\t\t${Font_Red}Failed (Unexpected Result: $result)${Font_Suffix}\n"
            LemonBench_Result_MediaUnlockTest_BBC="Failed (Unexpected Result: $result)"
        fi
    else
        echo -n -e "\r BBC:\t\t\t\t\t${Font_Red}Failed (Network Connection)${Font_Suffix}\n"
        LemonBench_Result_MediaUnlockTest_BBC="Failed (Network Connection)"
    fi
}

# =============== Speedtest 部分 ===============
Run_Speedtest() {
    # 调用方式: Run_Speedtest "服务器ID" "节点名称(用于显示)"
    sleep 0.5
    # 超时时间, 防止Speedtest卡死
    local timeout_sec="60"
    echo -n -e " $2\t\t->\c"
    mkdir -p ${WorkDir}/result/speedtest/ >/dev/null 2>&1
    if [ "$1" = "default" ]; then
        local result="$(timeout ${timeout_sec} /usr/local/lemonbench/bin/speedtest --accept-license --accept-gdpr --format=json --unit=MiB/s --progress=no 2>/dev/null || echo "Error-TimeoutExceeded")"
    elif [ "$1" = "" ]; then
        echo -n -e "\r $2\t\t${Font_Red}Fail: Invalid Speedtest Server (No servers defined)${Font_Suffix}\n"
        echo -e " $2\t\tFail: Invalid Speedtest Server (No servers defined)" >>${WorkDir}/Speedtest/result.txt
    else
        local result="$(timeout ${timeout_sec} /usr/local/lemonbench/bin/speedtest --accept-license --accept-gdpr --format=json --unit=MiB/s --progress=no --server-id $1 2>/dev/null || echo "Error-TimeoutExceeded")"
    fi
    if [ "${result}" = "Error-TimeoutExceeded" ]; then
        echo -n -e "\r $2\t\t${Font_Red}Fail: Timeout Exceeded after ${timeout_sec} seconds${Font_Suffix}\n"
        echo -e " $2\t\tFail: Timeout Exceeded after ${timeout_sec} seconds" >>${WorkDir}/Speedtest/result.txt
    else
        # 处理结果
        local getresultid="$(echo $result | jq -r .result.id 2>/dev/null | grep -v null)"
        if [ "${getresultid}" != "" ]; then
            # 上传速度 (Raw Data, 单位: bytes)
            local rr_upload_bandwidth="$(echo $result | jq -r .upload.bandwidth 2>/dev/null)"
            # 下载速度 (Raw Data, 单位: bytes)
            local rr_download_bandwidth="$(echo $result | jq -r .download.bandwidth 2>/dev/null)"
            # Ping 延迟 (Raw Data, 单位: ms)
            local rr_ping_latency="$(echo $result | jq -r .ping.latency 2>/dev/null)"
             # 获取测速节点名称
            local rr_server_name="$(echo $result | jq -r .server.name 2>/dev/null)"
            local rr_server_country="$(echo $result | jq -r .server.country 2>/dev/null)"
            local rr_server_location="$(echo $result | jq -r .server.location 2>/dev/null)"
            # 处理上传速度与下载速度,从B/s转换成MB/s
            local fr_upload_bandwidth="$(echo $rr_upload_bandwidth | awk '{printf"%.2f",$1/1024/1024}')"
            local fr_download_bandwidth="$(echo $rr_download_bandwidth | awk '{printf"%.2f",$1/1024/1024}')"
            # 处理Ping值数据,如果大于1000,只输出整位,否则保留两位小数
            local fr_ping_latency="$(echo $rr_ping_latency | awk '{if($1>=1000){printf"%d",$1}else{printf"%.2f",$1}}')"
            # 合并测速节点名称信息
            local fr_server_name="$rr_server_name ($rr_server_country $rr_server_location)"
            # 输出结果
            local test_latency_charlength="$(echo "$fr_ping_latency ms" | grep -oE "\b[0-9]{1}\.[0-9]{2} ms" >/dev/null && echo "0" || echo "1")"
            if [ "$test_latency_charlength" = "0" ]; then
                echo -n -e "\r $2\t\t${Font_SkyBlue}${fr_upload_bandwidth}${Font_Suffix} MB/s\t${Font_SkyBlue}${fr_download_bandwidth}${Font_Suffix} MB/s\t${Font_SkyBlue}${fr_ping_latency}${Font_Suffix} ms\t\t${Font_SkyBlue}${fr_server_name}${Font_Suffix}\n"
                echo -e " $2\t\t${fr_upload_bandwidth} MB/s\t${fr_download_bandwidth} MB/s\t${fr_ping_latency} ms\t\t${fr_server_name}" >>${WorkDir}/Speedtest/result.txt
            else
                echo -n -e "\r $2\t\t${Font_SkyBlue}${fr_upload_bandwidth}${Font_Suffix} MB/s\t${Font_SkyBlue}${fr_download_bandwidth}${Font_Suffix} MB/s\t${Font_SkyBlue}${fr_ping_latency}${Font_Suffix} ms\t${Font_SkyBlue}${fr_server_name}${Font_Suffix}\n"
                echo -e " $2\t\t${fr_upload_bandwidth} MB/s\t${fr_download_bandwidth} MB/s\t${fr_ping_latency} ms\t${fr_server_name}" >>${WorkDir}/Speedtest/result.txt
            fi
        else
            local getlevel="$(echo $result | jq -r .level 2>/dev/null)"
            if [ "${getlevel}" = "error" ]; then
                local getmessage="$(echo $result | jq -r .message 2>/dev/null)"
                echo -n -e "\r $2\t\t${Font_Red}Fail: ${getmessage}${Font_Suffix}\n"
                echo -e " $2\t\tFail: ${getmessage}" >>${WorkDir}/Speedtest/result.txt
            else
                local geterror="$(echo $result | jq -r .error 2>/dev/null)"
                if [ "${geterror}" != "null" ]; then
                    echo -n -e "\r $2\t\t${Font_Red}Fail: ${geterror}${Font_Suffix}\n"
                    echo -e " $2\t\tFail: ${geterror}" >>${WorkDir}/Speedtest/result.txt
                else
                    echo -n -e "\r $2\t\t${Font_Red}Fail: ${result}${Font_Suffix}\n"
                    echo -e " $2\t\tFail: ${result}" >>${WorkDir}/Speedtest/result.txt
                fi
            fi
        fi      
    fi
}

Function_Speedtest_Fast() {
    mkdir -p ${WorkDir}/Speedtest/ >/dev/null 2>&1
    echo -e "\n ${Font_Yellow}-> Speedtest.net Network Speed Test${Font_Suffix}\n"
    echo -e "\n -> Speedtest.net Network Speed Test\n" >>${WorkDir}/Speedtest/result.txt
    Check_JSONQuery
    Check_Speedtest
    echo -e " ${Font_Yellow}Node Name\t\t\tUpload Speed\tDownload Speed\tPing Latency\tServer Name${Font_Suffix}"
    echo -e " Node Name\t\t\tUpload Speed\tDownload Speed\tPing Latency\tServer Name" >>${WorkDir}/Speedtest/result.txt
    # 默认测试
    Run_Speedtest "default" "Speedtest Default"
    # 快速测试
    Run_Speedtest "5145"  "China, Beijing CU  "
    Run_Speedtest "3633"  "China, Shanghai CT "
    Run_Speedtest "4647"  "China, Hangzhou CM "
    # 执行完成, 标记FLAG
    LBench_Flag_FinishSpeedtestFast="1"
    sleep 1
}

Function_Speedtest_Full() {
    mkdir -p ${WorkDir}/Speedtest/ >/dev/null 2>&1
    echo -e "\n ${Font_Yellow}-> Speedtest.net Network Speed Test${Font_Suffix}\n"
    echo -e "\n -> Speedtest.net Network Speed Test\n" >>${WorkDir}/Speedtest/result.txt
    Check_JSONQuery
    Check_Speedtest
    echo -e " ${Font_Yellow}Node Name\t\t\tUpload Speed\tDownload Speed\tPing Latency\tServer Name${Font_Suffix}"
    echo -e " Node Name\t\t\tUpload Speed\tDownload Speed\tPing Latency\tServer Name" >>${WorkDir}/Speedtest/result.txt
    # 默认测试
    Run_Speedtest "default" "Speedtest Default"
    # 国内测试 - 联通组
    Run_Speedtest "13704" "China, Nanjing CU  "
    Run_Speedtest "24447" "China, Shanghai CU "
    # 国内测试 - 电信组
    Run_Speedtest "7509"  "China, Hangzhou CT "
    Run_Speedtest "26352" "China, Nanjing CT  "
    Run_Speedtest "27594" "China, Guangzhou CT"
    Run_Speedtest "23844" "China, Wuhan CT    "
    # 国内测试 - 移动组
    Run_Speedtest "16167" "China, Shenyang CM "
    Run_Speedtest "4647"  "China, Hangzhou CM "
    Run_Speedtest "15863" "China, Nanning CM  "
    Run_Speedtest "16145" "China, Lanzhou CM  "
    Run_Speedtest "13538" "Hong Kong, CSL     "
    Run_Speedtest "1536"  "Hong Kong, PCCW    "
    Run_Speedtest "6527"  "Korea, South Korea "
    Run_Speedtest "6087"  "Japan, GLBB        "
    Run_Speedtest "17205" "Taiwan, FET        "
    Run_Speedtest "4938"  "Taiwan, Chief      "
    Run_Speedtest "11702" "Taiwan, TWM        "
    Run_Speedtest "13623" "Singapore, Singtel "
    Run_Speedtest "7311"  "Singapore, M1      "
    Run_Speedtest "367"   "Singapore, NME     "
    Run_Speedtest "8864"  "USA, Century Link  "
    # 执行完成, 标记FLAG
    LBench_Flag_FinishSpeedtestFull="1"
    sleep 1
}

# =============== 磁盘测试 部分 ===============
Run_DiskTest_DD() {
    # 调用方式: Run_DiskTest_DD "测试文件名" "块大小" "写入次数" "测试项目名称"
    mkdir -p ${WorkDir}/DiskTest/ >/dev/null 2>&1
    SystemInfo_GetVirtType
    mkdir -p /.tmp_LBench/DiskTest >/dev/null 2>&1
    mkdir -p ${WorkDir}/data >/dev/null 2>&1
    local Var_DiskTestResultFile="${WorkDir}/data/disktest_result"
    # 将先测试读, 后测试写
    echo -n -e " $4\t\t->\c"
    # 清理缓存, 避免影响测试结果
    sync
    if [ "${Var_VirtType}" != "docker" ] && [ "${Var_VirtType}" != "openvz" ] && [ "${Var_VirtType}" != "lxc" ] && [ "${Var_VirtType}" != "wsl" ]; then
        echo 3 >/proc/sys/vm/drop_caches
    fi
    # 避免磁盘压力过高, 启动测试前暂停1s
    sleep 1
    # 正式写测试
    dd if=/dev/zero of=/.tmp_LBench/DiskTest/$1 bs=$2 count=$3 oflag=direct 2>${Var_DiskTestResultFile}
    local DiskTest_WriteSpeed_ResultRAW="$(cat ${Var_DiskTestResultFile} | grep -oE "[0-9]{1,4} kB\/s|[0-9]{1,4}.[0-9]{1,2} kB\/s|[0-9]{1,4} KB\/s|[0-9]{1,4}.[0-9]{1,2} KB\/s|[0-9]{1,4} MB\/s|[0-9]{1,4}.[0-9]{1,2} MB\/s|[0-9]{1,4} GB\/s|[0-9]{1,4}.[0-9]{1,2} GB\/s|[0-9]{1,4} TB\/s|[0-9]{1,4}.[0-9]{1,2} TB\/s|[0-9]{1,4} kB\/秒|[0-9]{1,4}.[0-9]{1,2} kB\/秒|[0-9]{1,4} KB\/秒|[0-9]{1,4}.[0-9]{1,2} KB\/秒|[0-9]{1,4} MB\/秒|[0-9]{1,4}.[0-9]{1,2} MB\/秒|[0-9]{1,4} GB\/秒|[0-9]{1,4}.[0-9]{1,2} GB\/秒|[0-9]{1,4} TB\/秒|[0-9]{1,4}.[0-9]{1,2} TB\/秒")"
    DiskTest_WriteSpeed="$(echo "${DiskTest_WriteSpeed_ResultRAW}" | sed "s/秒/s/")"
    local DiskTest_WriteTime_ResultRAW="$(cat ${Var_DiskTestResultFile} | grep -oE "[0-9]{1,}.[0-9]{1,} s|[0-9]{1,}.[0-9]{1,} s|[0-9]{1,}.[0-9]{1,} 秒|[0-9]{1,}.[0-9]{1,} 秒")"
    DiskTest_WriteTime="$(echo ${DiskTest_WriteTime_ResultRAW} | awk '{print $1}')"
    DiskTest_WriteIOPS="$(echo ${DiskTest_WriteTime} $3 | awk '{printf "%d\n",$2/$1}')"
    DiskTest_WritePastTime="$(echo ${DiskTest_WriteTime} | awk '{printf "%.2f\n",$1}')"
    if [ "${DiskTest_WriteIOPS}" -ge "10000" ]; then
        DiskTest_WriteIOPS="$(echo ${DiskTest_WriteIOPS} 1000 | awk '{printf "%.2f\n",$2/$1}')"
        echo -n -e "\r $4\t\t${Font_SkyBlue}${DiskTest_WriteSpeed} (${DiskTest_WriteIOPS}K IOPS, ${DiskTest_WritePastTime}s)${Font_Suffix}\t\t->\c"
    else
        echo -n -e "\r $4\t\t${Font_SkyBlue}${DiskTest_WriteSpeed} (${DiskTest_WriteIOPS} IOPS, ${DiskTest_WritePastTime}s)${Font_Suffix}\t\t->\c"
    fi
    # 清理结果文件, 准备下一次测试
    rm -f ${Var_DiskTestResultFile}
    # 清理缓存, 避免影响测试结果
    sync
    if [ "${Var_VirtType}" != "docker" ] && [ "${Var_VirtType}" != "wsl" ]; then
        echo 3 >/proc/sys/vm/drop_caches
    fi
    sleep 0.5
    # 正式读测试
    dd if=/.tmp_LBench/DiskTest/$1 of=/dev/null bs=$2 count=$3 iflag=direct 2>${Var_DiskTestResultFile}
    local DiskTest_ReadSpeed_ResultRAW="$(cat ${Var_DiskTestResultFile} | grep -oE "[0-9]{1,4} kB\/s|[0-9]{1,4}.[0-9]{1,2} kB\/s|[0-9]{1,4} KB\/s|[0-9]{1,4}.[0-9]{1,2} KB\/s|[0-9]{1,4} MB\/s|[0-9]{1,4}.[0-9]{1,2} MB\/s|[0-9]{1,4} GB\/s|[0-9]{1,4}.[0-9]{1,2} GB\/s|[0-9]{1,4} TB\/s|[0-9]{1,4}.[0-9]{1,2} TB\/s|[0-9]{1,4} kB\/秒|[0-9]{1,4}.[0-9]{1,2} kB\/秒|[0-9]{1,4} KB\/秒|[0-9]{1,4}.[0-9]{1,2} KB\/秒|[0-9]{1,4} MB\/秒|[0-9]{1,4}.[0-9]{1,2} MB\/秒|[0-9]{1,4} GB\/秒|[0-9]{1,4}.[0-9]{1,2} GB\/秒|[0-9]{1,4} TB\/秒|[0-9]{1,4}.[0-9]{1,2} TB\/秒")"
    DiskTest_ReadSpeed="$(echo "${DiskTest_ReadSpeed_ResultRAW}" | sed "s/s/s/")"
    local DiskTest_ReadTime_ResultRAW="$(cat ${Var_DiskTestResultFile} | grep -oE "[0-9]{1,}.[0-9]{1,} s|[0-9]{1,}.[0-9]{1,} s|[0-9]{1,}.[0-9]{1,} 秒|[0-9]{1,}.[0-9]{1,} 秒")"
    DiskTest_ReadTime="$(echo ${DiskTest_ReadTime_ResultRAW} | awk '{print $1}')"
    DiskTest_ReadIOPS="$(echo ${DiskTest_ReadTime} $3 | awk '{printf "%d\n",$2/$1}')"
    DiskTest_ReadPastTime="$(echo ${DiskTest_ReadTime} | awk '{printf "%.2f\n",$1}')"
    rm -f ${Var_DiskTestResultFile}
    # 输出结果
    echo -n -e "\r $4\t\t${Font_SkyBlue}${DiskTest_WriteSpeed} (${DiskTest_WriteIOPS} IOPS, ${DiskTest_WritePastTime}s)${Font_Suffix}\t\t${Font_SkyBlue}${DiskTest_ReadSpeed} (${DiskTest_ReadIOPS} IOPS, ${DiskTest_ReadPastTime}s)${Font_Suffix}\n"
    echo -e " $4\t\t${DiskTest_WriteSpeed} (${DiskTest_WriteIOPS} IOPS, ${DiskTest_WritePastTime} s)\t\t${DiskTest_ReadSpeed} (${DiskTest_ReadIOPS} IOPS, ${DiskTest_ReadPastTime} s)" >>${WorkDir}/DiskTest/result.txt
    rm -rf /.tmp_LBench/DiskTest/
}

Function_DiskTest_Fast() {
    mkdir -p ${WorkDir}/DiskTest/ >/dev/null 2>&1
    echo -e "\n ${Font_Yellow}-> Disk Speed Test (4K Block/1M Block, Direct Mode)${Font_Suffix}\n"
    echo -e "\n -> Disk Speed Test (4K Block/1M Block, Direct Mode)\n" >>${WorkDir}/DiskTest/result.txt
    SystemInfo_GetVirtType
    SystemInfo_GetOSRelease
    if [ "${Var_VirtType}" = "docker" ] || [ "${Var_VirtType}" = "wsl" ]; then
        echo -e " ${Msg_Warning}Due to virt architecture limit, the result may affect by the cache !\n"
    fi
    echo -e " ${Font_Yellow}Test Name\t\tWrite Speed\t\t\t\tRead Speed${Font_Suffix}"
    echo -e " Test Name\t\tWrite Speed\t\t\t\tRead Speed" >>${WorkDir}/DiskTest/result.txt
    Run_DiskTest_DD "100MB.test" "4k" "25600" "100MB-4K Block"
    Run_DiskTest_DD "1GB.test" "1M" "1000" "1GB-1M Block"
    # 执行完成, 标记FLAG
    LBench_Flag_FinishDiskTestFast="1"
    sleep 1
}

Function_DiskTest_Full() {
    mkdir -p ${WorkDir}/DiskTest/ >/dev/null 2>&1
    echo -e "\n ${Font_Yellow}-> Disk Speed Test (4K Block/1M Block, Direct-Write)${Font_Suffix}\n"
    echo -e "\n -> Disk Speed Test (4K Block/1M Block, Direct-Write)\n" >>${WorkDir}/DiskTest/result.txt
    SystemInfo_GetVirtType
    SystemInfo_GetOSRelease
    if [ "${Var_VirtType}" = "docker" ] || [ "${Var_VirtType}" = "wsl" ]; then
        echo -e " ${Msg_Warning}Due to virt architecture limit, the result may affect by the cache !\n"
    fi
    echo -e " ${Font_Yellow}Test Name\t\tWrite Speed\t\t\t\tRead Speed${Font_Suffix}"
    echo -e " Test Name\t\tWrite Speed\t\t\t\tRead Speed" >>${WorkDir}/DiskTest/result.txt
    Run_DiskTest_DD "10MB.test" "4k" "2560" "10MB-4K Block"
    Run_DiskTest_DD "10MB.test" "1M" "10" "10MB-1M Block"
    Run_DiskTest_DD "100MB.test" "4k" "25600" "100MB-4K Block"
    Run_DiskTest_DD "100MB.test" "1M" "100" "100MB-1M Block"
    Run_DiskTest_DD "1GB.test" "4k" "256000" "1GB-4K Block"
    Run_DiskTest_DD "1GB.test" "1M" "1000" "1GB-1M Block"
    # 执行完成, 标记FLAG
    LBench_Flag_FinishDiskTestFull="1"
    sleep 1
}

# =============== BestTrace 部分 ===============
Run_BestTrace() {
    mkdir -p ${WorkDir}/BestTrace/ >/dev/null 2>&1
    # 调用方式: Run_BestTrace "目标IP" "ICMP/TCP" "最大跃点数" "说明"
    if [ "$2" = "tcp" ] || [ "$2" = "TCP" ]; then
        echo -e "Traceroute to $4 (TCP Mode, Max $3 Hop)"
        echo -e "============================================================"
        echo -e "\nTraceroute to $4 (TCP Mode, Max $3 Hop)" >>${WorkDir}/BestTrace/result.txt
        echo -e "============================================================" >>${WorkDir}/BestTrace/result.txt
        /usr/local/lemonbench/bin/besttrace -g en -q 1 -n -T -m $3 $1 | tee -a ${WorkDir}/BestTrace/result.txt
    else
        echo -e "Traceroute to $4 (ICMP Mode, Max $3 Hop)"
        echo -e "============================================================"
        echo -e "\nTracecroute to $4 (ICMP Mode, Max $3 Hop)" >>${WorkDir}/BestTrace/result.txt
        echo -e "============================================================" >>${WorkDir}/BestTrace/result.txt
        /usr/local/lemonbench/bin/besttrace -g en -q 1 -n -m $3 $1 | tee -a ${WorkDir}/BestTrace/result.txt
    fi
}

Run_BestTrace6() {
    # 调用方式: Run_BestTrace "目标IP" "ICMP/TCP" "最大跃点数" "说明"
    if [ "$2" = "tcp" ] || [ "$2" = "TCP" ]; then
        echo -e "Traceroute to $4 (TCP Mode, Max $3 Hop)"
        echo -e "============================================================"
        echo -e "\nTraceroute to $4 (TCP Mode, Max $3 Hop)" >>${WorkDir}/BestTrace/result.txt
        echo -e "============================================================" >>${WorkDir}/BestTrace/result.txt
        /usr/local/lemonbench/bin/besttrace -g en -6 -q 1 -n -T -m $3 $1 >>${WorkDir}/BestTrace/result.txt
    elif [ "$2" = "icmp" ] || [ "$2" = "ICMP" ]; then
        echo -e "Traceroute to $4 (ICMP Mode, Max $3 Hop)"
        echo -e "============================================================"
        echo -e "Traceroute to $4 (ICMP Mode, Max $3 Hop)" >>${WorkDir}/BestTrace/result.txt
        echo -e "============================================================" >>${WorkDir}/BestTrace/result.txt
        /usr/local/lemonbench/bin/besttrace -g en -6 -q 1 -n -m $3 $1 | tee -a ${WorkDir}/BestTrace/result.txt
    fi
}

Function_BestTrace_Fast() {
    Check_BestTrace
    mkdir -p ${WorkDir}/BestTrace/ >/dev/null 2>&1
    if [ "${LBench_Result_NetworkStat}" = "ipv4only" ] || [ "${LBench_Result_NetworkStat}" = "dualstack" ]; then
        echo -e "\n ${Font_Yellow}-> Traceroute Test (IPV4)${Font_Suffix}\n"
        echo -e "\n -> Traceroute Test (IPV4)\n" >>${WorkDir}/BestTrace/result.txt
        # LemonBench RouteTest 节点列表 Ver 20191112
        # 国内部分
        Run_BestTrace "123.125.99.1" "${GlobalVar_TracerouteMode}" "30" "China, Beijing CU"
        Run_BestTrace "180.149.128.9" "${GlobalVar_TracerouteMode}" "30" "China, Beijing CT"
        Run_BestTrace "211.136.25.153" "${GlobalVar_TracerouteMode}" "30" "China, Beijing CM"
        Run_BestTrace "58.247.8.158" "${GlobalVar_TracerouteMode}" "30" "China, Shanghai CU"
        Run_BestTrace "180.153.28.5" "${GlobalVar_TracerouteMode}" "30" "China, Shanghai CT"
        Run_BestTrace "221.183.55.22" "${GlobalVar_TracerouteMode}" "30" "China, Shanghai CM"
        Run_BestTrace "210.21.4.130" "${GlobalVar_TracerouteMode}" "30" "China, Guangzhou CU"
        Run_BestTrace "113.108.209.1" "${GlobalVar_TracerouteMode}" "30" "China, Guangzhou CT"
        Run_BestTrace "120.196.212.25" "${GlobalVar_TracerouteMode}" "30" "China, Guangzhou CM"
        Run_BestTrace "210.13.66.238" "${GlobalVar_TracerouteMode}" "30" "China, Shanghai CU AS9929"
        Run_BestTrace "58.32.0.1" "${GlobalVar_TracerouteMode}" "30" "China, Shanghai CT CN2"
        Run_BestTrace "119.121.0.1" "${GlobalVar_TracerouteMode}" "30" "China, Guangzhou CT CN2 Gaming Broadband"
        Run_BestTrace "14.131.128.1" "${GlobalVar_TracerouteMode}" "30" "China, Beijing Dr.Peng Home Network"
        Run_BestTrace "211.167.230.100" "${GlobalVar_TracerouteMode}" "30" "China, Beijing Dr.Peng Network IDC Network"
        Run_BestTrace "202.205.109.205" "${GlobalVar_TracerouteMode}" "30" "China, Beijing CERNET"
        Run_BestTrace "159.226.254.1" "${GlobalVar_TracerouteMode}" "30" "China, Beijing CSTNET"
        Run_BestTrace "211.156.140.17" "${GlobalVar_TracerouteMode}" "30" "China, Beijing GCable"
    fi
    if [ "${LBench_Result_NetworkStat}" = "ipv6only" ] || [ "${LBench_Result_NetworkStat}" = "dualstack" ]; then
        echo -e "\n ${Font_Yellow}-> Traceroute Test (IPV6)${Font_Suffix}\n"
        echo -e "\n -> Traceroute Test (IPV6)\n" >>${WorkDir}/BestTrace/result.txt
        Run_BestTrace6 "2408:80f0:4100:2005::3" "ICMP" "30" "China, Beijing CU IPV6"
        Run_BestTrace6 "240e:18:10:a01::1" "ICMP" "30" "China, Shanghai CT IPV6"
        Run_BestTrace6 "2409:8057:5c00:30::6" "ICMP" "30" "China, Guangzhou CM IPV6"
        Run_BestTrace6 "2001:da8:a0:1001::1" "ICMP" "30" "China, Beijing CERNET2 IPV6"
        Run_BestTrace6 "2400:dd00:0:37::213" "ICMP" "30" "China, Beijing CSTNET IPV6"
    fi
    # 执行完成, 标记FLAG
    LBench_Flag_FinishBestTraceFast="1"
    sleep 1
}

Function_BestTrace_Full() {
    Check_BestTrace
    mkdir -p ${WorkDir}/BestTrace/ >/dev/null 2>&1
    if [ "${LBench_Result_NetworkStat}" = "ipv4only" ] || [ "${LBench_Result_NetworkStat}" = "dualstack" ] || [ "${LBench_Result_NetworkStat}" = "unknown" ]; then
        echo -e "\n ${Font_Yellow}-> Traceroute Test (IPV4)${Font_Suffix}\n"
        echo -e "\n -> Traceroute Test (IPV4)\n" >>${WorkDir}/BestTrace/result.txt
        # LemonBench RouteTest 节点列表 Ver 20191112
        # 国内部分
        Run_BestTrace "123.125.99.1" "${GlobalVar_TracerouteMode}" "30" "China, Beijing CU"
        Run_BestTrace "180.149.128.1" "${GlobalVar_TracerouteMode}" "30" "China, Beijing CT"
        Run_BestTrace "211.136.25.153" "${GlobalVar_TracerouteMode}" "30" "China, Beijing CM"
        Run_BestTrace "58.247.0.49" "${GlobalVar_TracerouteMode}" "30" "China, Shanghai CU"
        Run_BestTrace "180.153.28.1" "${GlobalVar_TracerouteMode}" "30" "China, Shanghai CT"
        Run_BestTrace "221.183.55.22" "${GlobalVar_TracerouteMode}" "30" "China, Shanghai CM"
        Run_BestTrace "210.21.4.130" "${GlobalVar_TracerouteMode}" "30" "China, Guangzhou CU"
        Run_BestTrace "113.108.209.1" "${GlobalVar_TracerouteMode}" "30" "China, Guangzhou CT"
        Run_BestTrace "211.139.129.5" "${GlobalVar_TracerouteMode}" "30" "China, Guangzhou CM"
        Run_BestTrace "210.13.66.238" "${GlobalVar_TracerouteMode}" "30" "China, Shanghai CU AS9929"
        Run_BestTrace "58.32.0.1" "${GlobalVar_TracerouteMode}" "30" "China, Shanghai CT CN2"
    Run_BestTrace "119.121.0.1" "${GlobalVar_TracerouteMode}" "30" "China, Guangzhou CT CN2 Gaming Broadband"
        Run_BestTrace "14.131.128.1" "${GlobalVar_TracerouteMode}" "30" "China, Beijing Dr.Peng Home Network"
        Run_BestTrace "211.167.230.100" "${GlobalVar_TracerouteMode}" "30" "China, Beijing Dr.Peng Network IDC Network"
        Run_BestTrace "202.205.109.205" "${GlobalVar_TracerouteMode}" "30" "China, Beijing CERNET"
        Run_BestTrace "159.226.254.1" "${GlobalVar_TracerouteMode}" "30" "China, Beijing CSTNET"
        Run_BestTrace "211.156.140.17" "${GlobalVar_TracerouteMode}" "30" "China, Beijing GCable"
        # 香港部分
        Run_BestTrace "203.160.95.218" "${GlobalVar_TracerouteMode}" "30" "China, Hongkong CU"
        Run_BestTrace "203.215.232.173" "${GlobalVar_TracerouteMode}" "30" "China, Hongkong CT"
        Run_BestTrace "203.8.25.187" "${GlobalVar_TracerouteMode}" "30" "China, Hongkong CT CN2"
        Run_BestTrace "203.142.105.9" "${GlobalVar_TracerouteMode}" "30" "China, Hongkong CM"
        Run_BestTrace "218.188.104.30" "${GlobalVar_TracerouteMode}" "30" "China, Hongkong HGC"
        Run_BestTrace "210.6.23.239" "${GlobalVar_TracerouteMode}" "30" "China, Hongkong HKBN"
        Run_BestTrace "202.85.125.60" "${GlobalVar_TracerouteMode}" "30" "China, Hongkong PCCW"
        Run_BestTrace "202.123.76.239" "${GlobalVar_TracerouteMode}" "30" "China, Hongkong TGT"
        Run_BestTrace "59.152.252.242" "${GlobalVar_TracerouteMode}" "30" "China, Hongkong WTT"
        # 新加坡部分
        Run_BestTrace "203.215.233.1" "${GlobalVar_TracerouteMode}" "30" "Singapore, China CT"
        Run_BestTrace "183.91.61.1" "${GlobalVar_TracerouteMode}" "30" "Singapore, China CT CN2"
        Run_BestTrace "118.201.1.11" "${GlobalVar_TracerouteMode}" "30" "Singapore, Singtel"
        Run_BestTrace "203.116.46.33" "${GlobalVar_TracerouteMode}" "30" "Singapore, StarHub"
        Run_BestTrace "118.189.184.1" "${GlobalVar_TracerouteMode}" "30" "Singapore, M1"
        Run_BestTrace "118.189.38.17" "${GlobalVar_TracerouteMode}" "30" "Singapore, M1 GamePro"
        Run_BestTrace "13.228.0.251" "${GlobalVar_TracerouteMode}" "30" "Singapore, AWS"
        # 日本部分
        Run_BestTrace "61.213.155.84" "${GlobalVar_TracerouteMode}" "30" "Japan, NTT"
        Run_BestTrace "202.232.15.70" "${GlobalVar_TracerouteMode}" "30" "Japan, IIJ"
        Run_BestTrace "210.175.32.26" "${GlobalVar_TracerouteMode}" "30" "Japan, SoftBank"
        Run_BestTrace "106.162.242.108" "${GlobalVar_TracerouteMode}" "30" "Japan, KDDI"
        Run_BestTrace "203.215.236.3" "${GlobalVar_TracerouteMode}" "30" "Japan, China CT"
        Run_BestTrace "202.55.27.4" "${GlobalVar_TracerouteMode}" "30" "Japan, China CT CN2"
        Run_BestTrace "13.112.63.251" "${GlobalVar_TracerouteMode}" "30" "Japan, Amazon AWS"
        # 韩国部分
        Run_BestTrace "210.114.41.101" "${GlobalVar_TracerouteMode}" "30" "South Korea, KT"
        Run_BestTrace "175.122.253.62 " "${GlobalVar_TracerouteMode}" "30" "South Korea, SK"
        Run_BestTrace "211.174.62.44" "${GlobalVar_TracerouteMode}" "30" "South Korea, LG"
        Run_BestTrace "218.185.246.3" "${GlobalVar_TracerouteMode}" "30" "South Korea, China CT CN2"
        Run_BestTrace "13.124.63.251" "${GlobalVar_TracerouteMode}" "30" "South Korea, Amazon AWS"
        # 台湾部分
        Run_BestTrace "202.133.242.116" "${GlobalVar_TracerouteMode}" "30" "China, Taiwan Chief"
        Run_BestTrace "210.200.69.90" "${GlobalVar_TracerouteMode}" "30" "China, Taiwan APTG"
        Run_BestTrace "203.75.129.162" "${GlobalVar_TracerouteMode}" "30" "China, Taiwan CHT"
        Run_BestTrace "219.87.66.3" "${GlobalVar_TracerouteMode}" "30" "China, Taiwan TFN"
        Run_BestTrace "211.73.144.38" "${GlobalVar_TracerouteMode}" "30" "China,Taiwan FET"
        Run_BestTrace "61.63.0.102" "${GlobalVar_TracerouteMode}" "30" "China, Taiwan KBT"
        Run_BestTrace "103.31.196.203" "${GlobalVar_TracerouteMode}" "30" "China, Taiwan TAIFO"
        # 美国部分
        Run_BestTrace "218.30.33.17" "${GlobalVar_TracerouteMode}" "30" "United States, Los Angeles China CT"
        Run_BestTrace "66.102.252.100" "${GlobalVar_TracerouteMode}" "30" "United States, Los Angeles China CT CN2"
        Run_BestTrace "63.218.42.81" "${GlobalVar_TracerouteMode}" "30" "United States, Los Angeles PCCW"
        Run_BestTrace "66.220.18.42" "${GlobalVar_TracerouteMode}" "30" "United States, Los Angeles HE"
        Run_BestTrace "173.205.77.98" "${GlobalVar_TracerouteMode}" "30" "United States, Los Angeles GTT"
        Run_BestTrace "12.169.215.33" "${GlobalVar_TracerouteMode}" "30" "United States, San Fransico ATT"
        Run_BestTrace "66.198.181.100" "${GlobalVar_TracerouteMode}" "30" "United States, New York TATA"
        Run_BestTrace "218.30.33.17" "${GlobalVar_TracerouteMode}" "30" "United States, San Jose China CT"
        Run_BestTrace "23.11.26.62" "${GlobalVar_TracerouteMode}" "30" "United States, San Jose NTT"
        Run_BestTrace "72.52.104.74" "${GlobalVar_TracerouteMode}" "30" "United States, Fremont HE"
        Run_BestTrace "205.216.62.38" "${GlobalVar_TracerouteMode}" "30" "United States, Las Vegas Level3"
        Run_BestTrace "64.125.191.31" "${GlobalVar_TracerouteMode}" "30" "United States, San Jose ZAYO"
        Run_BestTrace "149.127.109.166" "${GlobalVar_TracerouteMode}" "30" "United States, Ashburn Cogentco"
        # 欧洲部分
        Run_BestTrace "80.146.191.1" "${GlobalVar_TracerouteMode}" "30" "German, Telekom"
        Run_BestTrace "82.113.108.25" "${GlobalVar_TracerouteMode}" "30" "German, Frankfurt O2"
        Run_BestTrace "139.7.146.11" "${GlobalVar_TracerouteMode}" "30" "German, Frankfurt Vodafone"
        Run_BestTrace "118.85.205.101" "${GlobalVar_TracerouteMode}" "30" "German, Frankfurt China CT"
        Run_BestTrace "5.10.138.33" "${GlobalVar_TracerouteMode}" "30" "German, Frankfurt China CT CN2"
        Run_BestTrace "213.200.65.70" "${GlobalVar_TracerouteMode}" "30" "German, Frankfurt GTT"
        Run_BestTrace "212.20.150.5" "${GlobalVar_TracerouteMode}" "30" "German, FrankfurtCogentco"
        Run_BestTrace "194.62.232.211" "${GlobalVar_TracerouteMode}" "30" "United Kingdom, Vodafone"
        Run_BestTrace "213.121.43.24" "${GlobalVar_TracerouteMode}" "30" "United Kingdom, BT"
        Run_BestTrace "80.231.131.34" "${GlobalVar_TracerouteMode}" "30" "United Kingdom, London TATA"
        Run_BestTrace "118.85.205.181" "${GlobalVar_TracerouteMode}" "30" "Russia, China CT"
        Run_BestTrace "185.75.173.17" "${GlobalVar_TracerouteMode}" "30" "Russia, China CT CN2"
        Run_BestTrace "87.226.162.77" "${GlobalVar_TracerouteMode}" "30" "Russia, Moscow RT"
        Run_BestTrace "217.150.32.2" "${GlobalVar_TracerouteMode}" "30" "Russia, Moscow TTK"
        Run_BestTrace "195.34.32.71" "${GlobalVar_TracerouteMode}" "30" "Russia, Moscow MTS"
    fi
    if [ "${LBench_Result_NetworkStat}" = "ipv6only" ] || [ "${LBench_Result_NetworkStat}" = "dualstack" ] || [ "${LBench_Result_NetworkStat}" = "unknown" ]; then
        echo -e "\n ${Font_Yellow}-> Traceroute Test (IPV6)${Font_Suffix}\n"
        echo -e "\n -> Traceroute Test (IPV6)\n" >>${WorkDir}/BestTrace/result.txt
        # 国内部分
        Run_BestTrace6 "2408:80f0:4100:2005::3" "ICMP" "30" "China, Beijing CU IPV6"
        Run_BestTrace6 "2400:da00:2::29" "ICMP" "30" "China, Beijing CT IPV6"
        Run_BestTrace6 "2409:8089:1020:50ff:1000::fd01" "ICMP" "30" "China, Beijing CM IPV6"
        Run_BestTrace6 "2408:8000:9000:20e6::b7" "ICMP" "30" "China, Shanghai CU IPV6"
        Run_BestTrace6 "240e:18:10:a01::1" "ICMP" "30" "China, Shanghai CT IPV6"
        Run_BestTrace6 "2409:801e:5c03:2000::207" "ICMP" "30" "China, Shanghai CM IPV6"
        Run_BestTrace6 "2408:8001:3011:310::3" "ICMP" "30" "China, Guangzhou CU IPV6"
        Run_BestTrace6 "240e:ff:e02c:1:21::" "ICMP" "30" "China, Guangzhou CT IPV6"
        Run_BestTrace6 "2409:8057:5c00:30::6" "ICMP" "30" "China, Guangzhou CM IPV6"
        Run_BestTrace6 "2403:8880:400f::2" "ICMP" "30" "China, Beijing Dr.Peng IPV6"
        Run_BestTrace6 "2001:da8:a0:1001::1" "ICMP" "30" "China, Beijing CERNET2 IPV6"
        Run_BestTrace6 "2400:dd00:0:37::213" "ICMP" "30" "China, Beijing CSTNET IPV6"
        # 香港部分
        Run_BestTrace6 "2001:7fa:0:1::ca28:a1a9" "ICMP" "30" "China, Hongkong HKIX IPV6"
        Run_BestTrace6 "2001:470:0:490::2" "ICMP" "30" "China, Hongkong HE IPV6"
        # 美国部分
        Run_BestTrace6 "2001:470:1:ff::1" "ICMP" "30" "United States, San Jose HE IPV6"
        Run_BestTrace6 "2001:418:0:5000::1026" "ICMP" "30" "United States, Chicago NTT IPV6"
        Run_BestTrace6 "2001:2000:3080:1e96::2" "ICMP" "30" "United States, Los Angeles Telia IPV6"
        Run_BestTrace6 "2001:668:0:3:ffff:0:d8dd:9d5a" "ICMP" "30" "United States, Los Angeles GTT IPV6"
        Run_BestTrace6 "2600:0:1:1239:144:228:241:71" "ICMP" "30" "United States, Kansas City Sprint IPV6"
        Run_BestTrace6 "2600:80a:2::15" "ICMP" "30" "United States, Los Angeles Verizon IPV6"
        Run_BestTrace6 "2001:550:0:1000::9a36:4215" "ICMP" "30" "United Status, Ashburn Cogentco IPV6"
        Run_BestTrace6 "2001:1900:2100::2eb5" "ICMP" "30" "United States, San Jose Level3 IPV6"
        Run_BestTrace6 "2001:438:ffff::407d:d6a" "ICMP" "30" "United States, Seattle Zayo IPV6"
        # 欧洲部分
        Run_BestTrace6 "2001:470:0:349::1" "ICMP" "30" "France, Paris HE IPV6"
        Run_BestTrace6 "2001:728:0:5000::6f6" "ICMP" "30" "German, Frankfurt NTT IPV6"
    fi
    # 执行完成, 标记FLAG
    LBench_Flag_FinishBestTraceFull="1"
    sleep 1
}

Function_SpooferTest() {
    if [ "${Var_SpooferDisabled}" = "1" ]; then
        return 0
    fi
    mkdir -p ${WorkDir}/Spoofer/ >/dev/null 2>&1
    echo -e "\n ${Font_Yellow}-> Spoof Test${Font_Suffix}\n"
    echo -e "\n -> Spoof Test\n" >>${WorkDir}/Spoofer/result.txt
    Check_Spoofer
    mkdir ${WorkDir}/ >/dev/null 2>&1
    echo -e "Running Spoof Test, this may take a long time, please wait ..."
    /usr/local/bin/spoofer-prober -s0 -r0 | tee -a ${WorkDir}/spoofer.log >/dev/null
    if [ "$?" = "0" ]; then
        LBench_Result_SpooferResultURL="$(cat ${WorkDir}/spoofer.log | grep -oE "https://spoofer.caida.org/report.php\?sessionkey\=[0-9a-z]{1,}")"
        echo -e "\n ${Msg_Success}Spoofer Result:${LBench_Result_SpooferResultURL}"
        echo -e "\n Spoofer Result:${LBench_Result_SpooferResultURL}" >>${WorkDir}/Spoofer/result.txt
        LBench_Flag_FinishSpooferTest="1"
    else
        cp -f ${WorkDir}/spoofer.log /tmp/lemonbench.spoofer.log
        echo -e "\n ${Msg_Error}Spoofer Test Fail! Please read /tmp/lemonbench.spoofer.log to view logs !"
        echo -e "\n Spoofer Result:Fail" >>${WorkDir}/Spoofer/result.txt
        LBench_Flag_FinishSpooferTest="2"
    fi
    rm -rf ${WorkDir}/spoofer.log
    # 执行完成, 标记FLAG
    sleep 1
}

Function_SpooferWarning() {
    echo -e " "
    echo -e "\e[33;43;1m  Please Read this FIRST  \e[0m"
    echo -e " "
    echo -e " Due to some user report, running spoof test may cause server suspendsion by your host provider."
    echo -e " Please use this function with caution."
    echo -e " "
    echo -e " If you still want to start this test, you can press any key to continue, else press Ctrl+C to"
    echo -e " stop running this test."
    read -s -n1 -p ""
}

# =============== SysBench - CPU性能 部分 ===============
Run_SysBench_CPU() {
    # 调用方式: Run_SysBench_CPU "线程数" "测试时长(s)" "测试遍数" "说明"
    # 变量初始化
    mkdir -p ${WorkDir}/SysBench/CPU/ >/dev/null 2>&1
    maxtestcount="$3"
    local count="1"
    local TestScore="0"
    local TotalScore="0"
    # 运行测试
    while [ $count -le $maxtestcount ]; do
        echo -e "\r ${Font_Yellow}$4: ${Font_Suffix}\t\t$count/$maxtestcount \c"
        local TestResult="$(sysbench --test=cpu --num-threads=$1 --cpu-max-prime=10000 --max-requests=1000000 --max-time=$2 run 2>&1)"
        local TestScore="$(echo ${TestResult} | grep -oE "events per second: [0-9]+" | grep -oE "[0-9]+")"
        local TotalScore="$(echo "${TotalScore} ${TestScore}" | awk '{printf "%d",$1+$2}')"
        let count=count+1
        local TestResult=""
        local TestScore="0"
    done
    local ResultScore="$(echo "${TotalScore} ${maxtestcount}" | awk '{printf "%d",$1/$2}')"
    if [ "$1" = "1" ]; then
        echo -e "\r ${Font_Yellow}$4: ${Font_Suffix}\t\t${Font_SkyBlue}${ResultScore}${Font_Suffix} ${Font_Yellow}Scores${Font_Suffix}"
        echo -e " $4:\t\t\t${ResultScore} Scores" >>${WorkDir}/SysBench/CPU/result.txt
    elif [ "$1" -ge "2" ]; then
        echo -e "\r ${Font_Yellow}$4: ${Font_Suffix}\t\t${Font_SkyBlue}${ResultScore}${Font_Suffix} ${Font_Yellow}Scores${Font_Suffix}"
        echo -e " $4:\t\t${ResultScore} Scores" >>${WorkDir}/SysBench/CPU/result.txt
    fi
}

Function_SysBench_CPU_Fast() {
    mkdir -p ${WorkDir}/SysBench/CPU/ >/dev/null 2>&1
    echo -e "\n ${Font_Yellow}-> CPU Performance Test (Fast Mode, 1-Pass @ 5sec)${Font_Suffix}\n"
    echo -e "\n -> CPU Performance Test (Fast Mode, 1-Pass @ 5sec)\n" >>${WorkDir}/SysBench/CPU/result.txt
    Run_SysBench_CPU "1" "5" "1" "1 Thread Test"
    if [ "${LBench_Result_CPUThreadNumber}" -ge "2" ]; then
        Run_SysBench_CPU "${LBench_Result_CPUThreadNumber}" "5" "1" "${LBench_Result_CPUThreadNumber} Threads Test"
    elif [ "${LBench_Result_CPUProcessorNumber}" -ge "2" ]; then
        Run_SysBench_CPU "${LBench_Result_CPUProcessorNumber}" "5" "1" "${LBench_Result_CPUProcessorNumber} Threads Test"
    fi
    # 完成FLAG
    LBench_Flag_FinishSysBenchCPUFast="1"
}

Function_SysBench_CPU_Full() {
    mkdir -p ${WorkDir}/SysBench/CPU/ >/dev/null 2>&1
    echo -e "\n ${Font_Yellow}-> CPU Performance Test (Standard Mode, 3-Pass @ 30sec)${Font_Suffix}\n"
    echo -e "\n -> CPU Performance Test (Standard Mode, 3-Pass @ 30sec)\n" >>${WorkDir}/SysBench/CPU/result.txt
    Run_SysBench_CPU "1" "30" "3" "1 Thread Test"
    if [ "${LBench_Result_CPUThreadNumber}" -ge "2" ]; then
        Run_SysBench_CPU "${LBench_Result_CPUThreadNumber}" "30" "3" "${LBench_Result_CPUThreadNumber} Threads Test"
    elif [ "${LBench_Result_CPUProcessorNumber}" -ge "2" ]; then
        Run_SysBench_CPU "${LBench_Result_CPUProcessorNumber}" "30" "3" "${LBench_Result_CPUProcessorNumber} Threads Test"
    fi
    # 完成FLAG
    LBench_Flag_FinishSysBenchCPUFull="1"
    sleep 1
}

# =============== SysBench - 内存性能 部分 ===============
Run_SysBench_Memory() {
    # 调用方式: Run_SysBench_Memory "线程数" "测试时长(s)" "测试遍数" "测试模式(读/写)" "读写方式(顺序/随机)" "说明"
    # 变量初始化
    mkdir -p ${WorkDir}/SysBench/Memory/ >/dev/null 2>&1
    maxtestcount="$3"
    local count="1"
    local TestScore="0.00"
    local TestSpeed="0.00"
    local TotalScore="0.00"
    local TotalSpeed="0.00"
    if [ "$1" -ge "2" ]; then
        MultiThread_Flag="1"
    else
        MultiThread_Flag="0"
    fi
    # 运行测试
    while [ $count -le $maxtestcount ]; do
        if [ "$1" -ge "2" ] && [ "$4" = "write" ]; then
            echo -e "\r ${Font_Yellow}$6:${Font_Suffix}\t$count/$maxtestcount \c"
        else
            echo -e "\r ${Font_Yellow}$6:${Font_Suffix}\t\t$count/$maxtestcount \c"
        fi
        local TestResult="$(sysbench --test=memory --num-threads=$1 --memory-block-size=1M --memory-total-size=102400G --memory-oper=$4 --max-time=$2 --memory-access-mode=$5 run 2>&1)"
        # 判断是MB还是MiB
        echo "${TestResult}" | grep -oE "MiB" >/dev/null 2>&1
        if [ $? -eq 0 ]; then
            local MiB_Flag="1"
        else
            local MiB_Flag="0"
        fi
        local TestScore="$(echo "${TestResult}" | grep -oE "[0-9]{1,}.[0-9]{1,2} ops\/sec|[0-9]{1,}.[0-9]{1,2} per second" | grep -oE "[0-9]{1,}.[0-9]{1,2}")"
        local TestSpeed="$(echo "${TestResult}" | grep -oE "[0-9]{1,}.[0-9]{1,2} MB\/sec|[0-9]{1,}.[0-9]{1,2} MiB\/sec" | grep -oE "[0-9]{1,}.[0-9]{1,2}")"
        local TotalScore="$(echo "${TotalScore} ${TestScore}" | awk '{printf "%.2f",$1+$2}')"
        local TotalSpeed="$(echo "${TotalSpeed} ${TestSpeed}" | awk '{printf "%.2f",$1+$2}')"
        let count=count+1
        local TestResult=""
        local TestScore="0.00"
        local TestSpeed="0.00"
    done
    ResultScore="$(echo "${TotalScore} ${maxtestcount} 1000" | awk '{printf "%.2f",$1/$2/$3}')"
    if [ "${MiB_Flag}" = "1" ]; then
        # MiB to MB
        ResultSpeed="$(echo "${TotalSpeed} ${maxtestcount} 1048576‬ 1000000" | awk '{printf "%.2f",$1/$2/$3*$4}')"
    else
        # 直接输出
        ResultSpeed="$(echo "${TotalSpeed} ${maxtestcount}" | awk '{printf "%.2f",$1/$2}')"
    fi
    # 1线程的测试结果写入临时变量,方便与后续的多线程变量做对比
    if [ "$1" = "1" ] && [ "$4" = "read" ]; then
        LBench_Result_MemoryReadSpeedSingle="${ResultSpeed}"
    elif [ "$1" = "1" ] &&[ "$4" = "write" ]; then
        LBench_Result_MemoryWriteSpeedSingle="${ResultSpeed}"
    fi
    if [ "${MultiThread_Flag}" = "1" ]; then
        # 如果是多线程测试,输出与1线程测试对比的倍率
        if [ "$1" -ge "2" ] && [ "$4" = "read" ]; then
            LBench_Result_MemoryReadSpeedMulti="${ResultSpeed}"
            local readmultiple="$(echo "${LBench_Result_MemoryReadSpeedMulti} ${LBench_Result_MemoryReadSpeedSingle}" | awk '{printf "%.2f", $1/$2}')"
            echo -e "\r ${Font_Yellow}$6:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_MemoryReadSpeedMulti}${Font_Suffix} ${Font_Yellow}MB/s${Font_Suffix} (${readmultiple} x)"
        elif [ "$1" -ge "2" ] && [ "$4" = "write" ]; then
            LBench_Result_MemoryWriteSpeedMulti="${ResultSpeed}"
            local writemultiple="$(echo "${LBench_Result_MemoryWriteSpeedMulti} ${LBench_Result_MemoryWriteSpeedSingle}" | awk '{printf "%.2f", $1/$2}')"
            echo -e "\r ${Font_Yellow}$6:${Font_Suffix}\t\t${Font_SkyBlue}${LBench_Result_MemoryWriteSpeedMulti}${Font_Suffix} ${Font_Yellow}MB/s${Font_Suffix} (${writemultiple} x)"
        fi
    else
        if [ "$4" = "read" ]; then
            echo -e "\r ${Font_Yellow}$6:${Font_Suffix}\t\t${Font_SkyBlue}${ResultSpeed}${Font_Suffix} ${Font_Yellow}MB/s${Font_Suffix}"
        elif [ "$4" = "write" ]; then
            echo -e "\r ${Font_Yellow}$6:${Font_Suffix}\t\t${Font_SkyBlue}${ResultSpeed}${Font_Suffix} ${Font_Yellow}MB/s${Font_Suffix}"
        fi
    fi
    # Fix
    if [ "$1" -ge "2" ] && [ "$4" = "write" ]; then
        echo -e " $6:\t${ResultSpeed} MB/s" >>${WorkDir}/SysBench/Memory/result.txt
    else
        echo -e " $6:\t\t${ResultSpeed} MB/s" >>${WorkDir}/SysBench/Memory/result.txt
    fi
    sleep 1
}

Function_SysBench_Memory_Fast() {
    mkdir -p ${WorkDir}/SysBench/Memory/ >/dev/null 2>&1
    echo -e "\n ${Font_Yellow}-> Memory Performance Test (Fast Mode, 1-Pass @ 5sec)${Font_Suffix}\n"
    echo -e "\n -> Memory Performance Test (Fast Mode, 1-Pass @ 5sec)\n" >>${WorkDir}/SysBench/Memory/result.txt
    Run_SysBench_Memory "1" "5" "1" "read" "seq" "1 Thread - Read Test "
    Run_SysBench_Memory "1" "5" "1" "write" "seq" "1 Thread - Write Test"
    # 完成FLAG
    LBench_Flag_FinishSysBenchMemoryFast="1"
    sleep 1
}

Function_SysBench_Memory_Full() {
    mkdir -p ${WorkDir}/SysBench/Memory/ >/dev/null 2>&1
    echo -e "\n ${Font_Yellow}-> Memory Performance Test (Standard Mode, 3-Pass @ 30sec)${Font_Suffix}\n"
    echo -e "\n -> Memory Performance Test (Standard Mode, 3-Pass @ 30sec)\n" >>${WorkDir}/SysBench/Memory/result.txt
    Run_SysBench_Memory "1" "30" "3" "read" "seq" "1 Thread - Read Test "
    Run_SysBench_Memory "1" "30" "3" "write" "seq" "1 Thread - Write Test"
    # 完成FLAG
    LBench_Flag_FinishSysBenchMemoryFull="1"
    sleep 1
}

# 生成结果文件
Function_GenerateResult() {
    echo -e "${Msg_Info}Please wait, collecting results ..."
    mkdir -p /tmp/ >/dev/null 2>&1
    mkdir -p ${WorkDir}/result >/dev/null 2>&1
    Function_GenerateResult_Header >/dev/null
    Function_GenerateResult_SystemInfo >/dev/null
    Function_GenerateResult_NetworkInfo >/dev/null
    Function_GenerateResult_MediaUnlockTest >/dev/null
    Function_GenerateResult_SysBench_CPUTest >/dev/null
    Function_GenerateResult_SysBench_MemoryTest >/dev/null
    Function_GenerateResult_DiskTest >/dev/null
    Function_GenerateResult_Speedtest >/dev/null
    Function_GenerateResult_BestTrace >/dev/null
    Function_GenerateResult_Spoofer >/dev/null
    Function_GenerateResult_Footer >/dev/null
    echo -e "${Msg_Info}Generating Report ..."
    local finalresultfile="${WorkDir}/result/finalresult.txt"
    sleep 0.2
    if [ -f "${WorkDir}/result/00-header.result" ]; then
        cat ${WorkDir}/result/00-header.result >>${WorkDir}/result/finalresult.txt
    fi
    sleep 0.2
    if [ -f "${WorkDir}/result/01-systeminfo.result" ]; then
        cat ${WorkDir}/result/01-systeminfo.result >>${WorkDir}/result/finalresult.txt
    fi
    sleep 0.2
    if [ -f "${WorkDir}/result/02-networkinfo.result" ]; then
        cat ${WorkDir}/result/02-networkinfo.result >>${WorkDir}/result/finalresult.txt
    fi
    if [ -f "${WorkDir}/result/03-mediaunlocktest.result" ]; then
        cat ${WorkDir}/result/03-mediaunlocktest.result >>${WorkDir}/result/finalresult.txt
    fi
    sleep 0.2
    if [ -f "${WorkDir}/result/04-cputest.result" ]; then
        cat ${WorkDir}/result/04-cputest.result >>${WorkDir}/result/finalresult.txt
    fi
    sleep 0.2
    if [ -f "${WorkDir}/result/05-memorytest.result" ]; then
        cat ${WorkDir}/result/05-memorytest.result >>${WorkDir}/result/finalresult.txt
    fi
    sleep 0.2
    if [ -f "${WorkDir}/result/06-disktest.result" ]; then
        cat ${WorkDir}/result/06-disktest.result >>${WorkDir}/result/finalresult.txt
    fi
    if [ -f "${WorkDir}/result/07-speedtest.result" ]; then
        cat ${WorkDir}/result/07-speedtest.result >>${WorkDir}/result/finalresult.txt
    fi
    sleep 0.2
    if [ -f "${WorkDir}/result/08-besttrace.result" ]; then
        cat ${WorkDir}/result/08-besttrace.result >>${WorkDir}/result/finalresult.txt
    fi
    sleep 0.2
    if [ -f "${WorkDir}/result/09-spoofer.result" ]; then
        cat ${WorkDir}/result/09-spoofer.result >>${WorkDir}/result/finalresult.txt
    fi
    sleep 0.2
    if [ -f "${WorkDir}/result/99-footer.result" ]; then
        cat ${WorkDir}/result/99-footer.result >>${WorkDir}/result/finalresult.txt
    fi
    sleep 0.2
    echo -e "${Msg_Info}Saving local Report ..."
    cp ${WorkDir}/result/finalresult.txt $HOME/LemonBench.Result.txt
    sleep 0.1
    echo -e "${Msg_Info}Generating Report URL ..."
    cat ${WorkDir}/result/finalresult.txt | PasteBin_Upload
}

Function_GenerateResult_Header() {
    sleep 0.1
    local rfile="${WorkDir}/result/00-header.result"
    echo -e " " >>$rfile
    echo -e " LemonBench Linux System Benchmark Utility Version ${BuildTime} " >>$rfile
    echo -e " " >>$rfile
    echo -e " Bench Start Time:\t${LBench_Result_BenchStartTime}" >>$rfile
    echo -e " Bench Finish Time:\t${LBench_Result_BenchFinishTime}" >>$rfile
    echo -e " Test Mode:\t\t${Global_TestModeTips}" >>$rfile
    echo -e " \n\n"
}

Function_GenerateResult_SystemInfo() {
    sleep 0.1
    local rfile="${WorkDir}/result/01-systeminfo.result"
    if [ "${LBench_Flag_FinishSystemInfo}" = "1" ]; then
        echo -e " \n -> System Information" >>$rfile
        echo -e " " >>$rfile
        echo -e " OS Release:\t\t${LBench_Result_OSReleaseFullName}" >>$rfile
        if [ "${Flag_DymanicCPUFreqDetected}" = "1" ]; then
            echo -e " CPU Model:\t\t${LBench_Result_CPUModelName}  ${LBench_Result_CPUFreqMinGHz}~${LBench_Result_CPUFreqMaxGHz} GHz" >>$rfile
        elif [ "${Flag_DymanicCPUFreqDetected}" = "0" ]; then
            echo -e " CPU Model:\t\t${LBench_Result_CPUModelName}  ${LBench_Result_CPUFreqGHz} GHz" >>$rfile
        fi
        echo -e " CPU Cache Size:\t${LBench_Result_CPUCacheSize}" >>$rfile
        if [ "${LBench_Result_CPUIsPhysical}" = "1" ]; then
            if [ "${LBench_Result_CPUPhysicalNumber}" -eq "1" ]; then
                echo -e " CPU Number:\t\t${LBench_Result_CPUPhysicalNumber} Physical CPU, ${LBench_Result_CPUCoreNumber} Cores, ${LBench_Result_CPUThreadNumber} Threads" >>$rfile
            elif [ "${LBench_Result_CPUPhysicalNumber}" -ge "2" ]; then
                echo -e " CPU Number:\t\t${LBench_Result_CPUPhysicalNumber} Physical CPUs, ${LBench_Result_CPUCoreNumber} Cores/CPU, ${LBench_Result_CPUSiblingsNumber} Thread)/CPU (Total ${LBench_Result_CPUTotalCoreNumber} Cores, ${LBench_Result_CPUProcessorNumber} Threads)" >>$rfile
            elif [ "${LBench_Result_CPUThreadNumber}" = "0" ] && [ "${LBench_Result_CPUProcessorNumber} " -ge "1" ]; then
                echo -e " CPU Number:\t\t${LBench_Result_CPUProcessorNumber} Cores" >>$rfile
            fi
            if [ "${LBench_Result_CPUVirtualization}" = "1" ]; then
                echo -e " VirtReady:\t\tYes (Based on ${LBench_Result_CPUVirtualizationType})" >>$rfile
            elif [ "${LBench_Result_CPUVirtualization}" = "2" ]; then
                echo -e " VirtReady:\t\tYes (Nested Virtualization)" >>$rfile
            else
                echo -e " VirtReady:\t\t${Font_SkyRed}No" >>$rfile
            fi
        elif [ "${Var_VirtType}" = "openvz" ]; then
            echo -e " CPU Number:\t\t${LBench_Result_CPUThreadNumber} vCPU (${LBench_Result_CPUCoreNumber} Host Core(s)/Thread(s))" >>$rfile
        else
            echo -e " CPU Number:\t\t${LBench_Result_CPUThreadNumber} vCPU" >>$rfile
        fi
        echo -e " Virt Type:\t\t${LBench_Result_VirtType}" >>$rfile
        echo -e " Memory Usage:\t\t${LBench_Result_Memory}" >>$rfile
        echo -e " Swap Usage:\t\t${LBench_Result_Swap}" >>$rfile
        if [ "${LBench_Result_DiskUsed_KB}" -lt "1000000" ]; then
            LBench_Result_Disk="${LBench_Result_DiskUsed_MB} MB / ${LBench_Result_DiskTotal_MB} MB"
            echo -e " Disk Usage:\t\t${LBench_Result_DiskUsed_MB} MB / ${LBench_Result_DiskTotal_MB} MB" >>$rfile
        elif [ "${LBench_Result_DiskUsed_KB}" -lt "1000000" ] && [ "${LBench_Result_DiskTotal_KB}" -lt "1000000000" ]; then
            LBench_Result_Disk="${LBench_Result_DiskUsed_MB} MB / ${LBench_Result_DiskTotal_GB} GB"
            echo -e " Disk Usage:\t\t${LBench_Result_DiskUsed_MB} MB / ${LBench_Result_DiskTotal_GB} GB" >>$rfile
        elif [ "${LBench_Result_DiskUsed_KB}" -lt "1000000000" ] && [ "${LBench_Result_DiskTotal_KB}" -lt "1000000000" ]; then
            LBench_Result_Disk="${LBench_Result_DiskUsed_GB} GB / ${LBench_Result_DiskTotal_GB} GB"
            echo -e " Disk Usage:\t\t${LBench_Result_DiskUsed_GB} GB / ${LBench_Result_DiskTotal_GB} GB" >>$rfile
        elif [ "${LBench_Result_DiskUsed_KB}" -lt "1000000000" ] && [ "${LBench_Result_DiskTotal_KB}" -ge "1000000000" ]; then
            LBench_Result_Disk="${LBench_Result_DiskUsed_GB} GB / ${LBench_Result_DiskTotal_TB} TB"
            echo -e " Disk Usage:\t\t${LBench_Result_DiskUsed_GB} GB / ${LBench_Result_DiskTotal_TB} TB" >>$rfile
        else
            LBench_Result_Disk="${LBench_Result_DiskUsed_TB} TB / ${LBench_Result_DiskTotal_TB} TB"
            echo -e " Disk Usage:\t\t${LBench_Result_DiskUsed_TB} TB / ${LBench_Result_DiskTotal_TB} TB" >>$rfile
        fi
        echo -e " Boot Device:\t\t${LBench_Result_DiskRootPath}" >>$rfile
        echo -e " Load (1/5/15min):\t${LBench_Result_LoadAverage_1min} ${LBench_Result_LoadAverage_5min} ${LBench_Result_LoadAverage_15min} " >>$rfile
        echo -e " CPU Usage:\t\t${LBench_Result_CPUStat_UsedAll}% used, ${LBench_Result_CPUStat_iowait}% iowait, ${LBench_Result_CPUStat_steal}% steal" >>$rfile
        echo -e " Kernel Version:\t${LBench_Result_KernelVersion}" >>$rfile
        echo -e " Network CC Method:\t${LBench_Result_NetworkCCMethod}" >>$rfile
    fi
}

Function_GenerateResult_NetworkInfo() {
    sleep 0.1
    if [ "${LBench_Flag_FinishNetworkInfo}" = "1" ]; then
        local rfile="${WorkDir}/result/02-networkinfo.result"
        echo -e "\n -> Network Information\n" >>$rfile
        if [ "${LBench_Result_NetworkStat}" = "ipv4only" ] || [ "${LBench_Result_NetworkStat}" = "dualstack" ]; then
            if [ "${IPAPI_IPV4_ip}" != "" ]; then
                local IPAPI_IPV4_ip_masked="$(echo ${IPAPI_IPV4_ip} | awk -F'.' '{print $1"."$2."."$3".*"}')"
                echo -e " IPV4 - IP Address:\t[${IPAPI_IPV4_country_code}] ${IPAPI_IPV4_ip_masked}" >>$rfile
                echo -e " IPV4 - ASN Info:\t${IPAPI_IPV4_asn} (${IPAPI_IPV4_organization})" >>$rfile
                echo -e " IPV4 - Region:\t\t${IPAPI_IPV4_location}" >>$rfile
            else
                echo -e " IPV6 - IP Address:\tError: API Query Failed" >>$rfile
            fi
        fi
        if [ "${LBench_Result_NetworkStat}" = "ipv6only" ] || [ "${LBench_Result_NetworkStat}" = "dualstack" ]; then
            if [ "${IPAPI_IPV6_ip}" != "" ]; then
                local IPAPI_IPV6_IP_Masked="$(echo ${IPAPI_IPV6_ip} | sed "s/[0-9a-f]\{1,4\}.$/*/g")"
                echo -e " IPV6 - IP Address:\t[${IPAPI_IPV6_country_code}] ${IPAPI_IPV6_IP_Masked}" >>$rfile
                echo -e " IPV6 - ASN Info:\t${IPAPI_IPV6_asn} (${IPAPI_IPV6_organization})" >>$rfile
                echo -e " IPV6 - Region:\t\t${IPAPI_IPV6_location}" >>$rfile
            else
                echo -e " IPV6 - IP Address:\tError: API Query Failed" >>$rfile
            fi
        fi
    fi
}

Function_GenerateResult_MediaUnlockTest() {
    sleep 0.1
    if [ "${LBench_Flag_FinishMediaUnlockTest}" = "1" ]; then
        local rfile="${WorkDir}/result/03-mediaunlocktest.result"
        echo -e "\n -> Media Unlock Test\n" >>$rfile
        # HBO Now
        echo -e " HBO Now:\t\t\t\t${LemonBench_Result_MediaUnlockTest_HBONow}" >>$rfile
        # 动画疯
        echo -e " Bahamut Anime:\t\t\t\t${LemonBench_Result_MediaUnlockTest_BahamutAnime}" >>$rfile
        # Abema.TV
        echo -e " Abema.TV:\t\t\t\t${LemonBench_Result_MediaUnlockTest_AbemaTV_IPTest}" >>$rfile
        # Princess Connect Re:Dive 日服
        echo -e " Princess Connect Re:Dive Japan:\t${LemonBench_Result_MediaUnlockTest_PCRJP}" >>$rfile
        # 爱奇艺台湾站
        # echo -e " IQiYi Taiwan (Beta):\t\t\t${LemonBench_Result_MediaUnlockTest_IQiYi_Taiwan}" >>$rfile
        # BBC
        echo -e " BBC:\t\t\t\t\t${LemonBench_Result_MediaUnlockTest_BBC}" >>$rfile
        # 哔哩哔哩大陆限定
        echo -e " Bilibili China Mainland Only:\t\t${LemonBench_Result_MediaUnlockTest_ChinaMainland}" >>$rfile
        # 哔哩哔哩港澳台
        echo -e " Bilibili Hongkong/Macau/Taiwan:\t${LemonBench_Result_MediaUnlockTest_BilibiliHKMCTW}" >>$rfile
        # 哔哩哔哩台湾限定
        echo -e " Bilibili Taiwan Only:\t\t\t${LemonBench_Result_MediaUnlockTest_BilibiliTW}" >>$rfile
    fi
}

Function_GenerateResult_SysBench_CPUTest() {
    sleep 0.1
    if [ -f "${WorkDir}/SysBench/CPU/result.txt" ]; then
        cp -f ${WorkDir}/SysBench/CPU/result.txt ${WorkDir}/result/04-cputest.result
    fi
}

Function_GenerateResult_SysBench_MemoryTest() {
    sleep 0.1
    if [ -f "${WorkDir}/SysBench/Memory/result.txt" ]; then
        cp -f ${WorkDir}/SysBench/Memory/result.txt ${WorkDir}/result/05-memorytest.result
    fi
}

Function_GenerateResult_DiskTest() {
    sleep 0.1
    if [ -f "${WorkDir}/DiskTest/result.txt" ]; then
        cp -f ${WorkDir}/DiskTest/result.txt ${WorkDir}/result/06-disktest.result
    fi
}

Function_GenerateResult_Speedtest() {
    sleep 0.1
    if [ -f "${WorkDir}/Speedtest/result.txt" ]; then
        cp -f ${WorkDir}/Speedtest/result.txt ${WorkDir}/result/07-speedtest.result
    fi
}

Function_GenerateResult_BestTrace() {
    sleep 0.1
    if [ -f "${WorkDir}/BestTrace/result.txt" ]; then
        cp -f ${WorkDir}/BestTrace/result.txt ${WorkDir}/result/08-besttrace.result
    fi
}

Function_GenerateResult_Spoofer() {
    sleep 0.1
    if [ -f "${WorkDir}/Spoofer/result.txt" ]; then
        cp -f ${WorkDir}/Spoofer/result.txt ${WorkDir}/result/09-spoofer.result
    fi
}

Function_GenerateResult_Footer() {
    sleep 0.1
    local rfile="${WorkDir}/result/99-footer.result"
    echo -e "\nGenerated by LemonBench on $(date -u "+%Y-%m-%dT%H:%M:%SZ") Version ${BuildTime}, Hosted by DMIT.IO\n" >>$rfile
    # 恰饭时间!(雾
    echo -e "[AD] DMIT.IO 洛杉矶 CN2 GIA VPS, 高性能大带宽保障,做站理想之选!\n购买传送门: http://ilemonra.in/DMIT" >>$rfile
    echo -e "[AD] MoeCloud 洛杉矶三网 CN2GIA VPS,1Gbps高速端口,晚高峰不惧拥堵,24小时体验飞一样的感觉!仅需59元/月起,享受7天退款保障!\n购买传送门:http://ilemonra.in/MoeCloudLACN2Promo" >>$rfile
    echo -e " \n"  >>$rfile
}

# =============== 检查 Virt-what 组件 ===============
Check_Virtwhat() {
    if [ ! -f "/usr/sbin/virt-what" ]; then
        SystemInfo_GetOSRelease
        if [ "${Var_OSRelease}" = "centos" ] || [ "${Var_OSRelease}" = "rhel" ]; then
            echo -e "${Msg_Warning}Virt-What Module not found, Installing ..."
            yum -y install virt-what
        elif [ "${Var_OSRelease}" = "ubuntu" ] || [ "${Var_OSRelease}" = "debian" ]; then
            echo -e "${Msg_Warning}Virt-What Module not found, Installing ..."
            apt-get update
            apt-get install -y virt-what dmidecode
        elif [ "${Var_OSRelease}" = "fedora" ]; then
            echo -e "${Msg_Warning}Virt-What Module not found, Installing ..."
            dnf -y install virt-what
        elif [ "${Var_OSRelease}" = "alpinelinux" ]; then
            echo -e "${Msg_Warning}Virt-What Module not found, Installing ..."
            apk update
            apk add virt-what
        else
            echo -e "${Msg_Warning}Virt-What Module not found, but we could not find the os's release ..."
        fi
    fi
    # 二次检测
    if [ ! -f "/usr/sbin/virt-what" ]; then
        echo -e "Virt-What Moudle install Failure! Try Restart Bench or Manually install it! (/usr/sbin/virt-what)"
        exit 1
    fi
}

# =============== 检查 Speedtest 组件 ===============
Check_Speedtest() {
    if [ -f "/usr/local/lemonbench/bin/speedtest" ]; then
        chmod +x /usr/local/lemonbench/bin/speedtest >/dev/null 2>&1
        /usr/local/lemonbench/bin/speedtest --version >/dev/null 2>&1
        if [ "$?" = "0" ]; then
            return 0
        else
            rm -f /usr/local/lemonbench/bin/speedtest
            Check_Speedtest_GetComponent
        fi
    else
        Check_Speedtest_GetComponent
    fi
}

Check_Speedtest_GetComponent() {
    SystemInfo_GetOSRelease
    SystemInfo_GetSystemBit
    if [ "${LBench_Result_SystemBit_Full}" = "amd64" ]; then
        local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/Speedtest/1.0.0.2/speedtest-amd64.tar.gz"
    elif [ "${LBench_Result_SystemBit_Full}" = "i386" ]; then
        local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/Speedtest/1.0.0.2/speedtest-i386.tar.gz"
    elif [ "${LBench_Result_SystemBit_Full}" = "arm" ]; then
        local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/Speedtest/1.0.0.2/speedtest-arm.tar.gz"
    else
        local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/Speedtest/1.0.0.2/speedtest-i386.tar.gz"
    fi
    if [ "${Var_OSRelease}" = "centos" ] || [ "${Var_OSRelease}" = "rhel" ]; then
        echo -e "${Msg_Warning}Speedtest Module not found, Installing ..."
        echo -e "${Msg_Info}Installing Dependency ..."
        yum makecache fast
        yum -y install curl
        echo -e "${Msg_Info}Installing Speedtest Module ..."
        mkdir -p ${WorkDir}/.DownTmp >/dev/null 2>&1
        pushd ${WorkDir}/.DownTmp >/dev/null
        curl --user-agent "${UA_LemonBench}" ${DownloadSrc} -o ${WorkDir}/.DownTmp/speedtest.tar.gz
        tar xf ${WorkDir}/.DownTmp/speedtest.tar.gz
        mkdir -p /usr/local/lemonbench/bin/ >/dev/null 2>&1
        mv ${WorkDir}/.DownTmp/speedtest /usr/local/lemonbench/bin/
        chmod +x /usr/local/lemonbench/bin/speedtest
        echo -e "${Msg_Info}Cleaning up ..."
        popd >/dev/null
        rm -rf ${WorkDir}/.DownTmp
    elif [ "${Var_OSRelease}" = "ubuntu" ] || [ "${Var_OSRelease}" = "debian" ]; then
        echo -e "${Msg_Warning}Speedtest Module not found, Installing ..."
        echo -e "${Msg_Info}Installing Dependency ..."
        apt-get update
        apt-get --no-install-recommends -y install curl
        echo -e "${Msg_Info}Installing Speedtest Module ..."
        mkdir -p ${WorkDir}/.DownTmp >/dev/null 2>&1
        pushd ${WorkDir}/.DownTmp >/dev/null
        curl --user-agent "${UA_LemonBench}" ${DownloadSrc} -o ${WorkDir}/.DownTmp/speedtest.tar.gz
        tar xf ${WorkDir}/.DownTmp/speedtest.tar.gz
        mkdir -p /usr/local/lemonbench/bin/ >/dev/null 2>&1
        mv ${WorkDir}/.DownTmp/speedtest /usr/local/lemonbench/bin/
        chmod +x /usr/local/lemonbench/bin/speedtest
        echo -e "${Msg_Info}Cleaning up ..."
        popd >/dev/null
        rm -rf ${WorkDir}/.DownTmp
    elif [ "${Var_OSRelease}" = "fedora" ]; then
        echo -e "${Msg_Warning}Speedtest Module not found, Installing ..."
        echo -e "${Msg_Info}Installing Dependency ..."
        dnf -y install curl
        echo -e "${Msg_Info}Installing Speedtest Module ..."
        mkdir -p ${WorkDir}/.DownTmp >/dev/null 2>&1
        pushd ${WorkDir}/.DownTmp >/dev/null
        curl --user-agent "${UA_LemonBench}" ${DownloadSrc} -o ${WorkDir}/.DownTmp/speedtest.tar.gz
        tar xf ${WorkDir}/.DownTmp/speedtest.tar.gz
        mkdir -p /usr/local/lemonbench/bin/ >/dev/null 2>&1
        mv ${WorkDir}/.DownTmp/speedtest /usr/local/lemonbench/bin/
        chmod +x /usr/local/lemonbench/bin/speedtest
        echo -e "${Msg_Info}Cleaning up ..."
        popd >/dev/null
        rm -rf ${WorkDir}/.DownTmp
    elif [ "${Var_OSRelease}" = "alpinelinux" ]; then
        echo -e "${Msg_Warning}Speedtest Module not found, Installing ..."
        echo -e "${Msg_Info}Installing Dependency ..."
        apk update
        apk add curl
        echo -e "${Msg_Info}Installing Speedtest Module ..."
        mkdir -p ${WorkDir}/.DownTmp >/dev/null 2>&1
        pushd ${WorkDir}/.DownTmp >/dev/null
        curl --user-agent "${UA_LemonBench}" ${DownloadSrc} -o ${WorkDir}/.DownTmp/speedtest.tar.gz
        tar xf ${WorkDir}/.DownTmp/speedtest.tar.gz
        mkdir -p /usr/local/lemonbench/bin/ >/dev/null 2>&1
        mv ${WorkDir}/.DownTmp/speedtest /usr/local/lemonbench/bin/
        chmod +x /usr/local/lemonbench/bin/speedtest
        echo -e "${Msg_Info}Cleaning up ..."
        popd >/dev/null
        rm -rf ${WorkDir}/.DownTmp
    else
        echo -e "${Msg_Warning}Speedtest Module not found, trying direct download ..."
        mkdir -p ${WorkDir}/.DownTmp >/dev/null 2>&1
        pushd ${WorkDir}/.DownTmp >/dev/null
        curl --user-agent "${UA_LemonBench}" ${DownloadSrc} -o ${WorkDir}/.DownTmp/speedtest.tar.gz
        tar xf ${WorkDir}/.DownTmp/speedtest.tar.gz
        mkdir -p /usr/local/lemonbench/bin/ >/dev/null 2>&1
        mv ${WorkDir}/.DownTmp/speedtest /usr/local/lemonbench/bin/
        chmod +x /usr/local/lemonbench/bin/speedtest
        echo -e "${Msg_Info}Cleaning up ..."
        popd >/dev/null
        rm -rf ${WorkDir}/.DownTmp
    fi
    /usr/local/lemonbench/bin/speedtest --version >/dev/null 2>&1
    if [ "$?" != "0" ]; then
        echo -e "Speedtest Moudle install Failure! Try Restart Bench or Manually install it!"
        exit 1
    fi
}

# =============== 检查 BestTrace 组件 ===============
Check_BestTrace() {
    if [ ! -f "/usr/local/lemonbench/bin/besttrace" ]; then
        SystemInfo_GetOSRelease
        SystemInfo_GetSystemBit
        if [ "${LBench_Result_SystemBit_Full}" = "amd64" ]; then
            local BinaryName="besttrace64"
            local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/BestTrace/besttrace64.tar.gz"
            # local DownloadSrc="https://raw.githubusercontent.com/LemonBench/LemonBench/master/Resources/BestTrace/besttrace64.tar.gz"
        elif [ "${LBench_Result_SystemBit_Full}" = "i386" ]; then
            local BinaryName="besttrace32"
            local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/BestTrace/besttrace32.tar.gz"
            # local DownloadSrc="https://raw.githubusercontent.com/LemonBench/LemonBench/master/Resources/BestTrace/besttrace32.tar.gz"
        elif [ "${LBench_Result_SystemBit_Full}" = "arm" ]; then
            local BinaryName="besttracearm"
            local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/BestTrace/besttracearm.tar.gz"
            # local DownloadSrc="https://raw.githubusercontent.com/LemonBench/LemonBench/master/Resources/BestTrace/besttracearm.tar.gz"
        else
            local BinaryName="besttrace32"
            local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/BestTrace/besttrace32.tar.gz"
            # local DownloadSrc="https://raw.githubusercontent.com/LemonBench/LemonBench/master/Resources/BestTrace/besttrace32.tar.gz"
        fi
        mkdir -p ${WorkDir}/ >/dev/null 2>&1
        mkdir -p /usr/local/lemonbench/bin/ >/dev/null 2>&1
        if [ "${Var_OSRelease}" = "centos" ] || [ "${Var_OSRelease}" = "rhel" ]; then
            echo -e "${Msg_Warning}BestTrace Module not found, Installing ..."
            echo -e "${Msg_Info}Installing Dependency ..."
            yum -y install curl unzip
            echo -e "${Msg_Info}Downloading BestTrace Module ..."
            curl --user-agent "${UA_LemonBench}" ${DownloadSrc} -o ${WorkDir}/besttrace.tar.gz
            echo -e "${Msg_Info}Installing BestTrace Module ..."
            pushd ${WorkDir} >/dev/null
            tar xf besttrace.tar.gz
            mv ${BinaryName} /usr/local/lemonbench/bin/besttrace
            chmod +x /usr/local/lemonbench/bin/besttrace
            popd >/dev/null
            echo -e "${Msg_Info}Cleaning up ..."
            rm -rf ${WorkDir}/besttrace.tar.gz
        elif [ "${Var_OSRelease}" = "ubuntu" ] || [ "${Var_OSRelease}" = "debian" ]; then
            echo -e "${Msg_Warning}BestTrace Module not found, Installing ..."
            echo -e "${Msg_Info}Installing Dependency ..."
            apt-get update
            apt-get --no-install-recommends -y install wget unzip curl ca-certificates
            echo -e "${Msg_Info}Downloading BestTrace Module ..."
            curl --user-agent "${UA_LemonBench}" ${DownloadSrc} -o ${WorkDir}/besttrace.tar.gz
            echo -e "${Msg_Info}Installing BestTrace Module ..."
            pushd ${WorkDir} >/dev/null
            tar xf besttrace.tar.gz
            mv ${BinaryName} /usr/local/lemonbench/bin/besttrace
            chmod +x /usr/local/lemonbench/bin/besttrace
            popd >/dev/null
            echo -e "${Msg_Info}Cleaning up ..."
            rm -rf ${WorkDir}/besttrace.tar.gz
        elif [ "${Var_OSRelease}" = "fedora" ]; then
            echo -e "${Msg_Warning}BestTrace Module not found, Installing ..."
            echo -e "${Msg_Info}Installing Dependency ..."
            dnf -y install wget unzip curl
            echo -e "${Msg_Info}Downloading BestTrace Module ..."
            curl  --user-agent "${UA_LemonBench}" ${DownloadSrc} -o ${WorkDir}/besttrace.tar.gz
            echo -e "${Msg_Info}Installing BestTrace Module ..."
            pushd ${WorkDir} >/dev/null
            tar xf besttrace.tar.gz
            mv ${BinaryName} /usr/local/lemonbench/bin/besttrace
            chmod +x /usr/local/lemonbench/bin/besttrace
            popd >/dev/null
            echo -e "${Msg_Info}Cleaning up ..."
            rm -rf ${WorkDir}/besttrace.tar.gz
        elif [ "${Var_OSRelease}" = "alpinelinux" ]; then
            echo -e "${Msg_Warning}BestTrace Module not found, Installing ..."
            echo -e "${Msg_Info}Installing Dependency ..."
            apk update
            apk add wget unzip curl
            echo -e "${Msg_Info}Downloading BestTrace Module ..."
            curl --user-agent "${UA_LemonBench}" ${DownloadSrc} -o ${WorkDir}/besttrace.tar.gz
            echo -e "${Msg_Info}Installing BestTrace Module ..."
            pushd ${WorkDir} >/dev/null
            tar xf besttrace.tar.gz
            mv ${BinaryName} /usr/local/lemonbench/bin/besttrace
            chmod +x /usr/local/lemonbench/bin/besttrace
            popd >/dev/null
            echo -e "${Msg_Info}Cleaning up ..."
            rm -rf ${WorkDir}/besttrace.tar.gz
        else
            echo -e "${Msg_Warning}BestTrace Module not found, but we could not find the os's release ..."
        fi
    fi
    # 二次检测
    if [ ! -f "/usr/local/lemonbench/bin/besttrace" ]; then
        echo -e "BestTrace Moudle install Failure! Try Restart Bench or Manually install it! (/usr/local/lemonbench/bin/besttrace)"
        exit 1
    fi
}

# =============== 检查 JSON Query 组件 ===============
Check_JSONQuery() {
    if [ ! -f "/usr/bin/jq" ]; then
        SystemInfo_GetOSRelease
        SystemInfo_GetSystemBit
        if [ "${LBench_Result_SystemBit_Short}" = "64" ]; then
            local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/JSONQuery/jq-amd64.tar.gz"
            # local DownloadSrc="https://raw.githubusercontent.com/LemonBench/LemonBench/master/Resources/JSONQuery/jq-amd64.tar.gz"
            # local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/jq/1.6/amd64/jq.tar.gz"
        elif [ "${LBench_Result_SystemBit_Short}" = "32" ]; then
            local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/JSONQuery/jq-i386.tar.gz"
            # local DownloadSrc="https://raw.githubusercontent.com/LemonBench/LemonBench/master/Resources/JSONQuery/jq-i386.tar.gz"
            # local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/jq/1.6/i386/jq.tar.gz"
        else
            local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/JSONQuery/jq-i386.tar.gz"
            # local DownloadSrc="https://raw.githubusercontent.com/LemonBench/LemonBench/master/Resources/JSONQuery/jq-i386.tar.gz"
            # local DownloadSrc="https://raindrop.ilemonrain.com/LemonBench/include/jq/1.6/i386/jq.tar.gz"
        fi
        mkdir -p ${WorkDir}/
        if [ "${Var_OSRelease}" = "centos" ] || [ "${Var_OSRelease}" = "rhel" ]; then
            echo -e "${Msg_Warning}JSON Query Module not found, Installing ..."
            echo -e "${Msg_Info}Installing Dependency ..."
            yum install -y epel-release
            yum install -y jq
        elif [ "${Var_OSRelease}" = "ubuntu" ] || [ "${Var_OSRelease}" = "debian" ]; then
            echo -e "${Msg_Warning}JSON Query Module not found, Installing ..."
            echo -e "${Msg_Info}Installing Dependency ..."
            apt-get update
            apt-get install -y jq
        elif [ "${Var_OSRelease}" = "fedora" ]; then
            echo -e "${Msg_Warning}JSON Query Module not found, Installing ..."
            echo -e "${Msg_Info}Installing Dependency ..."
            dnf install -y jq
        elif [ "${Var_OSRelease}" = "alpinelinux" ]; then
            echo -e "${Msg_Warning}JSON Query Module not found, Installing ..."
            echo -e "${Msg_Info}Installing Dependency ..."
            apk update
            apk add jq
        else
            echo -e "${Msg_Warning}JSON Query Module not found, Installing ..."
            echo -e "${Msg_Info}Installing Dependency ..."
            apk update
            apk add wget unzip curl
            echo -e "${Msg_Info}Downloading Json Query Module ..."
            curl --user-agent "${UA_LemonBench}" ${DownloadSrc} -o ${WorkDir}/jq.tar.gz
            echo -e "${Msg_Info}Installing JSON Query Module ..."
            tar xvf ${WorkDir}/jq.tar.gz
            mv ${WorkDir}/jq /usr/bin/jq
            chmod +x /usr/bin/jq
            echo -e "${Msg_Info}Cleaning up ..."
            rm -rf ${WorkDir}/jq.tar.gz
        fi
    fi
    # 二次检测
    if [ ! -f "/usr/bin/jq" ]; then
        echo -e "JSON Query Moudle install Failure! Try Restart Bench or Manually install it! (/usr/bin/jq)"
        exit 1
    fi
}

# =============== 检查 Spoofer 组件 ===============
Check_Spoofer() {
    # 如果是快速模式启动, 则跳过Spoofer相关检查及安装
    if [ "${Global_TestMode}" = "fast" ] || [ "${Global_TestMode}" = "full" ]; then
        return 0
    fi
    # 检测是否存在已安装的Spoofer模块
    if [ -f "/usr/local/bin/spoofer-prober" ]; then
        return 0
    else
        echo -e "${Msg_Warning}Spoof Module not found, Installing ..."
        Check_Spoofer_PreBuild
    fi
    # 如果预编译安装失败了, 则开始编译安装
    if [ ! -f "/usr/local/bin/spoofer-prober" ]; then
        echo -e "${Msg_Warning}Spoof Module with Pre-Build Failed, trying complie ..."
        Check_Spoofer_InstantBuild
    fi
    # 如果编译安装仍然失败, 则停止运行
    if [ ! -f "/usr/local/bin/spoofer-prober" ]; then
        echo -e "${Msg_Error}Spoofer Moudle install Failure! Try Restart Bench or Manually install it! (/usr/local/bin/spoofer-prober)"
        exit 1
    fi
}

Check_Spoofer_PreBuild() {
    # 获取系统信息
    SystemInfo_GetOSRelease
    SystemInfo_GetSystemBit
    # 判断CentOS分支
    if [ "${Var_OSRelease}" = "centos" ] || [ "${Var_OSRelease}" = "rhel" ]; then
        local SysRel="centos"
        # 判断系统位数
        if [ "${LBench_Result_SystemBit}" = "i386" ]; then
            local SysBit="i386"
        elif [ "${LBench_Result_SystemBit}" = "amd64" ]; then
            local SysBit="amd64"
        else
            local SysBit="unknown"
        fi
        # 判断版本号
        if [ "${Var_CentOSELRepoVersion}" = "6" ]; then
            local SysVer="6"
        elif [ "${Var_CentOSELRepoVersion}" = "7" ]; then
            local SysVer="7"
        else
            local SysVer="unknown"
        fi
    # 判断Debian分支
    elif [ "${Var_OSRelease}" = "debian" ]; then
        local SysRel="debian"
        # 判断系统位数
        if [ "${LBench_Result_SystemBit}" = "i386" ]; then
            local SysBit="i386"
        elif [ "${LBench_Result_SystemBit}" = "amd64" ]; then
            local SysBit="amd64"
        else
            local SysBit="unknown"
        fi
        # 判断版本号
        if [ "${Var_OSReleaseVersion_Short}" = "8" ]; then
            local SysVer="8"
        elif [ "${Var_OSReleaseVersion_Short}" = "9" ]; then
            local SysVer="9"
        else
            local SysVer="unknown"
        fi
    # 判断Ubuntu分支
    elif [ "${Var_OSRelease}" = "ubuntu" ]; then
        local SysRel="ubuntu"
        # 判断系统位数
        if [ "${LBench_Result_SystemBit}" = "i386" ]; then
            local SysBit="i386"
        elif [ "${LBench_Result_SystemBit}" = "amd64" ]; then
            local SysBit="amd64"
        else
            local SysBit="unknown"
        fi
        # 判断版本号
        if [ "${Var_OSReleaseVersion_Short}" = "14.04" ]; then
            local SysVer="14.04"
        elif [ "${Var_OSReleaseVersion_Short}" = "16.04" ]; then
            local SysVer="16.04"
        elif [ "${Var_OSReleaseVersion_Short}" = "18.04" ]; then
            local SysVer="18.04"
        elif [ "${Var_OSReleaseVersion_Short}" = "18.10" ]; then
            local SysVer="18.10"
        elif [ "${Var_OSReleaseVersion_Short}" = "19.04" ]; then
            local SysVer="19.04"
        else
            local SysVer="unknown"
        fi
    fi
    if [ "${SysBit}" = "i386" ] && [ "${SysVer}" != "unknown" ]; then
        echo -e "${Msg_Warning}Pre-Build current does not support 32-bit system, starting compile process ..."
        Check_Spoofer_InstantBuild
    fi
    if [ "${SysBit}" = "unknown" ] || [ "${SysVer}" = "unknown" ]; then
        echo -e "${Msg_Warning}无法确认当前系统的版本号及位数, 或目前暂不支持预编译组件!"
    else
        if [ "${SysRel}" = "centos" ]; then
            echo -e "${Msg_Info}Release Detected: ${SysRel} ${SysVer} ${SysBit}"
            echo -e "${Msg_Info}Installing Dependency"
            yum install -y epel-release
            yum install -y protobuf-devel libpcap-devel openssl-devel traceroute wget curl
            local Spoofer_Version="$(curl  --user-agent "${UA_LemonBench}" -fskSL https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/latest_version)"
            echo -e "${Msg_Info}Downloading Spoof Module (Version ${Spoofer_Version}) ..."
            mkdir -p /tmp/_LBench/src/
            wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/spoofer-prober.gz https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/${Spoofer_Version}/${SysRel}/${SysVer}/${SysBit}/spoofer-prober.gz
            echo -e "${Msg_Info}Installing Spoof Module ..."
            tar xf /tmp/_LBench/src/spoofer-prober.gz
            cp -f /tmp/_LBench/src/spoofer-prober /usr/local/bin/spoofer-prober
            chmod +x /usr/local/bin/spoofer-prober
            echo -e "${Msg_Info}Cleaning up ..."
            rm -f /tmp/_LBench/src/spoofer-prober.tar.gz
            rm -f /tmp/_LBench/src/spoofer-prober
        elif [ "${SysRel}" = "ubuntu" ] || [ "${SysRel}" = "debian" ]; then
            echo -e "${Msg_Info}Release Detected: ${SysRel} ${SysVer} ${SysBit}"
            echo -e "${Msg_Info}Installing Dependency"
            apt-get update
            apt-get install --no-install-recommends -y ca-certificates libprotobuf-dev libpcap-dev traceroute wget curl
            local Spoofer_Version="$(curl  --user-agent "${UA_LemonBench}" -fskSL https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/latest_version)"
            echo -e "${Msg_Info}Downloading Spoof Module (Version ${Spoofer_Version}) ..."
            mkdir -p /tmp/_LBench/src/
            wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/spoofer-prober.gz https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/${Spoofer_Version}/${SysRel}/${SysVer}/${SysBit}/spoofer-prober.gz
            echo -e "${Msg_Info}Installing Spoof Module ..."
            tar xf /tmp/_LBench/src/spoofer-prober.gz
            cp -f /tmp/_LBench/src/spoofer-prober /usr/local/bin/spoofer-prober
            chmod +x /usr/local/bin/spoofer-prober
            echo -e "${Msg_Info}Cleaning up ..."
            rm -f /tmp/_LBench/src/spoofer-prober.tar.gz
            rm -f /tmp/_LBench/src/spoofer-prober
        else
            echo -e "${Msg_Warning}We cannot figure out the system bit or os release, so we cannot use the pre-build module!"
        fi
    fi
}

Check_Spoofer_InstantBuild() {
    SystemInfo_GetOSRelease
    SystemInfo_GetCPUInfo
    if [ "${Var_OSRelease}" = "centos" ] || [ "${Var_OSRelease}" = "rhel" ]; then
        echo -e "${Msg_Info}Release Detected: ${Var_OSRelease}"
        echo -e "${Msg_Info}Preparing compile enviorment ..."
        yum install -y epel-release
        yum install -y wget curl make gcc gcc-c++ traceroute openssl-devel protobuf-devel bison flex libpcap-devel
        local Spoofer_Version="$(curl  --user-agent "${UA_LemonBench}"  -fskSL https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/latest_version)"
        echo -e "${Msg_Info}Downloading Source code (Version ${Spoofer_Version})..."
        mkdir -p /tmp/_LBench/src/
        wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/spoofer.tar.gz https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/${Spoofer_Version}/spoofer.tar.gz
        echo -e "${Msg_Info}Compiling Spoof Module ..."
        cd /tmp/_LBench/src/
        tar xvf spoofer.tar.gz && cd spoofer-"${Spoofer_Version}"
        # 测试性补丁
        wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/configure.patch https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/${Spoofer_Version}/patch/configure.patch
        patch -p0 configure /tmp/_LBench/src/configure.patch
        ./configure && make -j ${LBench_Result_CPUThreadNumber}
        cp prober/spoofer-prober /usr/local/bin/spoofer-prober
        echo -e "${Msg_Info}Cleaning up ..."
        cd /tmp && rm -rf /tmp/_LBench/src/spoofer*
    elif [ "${Var_OSRelease}" = "ubuntu" ] || [ "${Var_OSRelease}" = "debian" ]; then
        echo -e "${Msg_Info}Release Detected: ${Var_OSRelease}"
        echo -e "${Msg_Info}Preparing compile enviorment ..."
        apt-get update
        apt-get install -y --no-install-recommends wget curl gcc g++ make traceroute protobuf-compiler libpcap-dev libprotobuf-dev openssl libssl-dev ca-certificates
        local Spoofer_Version="$(curl --user-agent "${UA_LemonBench}" -fskSL https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/latest_version)"
        echo -e "${Msg_Info}Downloading Source code (Version ${Spoofer_Version})..."
        mkdir -p /tmp/_LBench/src/
        wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/spoofer.tar.gz https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/${Spoofer_Version}/spoofer.tar.gz
        echo -e "${Msg_Info}Compiling Spoof Module ..."
        cd /tmp/_LBench/src/
        tar xvf spoofer.tar.gz && cd spoofer-"${Spoofer_Version}"
        # 测试性补丁
        wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/configure.patch https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/${Spoofer_Version}/patch/configure.patch
        patch -p0 configure /tmp/_LBench/src/configure.patch
        ./configure && make -j ${LBench_Result_CPUThreadNumber}
        cp prober/spoofer-prober /usr/local/bin/spoofer-prober
        echo -e "${Msg_Info}Cleaning up ..."
        cd /tmp && rm -rf /tmp/_LBench/src/spoofer*
    elif [ "${Var_OSRelease}" = "fedora" ]; then
        echo -e "${Msg_Info}Release Detected: ${Var_OSRelease}"
        echo -e "${Msg_Info}Preparing compile enviorment ..."
        dnf install -y wget curl make gcc gcc-c++ traceroute openssl-devel protobuf-devel bison flex libpcap-devel
        local Spoofer_Version="$(curl --user-agent "${UA_LemonBench}" -fskSL https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/latest_version)"
        echo -e "${Msg_Info}Downloading Source code (Version ${Spoofer_Version})..."
        mkdir -p /tmp/_LBench/src/
        wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/spoofer.tar.gz https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/${Spoofer_Version}/spoofer.tar.gz
        echo -e "${Msg_Info}Compiling Spoof Module ..."
        cd /tmp/_LBench/src/
        tar xvf spoofer.tar.gz && cd spoofer-"${Spoofer_Version}"
        # 测试性补丁
        wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/configure.patch https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/${Spoofer_Version}/patch/configure.patch
        patch -p0 configure /tmp/_LBench/src/configure.patch
        ./configure && make -j ${LBench_Result_CPUThreadNumber}
        cp prober/spoofer-prober /usr/local/bin/spoofer-prober
        echo -e "${Msg_Info}Cleaning up ..."
        cd /tmp && rm -rf /tmp/_LBench/src/spoofer*
    elif [ "${Var_OSRelease}" = "alpinelinux" ]; then
        echo -e "${Msg_Info}Release Detected: ${Var_OSRelease}"
        echo -e "${Msg_Info}Preparing compile enviorment ..."
        apk update
        apk add traceroute gcc g++ make openssl-dev protobuf-dev libpcap-dev
        local Spoofer_Version="$(curl  --user-agent "${UA_LemonBench}"  -fskSL https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/latest_version)"
        echo -e "${Msg_Info}Downloading Source code (Version ${Spoofer_Version})..."
        mkdir -p /tmp/_LBench/src/
        wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/spoofer.tar.gz https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/${Spoofer_Version}/spoofer.tar.gz
        echo -e "${Msg_Info}Compiling Spoof Module ..."
        cd /tmp/_LBench/src/
        tar xvf spoofer.tar.gz && cd spoofer-"${Spoofer_Version}"
        # 测试性补丁
        wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/configure.patch https://raindrop.ilemonrain.com/LemonBench/include/Spoofer/${Spoofer_Version}/patch/configure.patch
        patch -p0 configure /tmp/_LBench/src/configure.patch
        ./configure && make -j ${LBench_Result_CPUThreadNumber}
        cp prober/spoofer-prober /usr/local/bin/spoofer-prober
        echo -e "${Msg_Info}Cleaning up ..."
        cd /tmp && rm -rf /tmp/_LBench/src/spoofer*
    else
        echo -e "${Msg_Error}Cannot compile on current enviorment! (Only Support CentOS/Debian/Ubuntu/Fedora/AlpineLinux) "
    fi
}

# =============== 检查 SysBench 组件 ===============
Check_SysBench() {
    if [ ! -f "/usr/bin/sysbench" ] && [ ! -f "/usr/local/bin/sysbench" ]; then
        SystemInfo_GetOSRelease
        SystemInfo_GetSystemBit
        if [ "${Var_OSRelease}" = "centos" ] || [ "${Var_OSRelease}" = "rhel" ]; then
            echo -e "${Msg_Warning}Sysbench Module not found, installing ..."
            yum -y install epel-release
            yum -y install sysbench
        elif [ "${Var_OSRelease}" = "ubuntu" ]; then
            echo -e "${Msg_Warning}Sysbench Module not found, installing ..."
            apt-get install -y sysbench
        elif [ "${Var_OSRelease}" = "debian" ]; then
            echo -e "${Msg_Warning}Sysbench Module not found, installing ..."
            local mirrorbase="https://raindrop.ilemonrain.com/LemonBench"
            local componentname="Sysbench"
            local version="1.0.19-1"
            local arch="debian"
            local codename="${Var_OSReleaseVersion_Codename}"
            local bit="${LBench_Result_SystemBit_Full}"
            local filenamebase="sysbench"
            local filename="${filenamebase}_${version}_${bit}.deb"
            local downurl="${mirrorbase}/include/${componentname}/${version}/${arch}/${codename}/${filename}"
            mkdir -p ${WorkDir}/download/
            pushd ${WorkDir}/download/ >/dev/null
            wget -U "${UA_LemonBench}" -O ${filenamebase}_${version}_${bit}.deb ${downurl}
            dpkg -i ./${filename}
            apt-get install -f -y
            popd
            if [ ! -f "/usr/bin/sysbench" ] && [ ! -f "/usr/local/bin/sysbench" ]; then
                echo -e "${Msg_Warning}Sysbench Module Install Failed!"
            fi
        elif [ "${Var_OSRelease}" = "fedora" ]; then
            echo -e "${Msg_Warning}Sysbench Module not found, installing ..."
            dnf -y install sysbench
        elif [ "${Var_OSRelease}" = "alpinelinux" ]; then
            echo -e "${Msg_Warning}Sysbench Module not found, installing ..."
            echo -e "${Msg_Warning}SysBench Current not support Alpine Linux, Skipping..."
            Var_Skip_SysBench="1"
        fi
    fi
    # 垂死挣扎 (尝试编译安装)
    if [ ! -f "/usr/bin/sysbench" ] && [ ! -f "/usr/local/bin/sysbench" ]; then
        echo -e "${Msg_Warning}Sysbench Module install Failure, trying compile modules ..."
        Check_Sysbench_InstantBuild
    fi
    # 最终检测
    if [ ! -f "/usr/bin/sysbench" ] && [ ! -f "/usr/local/bin/sysbench" ]; then
        echo -e "${Msg_Error}SysBench Moudle install Failure! Try Restart Bench or Manually install it! (/usr/bin/sysbench)"
        exit 1
    fi
}

Check_Sysbench_InstantBuild() {
    SystemInfo_GetOSRelease
    SystemInfo_GetCPUInfo
    if [ "${Var_OSRelease}" = "centos" ] || [ "${Var_OSRelease}" = "rhel" ]; then
        echo -e "${Msg_Info}Release Detected: ${Var_OSRelease}"
        echo -e "${Msg_Info}Preparing compile enviorment ..."
        yum install -y epel-release
        yum install -y wget curl make gcc gcc-c++ make automake libtool pkgconfig libaio-devel
        echo -e "${Msg_Info}Release Detected: ${Var_OSRelease}"
        echo -e "${Msg_Info}Downloading Source code (Version 1.0.17)..."
        mkdir -p /tmp/_LBench/src/
        wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/sysbench.zip https://github.com/akopytov/sysbench/archive/1.0.17.zip
        echo -e "${Msg_Info}Compiling Sysbench Module ..."
        cd /tmp/_LBench/src/
        unzip sysbench.zip && cd sysbench-1.0.17
        ./autogen.sh && ./configure --without-mysql && make -j8 && make install
        echo -e "${Msg_Info}Cleaning up ..."
        cd /tmp && rm -rf /tmp/_LBench/src/sysbench*
    elif [ "${Var_OSRelease}" = "ubuntu" ] || [ "${Var_OSRelease}" = "debian" ]; then
        echo -e "${Msg_Info}Release Detected: ${Var_OSRelease}"
        echo -e "${Msg_Info}Preparing compile enviorment ..."
        apt-get update
        apt -y install --no-install-recommends curl wget make automake libtool pkg-config libaio-dev unzip
        echo -e "${Msg_Info}Downloading Source code (Version 1.0.17)..."
        mkdir -p /tmp/_LBench/src/
        wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/sysbench.zip https://github.com/akopytov/sysbench/archive/1.0.17.zip
        echo -e "${Msg_Info}Compiling Sysbench Module ..."
        cd /tmp/_LBench/src/
        unzip sysbench.zip && cd sysbench-1.0.17
        ./autogen.sh && ./configure --without-mysql && make -j8 && make install
        echo -e "${Msg_Info}Cleaning up ..."
        cd /tmp && rm -rf /tmp/_LBench/src/sysbench*
    elif [ "${Var_OSRelease}" = "fedora" ]; then
        echo -e "${Msg_Info}Release Detected: ${Var_OSRelease}"
        echo -e "${Msg_Info}Preparing compile enviorment ..."
        dnf install -y wget curl gcc gcc-c++ make automake libtool pkgconfig libaio-devel
        echo -e "${Msg_Info}Downloading Source code (Version 1.0.17)..."
        mkdir -p /tmp/_LBench/src/
        wget -U "${UA_LemonBench}" -O /tmp/_LBench/src/sysbench.zip https://github.com/akopytov/sysbench/archive/1.0.17.zip
        echo -e "${Msg_Info}Compiling Sysbench Module ..."
        cd /tmp/_LBench/src/
        unzip sysbench.zip && cd sysbench-1.0.17
        ./autogen.sh && ./configure --without-mysql && make -j8 && make install
        echo -e "${Msg_Info}Cleaning up ..."
        cd /tmp && rm -rf /tmp/_LBench/src/sysbench*
    else
        echo -e "${Msg_Error}Cannot compile on current enviorment! (Only Support CentOS/Debian/Ubuntu/Fedora) "
    fi
}

Function_CheckTracemode() {
    if [ "${Flag_TracerouteModeisSet}" = "1" ]; then
        if [ "${GlobalVar_TracerouteMode}" = "icmp" ]; then
            echo -e "${Msg_Info}Traceroute/BestTrace Tracemode is set to: ${Font_SkyBlue}ICMP Mode${Font_Suffix}"
        elif [ "${GlobalVar_TracerouteMode}" = "tcp" ]; then
            echo -e "${Msg_Info}Traceroute/BestTrace Tracemode is set to: ${Font_SkyBlue}TCP Mode${Font_Suffix}"
        fi
    else
        GlobalVar_TracerouteMode="tcp"
    fi
}

# =============== 全局启动信息 ===============
Global_Startup_Header() {
    echo -e "
 ${Font_Green}#-----------------------------------------------------------#${Font_Suffix}
 ${Font_Green}@${Font_Suffix}    ${Font_Blue}LemonBench${Font_Suffix} ${Font_Yellow}Server Evaluation & Benchmark Ultility${Font_Suffix}      ${Font_Green}@${Font_Suffix}
 ${Font_Green}#-----------------------------------------------------------#${Font_Suffix}
 ${Font_Green}@${Font_Suffix} ${Font_Purple}Written by${Font_Suffix} ${Font_SkyBlue}iLemonrain${Font_Suffix} ${Font_Blue}<ilemonrain@ilemonrain.com>${Font_Suffix}         ${Font_Green}@${Font_Suffix}
 ${Font_Green}@${Font_Suffix} ${Font_Purple}My Blog:${Font_Suffix} ${Font_SkyBlue}https://ilemonrain.com${Font_Suffix}                           ${Font_Green}@${Font_Suffix}
 ${Font_Green}@${Font_Suffix} ${Font_Purple}Telegram:${Font_Suffix} ${Font_SkyBlue}https://t.me/ilemonrain${Font_Suffix}                         ${Font_Green}@${Font_Suffix}
 ${Font_Green}@${Font_Suffix} ${Font_Purple}Telegram (For +86 User):${Font_Suffix} ${Font_SkyBlue}https://t.me/ilemonrain_chatbot${Font_Suffix}  ${Font_Green}@${Font_Suffix}
 ${Font_Green}@${Font_Suffix} ${Font_Purple}Telegram Channel:${Font_Suffix} ${Font_SkyBlue}https://t.me/ilemonrain_channel${Font_Suffix}         ${Font_Green}@${Font_Suffix}
 ${Font_Green}#-----------------------------------------------------------#${Font_Suffix}

 Version: ${BuildTime}

 Reporting Bugs Via:
 https://t.me/ilemonrain 或 https://t.me/ilemonrain_chatbot
 (简体中文/繁體中文/English only)
 
 Thanks for using!

 Usage (two way):
 (1) wget -O- https://ilemonrain.com/download/shell/LemonBench.sh | bash
 (2) curl -fsL https://ilemonrain.com/download/shell/LemonBench.sh | bash

"
}

# =============== 入口 - 快速测试 (fast) ===============
Entrance_FastBench() {
    Global_TestMode="fast"
    Global_TestModeTips="Fast Mode"
    Global_StartupInit_Action
    Function_GetSystemInfo
    Function_BenchStart
    Function_ShowSystemInfo
    Function_ShowNetworkInfo
    Function_MediaUnlockTest
    Function_SysBench_CPU_Fast
    Function_SysBench_Memory_Fast
    Function_DiskTest_Fast
    Function_Speedtest_Fast
    Function_BestTrace_Fast
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

# =============== 入口 - 完全测试 (full) ===============
Entrance_FullBench() {
    Global_TestMode="full"
    Global_TestModeTips="Full Mode"
    Global_StartupInit_Action
    Function_GetSystemInfo
    Function_BenchStart
    Function_ShowSystemInfo
    Function_ShowNetworkInfo
    Function_MediaUnlockTest
    Function_SysBench_CPU_Full
    Function_SysBench_Memory_Full
    Function_DiskTest_Full
    Function_Speedtest_Full
    Function_BestTrace_Full
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

# =============== 入口 - 仅流媒体解锁测试 (mlt) ===============
Entrance_MediaUnlockTest() {
    Global_Startup_Header
    Global_TestMode="mediaunlocktest"
    Global_TestModeTips="Media Unlock Test Only"
    Check_JSONQuery
    Function_BenchStart
    Function_MediaUnlockTest
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

# =============== 入口 - 仅Speedtest测试-快速模式 (spfast) ===============
Entrance_Speedtest_Fast() {
    Global_Startup_Header
    Global_TestMode="speedtest-fast"
    Global_TestModeTips="Speedtest Only (Fast Mode)"
    Function_BenchStart
    Check_Speedtest
    Function_Speedtest_Fast
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

# =============== 入口 - 仅Speedtest测试-全面模式 (spfull) ===============
Entrance_Speedtest_Full() {
    Global_Startup_Header
    Global_TestMode="speedtest-full"
    Global_TestModeTips="Speedtest Only (Full Mode)"
    Check_Speedtest
    Function_BenchStart
    Function_Speedtest_Full
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

# =============== 入口 - 仅磁盘性能测试-快速模式 (dtfast) ===============
Entrance_DiskTest_Fast() {
    Global_Startup_Header
    Global_TestMode="disktest-fast"
    Global_TestModeTips="Disk Performance Test Only (Fast Mode)"
    Function_BenchStart
    Function_DiskTest_Fast
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

# =============== 入口 - 仅磁盘性能测试-全面模式 (dtfull) ===============
Entrance_DiskTest_Full() {
    Global_Startup_Header
    Global_TestMode="disktest-full"
    Global_TestModeTips="Disk Performance Test Only (Full Mode)"
    Function_BenchStart
    Function_DiskTest_Full
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

# =============== 入口 - 仅路由追踪测试-快速模式 (btfast) ===============
Entrance_BestTrace_Fast() {
    Global_Startup_Header
    Global_TestMode="besttrace-fast"
    Global_TestModeTips="Traceroute Test Only (Fast Mode)"
    Function_CheckTracemode
    Check_JSONQuery
    Check_BestTrace
    echo -e "${Msg_Info}Collecting Network Info ..."
    SystemInfo_GetNetworkInfo
    Function_BenchStart
    Function_ShowNetworkInfo
    Function_BestTrace_Fast
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

# =============== 入口 - 仅路由追踪测试-完全模式 (btfull) ===============
Entrance_BestTrace_Full() {
    Global_Startup_Header
    Global_TestMode="besttrace-full"
    Global_TestModeTips="Traceroute Test Only (Full Mode)"
    Function_CheckTracemode
    Check_JSONQuery
    Check_BestTrace
    echo -e "${Msg_Info}Collecting Network Info ..."
    SystemInfo_GetNetworkInfo
    Function_BenchStart
    Function_ShowNetworkInfo
    Function_BestTrace_Full
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

# =============== 入口 - 仅Spoofer测试-快速模式 (spf) ===============
Entrance_Spoofer() {
    Global_Startup_Header
    Function_SpooferWarning
    Global_TestMode="spoofer"
    Global_TestModeTips="Spoof Test Only"
    Check_Spoofer
    Function_BenchStart
    Function_SpooferTest
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}


Entrance_SysBench_CPU_Fast() {
    Global_Startup_Header
    Global_TestMode="sysbench-cpu-fast"
    Global_TestModeTips="CPU Performance Test Only (Fast Mode)"
    Check_SysBench
    Function_BenchStart
    SystemInfo_GetCPUInfo
    Function_SysBench_CPU_Fast
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

Entrance_SysBench_CPU_Full() {
    Global_Startup_Header
    Global_TestMode="sysbench-cpu-full"
    Global_TestModeTips="CPU Performance Test Only (Standard Mode)"
    Check_SysBench
    Function_BenchStart
    SystemInfo_GetCPUInfo
    Function_SysBench_CPU_Full
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

#
Entrance_SysBench_Memory_Fast() {
    Global_Startup_Header
    Global_TestMode="sysbench-memory-fast"
    Global_TestModeTips="Memory Performance Test Only (Fast Mode)"
    Check_SysBench
    Function_BenchStart
    SystemInfo_GetCPUInfo
    Function_SysBench_Memory_Fast
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

Entrance_SysBench_Memory_Full() {
    Global_Startup_Header
    Global_TestMode="sysbench-memory-full"
    Global_TestModeTips="Memory Performance Test Only (Standard Mode)"
    Check_SysBench
    Function_BenchStart
    SystemInfo_GetCPUInfo
    Function_SysBench_Memory_Full
    Function_BenchFinish
    Function_GenerateResult
    Global_Exit_Action
}

# =============== 入口 - 帮助文档 (help) ===============
Entrance_HelpDocument() {
    echo -e " "
    echo -e " ${Font_SkyBlue}LemonBench${Font_Suffix} ${Font_Yellow}Server Performace Test Utility${Font_Suffix}"
    echo -e " "
    echo -e " ${Font_Yellow}Written by:${Font_Suffix}\t\t ${Font_SkyBlue}iLemonrain <ilemonrain@ilemonrain.com>${Font_Suffix}"
    echo -e " ${Font_Yellow}Project Homepage:${Font_Suffix}\t ${Font_SkyBlue}https://blog.ilemonrain.com/linux/LemonBench.html${Font_Suffix}"
    echo -e " ${Font_Yellow}Code Version:${Font_Suffix}\t\t ${Font_SkyBlue}${BuildTime}${Font_Suffix}"
    echo -e " "
    echo -e " Usage:"
    echo -e " ${Font_SkyBlue}>> One-Key Benchmark${Font_Suffix}"
    echo -e " ${Font_Yellow}--mode TestMode${Font_Suffix}\t${Font_SkyBlue}Test Mode (fast/full, aka FastMode/FullMode)${Font_Suffix}"
    echo -e " "
    echo -e " ${Font_SkyBlue}>> Single Test${Font_Suffix}"
    echo -e " ${Font_Yellow}--dtfast${Font_Suffix}\t\t${Font_SkyBlue}Disk Test (Fast Test Mode)${Font_Suffix}"
    echo -e " ${Font_Yellow}--dtfull${Font_Suffix}\t\t${Font_SkyBlue}Disk Test (Full Test Mode)${Font_Suffix}"
    echo -e " ${Font_Yellow}--spfast${Font_Suffix}\t\t${Font_SkyBlue}Speedtest Test (Fast Test Mode)${Font_Suffix}"
    echo -e " ${Font_Yellow}--spfull${Font_Suffix}\t\t${Font_SkyBlue}Speedtest Test (Full Test Mode)${Font_Suffix}"
    echo -e " ${Font_Yellow}--trfast${Font_Suffix}\t\t${Font_SkyBlue}Traceroute Test (Fast Test Mode)${Font_Suffix}"
    echo -e " ${Font_Yellow}--trfull${Font_Suffix}\t\t${Font_SkyBlue}Traceroute Test (Full Test Mode)${Font_Suffix}"
    echo -e " ${Font_Yellow}--sbcfast${Font_Suffix}\t\t${Font_SkyBlue}CPU Benchmark Test (Fast Test Mode)${Font_Suffix}"
    echo -e " ${Font_Yellow}--sbcfull${Font_Suffix}\t\t${Font_SkyBlue}CPU Benchmark Test (Full Test Mode)${Font_Suffix}"
    echo -e " ${Font_Yellow}--sbmfast${Font_Suffix}\t\t${Font_SkyBlue}Memory Benchmark Test (Fast Test Mode)${Font_Suffix}"
    echo -e " ${Font_Yellow}--sbmfull${Font_Suffix}\t\t${Font_SkyBlue}Memory Benchmark Test (Full Test Mode)${Font_Suffix}"    
    echo -e " ${Font_Yellow}--spoof${Font_Suffix}\t\t${Font_SkyBlue}Caida Spoofer Test ${Font_Yellow}(Use it at your own risk)${Font_Suffix}${Font_Suffix}"
}

# =============== 命令行参数 ===============
# 检测传入参数
SingleTestCount="0"
while [[ $# -ge 1 ]]; do
    case $1 in
    mode | -mode | --mode | testmode | -testmode | --testmode)
        shift
        if [ "${GlobalVar_TestMode}" != "" ]; then
            echo -e "\n${Msg_Error}只允许同时启用一种预置测试! 请检查输入参数后重试!"
            Entrance_HelpDocument
            exit 1
        else
            GlobalVar_TestMode="$1"
            shift
        fi
        ;;
    # 快速测试
    fast | -fast | --fast)
        shift
        if [ "${GlobalVar_TestMode}" != "" ]; then
            echo -e "\n${Msg_Error}只允许同时启用一种预置测试! 请检查输入参数后重试!"
            Entrance_HelpDocument
            exit 1
        else
            GlobalVar_TestMode="fast"
        fi
        ;;
    # 完整测试
    full | -full | --full)
        shift
        if [ "${GlobalVar_TestMode}" != "" ]; then
            echo -e "\n${Msg_Error}只允许同时启用一种预置测试! 请检查输入参数后重试!"
            Entrance_HelpDocument
            exit 1
        else
            GlobalVar_TestMode="full"
        fi
        ;;
    # 流媒体解锁测试
    mlt | -mlt | --mlt)
        shift
        GlobalVar_TestMode="mediaunlocktest"
        ;;
    # 磁盘测试
    dtfast | -dtfast | --dtfast)
        shift
        GlobalVar_TestMode="disktest-fast"
        ;;
    dtfull | -dtfull | --dtfull)
        shift
        GlobalVar_TestMode="disktest-full"
        ;;
    # Speedtest测试
    spfast | -spfast | --spfast)
        shift
        GlobalVar_TestMode="speedtest-fast"
        ;;
    spfull | -spfull | --spfull)
        shift
        GlobalVar_TestMode="speedtest-full"
        ;;
    # 路由追踪测试        
    btfast | -btfast | --btfast | trfast | -trfast | --trfast)
        shift
        GlobalVar_TestMode="besttrace-fast"
        ;;
    btfull | -btfull | --btfull | trfull | -trull | --trfull)
        shift
        GlobalVar_TestMode="besttrace-full"
        ;;
    # Spoof测试
    spf | -spf | --spf | spoof | -spoof | --spoof | spoofer | -spoofer | --spoofer)
        shift
        GlobalVar_TestMode="spoof"
        ;;
    # CPU测试
    sbcfast | -sbcfast | --sbcfast)
        shift
        GlobalVar_TestMode="sysbench-cpu-fast"
        ;;
    sbcfull | -sbcfull | --sbcfull)
        shift
        GlobalVar_TestMode="sysbench-cpu-full"
        ;;
    # 内存测试
    sbmfast | -sbmfast | --sbmfast)
        shift
        GlobalVar_TestMode="sysbench-memory-fast"
        ;;
    sbmfull | -sbmfull | --sbmfull)
        shift
        GlobalVar_TestMode="sysbench-memory-full"
        ;;
    # 路由追踪测试模式
    tracemode | -tracemode | --tracemode )
        shift
        if [ "$1" = "icmp" ]; then
            Flag_TracerouteModeisSet="1"
            GlobalVar_TracerouteMode="icmp"
            shift
        elif [ "$1" = "tcp" ]; then
            Flag_TracerouteModeisSet="1"
            GlobalVar_TracerouteMode="tcp"
            shift
        else
            Flag_TracerouteModeisSet="0"
            GlobalVar_TracerouteMode="tcp"
            shift
        fi
        ;;
    # 帮助文档
    h | -h | --h | help | -help | --help)
        Entrance_HelpDocument
        exit 1
        ;;
    # 无效参数处理
    *)
        [[ "$1" != 'error' ]] && echo -ne "\n${Msg_Error}Invalid Parameters: \"$1\"\n"
        Entrance_HelpDocument
        exit 1
        ;;
    esac
done
# 全局入口
echo " "
if [ "${#SingleTestList[@]}" -eq "0" ] && [ "${GlobalVar_TestMode}" = "" ]; then
    Entrance_HelpDocument
    exit 1
elif [ "${GlobalVar_TestMode}" = "fast" ]; then
    Global_Startup_Header
    Entrance_FastBench
elif [ "${GlobalVar_TestMode}" = "full" ]; then
    Global_Startup_Header
    Entrance_FullBench
elif [ "${GlobalVar_TestMode}" = "mediaunlocktest" ]; then
    Global_Startup_Header
    Entrance_MediaUnlockTest
elif [ "${GlobalVar_TestMode}" = "disktest-fast" ]; then
    Global_Startup_Header
    Entrance_DiskTest_Fast
elif [ "${GlobalVar_TestMode}" = "disktest-full" ]; then
    Global_Startup_Header
    Entrance_DiskTest_Full
elif [ "${GlobalVar_TestMode}" = "speedtest-fast" ]; then
    Global_Startup_Header
    Entrance_Speedtest_Fast
elif [ "${GlobalVar_TestMode}" = "speedtest-full" ]; then
    Global_Startup_Header
    Entrance_Speedtest_Full
elif [ "${GlobalVar_TestMode}" = "besttrace-fast" ]; then
    Global_Startup_Header
    Entrance_BestTrace_Fast
elif [ "${GlobalVar_TestMode}" = "besttrace-full" ]; then
    Global_Startup_Header
    Entrance_BestTrace_Full
elif [ "${GlobalVar_TestMode}" = "spoof" ]; then
    Global_Startup_Header
    Entrance_Spoofer
elif [ "${GlobalVar_TestMode}" = "sysbench-cpu-fast" ]; then
    Global_Startup_Header
    Entrance_SysBench_CPU_Fast
elif [ "${GlobalVar_TestMode}" = "sysbench-cpu-full" ]; then
    Global_Startup_Header
    Entrance_SysBench_CPU_Full
elif [ "${GlobalVar_TestMode}" = "sysbench-memory-fast" ]; then
    Global_Startup_Header
    Entrance_SysBench_Memory_Fast
elif [ "${GlobalVar_TestMode}" = "sysbench-memory-full" ]; then
    Global_Startup_Header
    Entrance_SysBench_Memory_Full
else
    Entrance_HelpDocument
    exit 1
fi

脚本五:内存检测脚本

#CentOS / RHEL
yum install wget -y
yum groupinstall "Development Tools" -y
wget https://raw.githubusercontent.com/FunctionClub/Memtester/master/memtester.cpp
gcc -l stdc++ memtester.cpp
./a.out
#Ubuntu / Debian
apt-get update
apt-get install wget build-essential -y
wget https://raw.githubusercontent.com/FunctionClub/Memtester/master/memtester.cpp
gcc -l stdc++ memtester.cpp
./a.out

FunctionClub大佬作品,本程序检测的可分配内存指的是用户使用时最大能占用的内存量。

特点

  • 检测VPS真实可分配内存,适用于检测VPS超售情况

脚本六:uPing

#Debian / Ubuntu
apt-get update
apt-get install python wget screen -y
#CentOS / RHEL
yum install screen wget python -y
screen -S uping
wget -N --no-check-certificate https://raw.githubusercontent.com/FunctionClub/uPing/master/uping.py
python uping.py

FunctionClub大佬作品,测试阶段,请勿用于生产环境!

特点

  • 一个24小时监测VPS延迟的工具

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import os
import time
import commands
import sys

class Pinger():
    STYLE = {
        'fore': {
            'black': 30, 'red': 31, 'green': 32, 'yellow': 33,
            'blue': 34, 'purple': 35, 'cyan': 36, 'white': 37,
        },
        'back': {
            'black': 40, 'red': 41, 'green': 42, 'yellow': 43,
            'blue': 44, 'purple': 45, 'cyan': 46, 'white': 47,
        },
        'mode': {
            'bold': 1, 'underline': 4, 'blink': 5, 'invert': 7,
        },
        'default': {
            'end': 0,
        }
    }

    def __init__(self, host):
        self.start_time = time.localtime(time.time())
        self.start_time_m = time.time()

        self.data = dict()
        self.host = host

        self.midnight_zero = list()
        self.midnight_non_zero = list()
        self.morning_zero = list()
        self.morning_non_zero = list()
        self.afternoon_zero = list()
        self.afternoon_non_zero = list()
        self.night_zero = list()
        self.night_non_zero = list()






    def ping(self):
        cmd = "ping "+ self.host + " -c1 -W 1"
        result = commands.getoutput(cmd)
        result = result.split()
        result = result[-2].split("/")[0]
        if result.isalpha():
            result =0
        return float(result)


    def use_style(self,string, mode='', fore='', back=''):
        mode = '%s' % self.STYLE['mode'][mode] if self.STYLE['mode'].has_key(mode) else ''
        fore = '%s' % self.STYLE['fore'][fore] if self.STYLE['fore'].has_key(fore) else ''
        back = '%s' % self.STYLE['back'][back] if self.STYLE['back'].has_key(back) else ''
        style = ';'.join([s for s in [mode, fore, back] if s])
        style = '\033[%sm' % style if style else ''
        end = '\033[%sm' % self.STYLE['default']['end'] if style else ''
        return '%s%s%s' % (style, string, end)

    def red(self,str):
        return self.use_style(str,fore="red")

    def blue(self,str):
        return self.use_style(str,fore="blue")

    def cyan(self,str):
        return self.use_style(str,fore="cyan")

    def yellow(self,str):
        return self.use_style(str,fore="yellow")

    def green(self,str):
        return self.use_style(str,fore="green")

    def purple(self,str):
        return self.use_style(str,fore="purple")

    def colored(self,latency):
        if latency == 0:
            return self.red(str(round(latency,2)) + " ms")
        elif(0<latency < 100):
            return self.green(str(round(latency,2)) + " ms")
        elif latency < 170:
            return self.yellow(str(round(latency,2)) + " ms")
        else:
            return self.red(str(round(latency,2)) + " ms")


    def start(self):
        current_time = time.localtime(time.time())
        i=1

        while(time.time() - self.start_time_m <= 86400):

            latency=self.ping()
            current_time = time.localtime(time.time())
            self.data[i] = {"year":  current_time[0], \
                            "month": current_time[1], \
                            "day" :  current_time[2], \
                            "hour" : current_time[3], \
                            "minute":current_time[4], \
                            "second":current_time[5],\
                            "latency": latency}

            i = i + 1
            self.print_graph()
            self.data.clear()

            if(latency != 0.0):
                time.sleep(1)





    def is_night(self,d):
        if  18 <= d["hour"] <= 23:
            return True
        else:
            return False

    def is_morning(self,d):
        if 6 <= d["hour"] <= 12:
            return True
        else:
            return False

    def is_mid_night(self,d):
        if 0 < d["hour"] < 6:
            return True
        else:
            return False

    def is_afternoon(self,d):
        if 12 < d["hour"] < 18:
            return True
        else:
            return False

    def lost_percentage(self,zero,non_zero):

        sum = len(zero) + len(non_zero)

        if sum == 0:
            return self.red(str(0) + " %")
        else:
            percentage = 100 * len(zero) / sum

        if percentage <5:
            return self.green(str(int(percentage)) + " %")
        elif percentage < 10:
            return self.yellow(str(int(percentage)) + " %")
        else:
            return self.red(str(int(percentage)) + " %")

    def print_graph(self):
        os.system("clear")
        spend_time = (time.time() - self.start_time_m)

        for i in self.data.keys():

            x = self.data[i]
            latency = x["latency"]

            total_count = self.data.keys()[-1]

            if(self.is_mid_night(x)):
                if latency == 0:
                    self.midnight_zero.append(latency)
                else:
                    self.midnight_non_zero.append(latency)

            elif(self.is_morning(x)):
                if latency == 0:
                    self.morning_zero.append(latency)
                else:
                    self.morning_non_zero.append(latency)

            elif(self.is_afternoon(x)):
                if latency == 0:
                    self.afternoon_zero.append(latency)
                else:
                    self.afternoon_non_zero.append(latency)

            elif(self.is_night(x)):
                if latency == 0:
                    self.night_zero.append(latency)
                else:
                    self.night_non_zero.append(latency)
            else:
                print("Error :", x)




        total_non_zero = self.morning_non_zero + self.midnight_non_zero + self.afternoon_non_zero+self.night_non_zero

        total_zero_list = self.morning_zero + self.midnight_zero + self.afternoon_zero+self.night_zero
        total_zero = len(total_zero_list)

        if(total_count - total_zero == 0):
            total_average = 0
        else:
            total_average = sum(total_non_zero)/(total_count - total_zero)

        if len(self.morning_non_zero) == 0:
            morning_average = 0
        else:
            morning_average = sum(self.morning_non_zero) / len(self.morning_non_zero)

        if len(self.afternoon_non_zero) == 0:
            afternoon_average = 0
        else:
            afternoon_average = sum(self.afternoon_non_zero) / len(self.afternoon_non_zero)

        if len(self.night_non_zero) == 0:
            night_average = 0
        else:
            night_average = sum(self.night_non_zero) / len(self.night_non_zero)

        if len(self.midnight_non_zero) == 0:
            midnight_average = 0
        else:
            midnight_average = sum(self.midnight_non_zero) / len(self.midnight_non_zero)

        print("-" * 53)
        print("|{0:16}{1:37}{2:16}|".format("",self.cyan("服务器延迟监测脚本"),""))
        print("-" * 53)
        print "| {0:37}| {1:37}|".format(self.blue("上午统计"),self.blue("下午统计"))
        print("{0:39}| {1:37}|".format("| 最低延迟: " + self.colored(  min(self.morning_non_zero) if len(self.morning_non_zero)!=0 else 0),"最低延迟: " + self.colored(min(self.afternoon_non_zero) if len(self.afternoon_non_zero) != 0 else 0)  )  )
        print("{0:39}| {1:37}|".format("| 最高延迟: " + self.colored(max(self.morning_non_zero) if len(self.morning_non_zero)!=0 else 0),"最高延迟: " + self.colored(max(self.afternoon_non_zero) if len(self.afternoon_non_zero) != 0 else 0)))
        print("{0:39}| {1:37}|".format("| 平均延迟: " + self.colored(morning_average),"平均延迟: " + self.colored(afternoon_average)))
        print("{0:38}| {1:36}|".format("| 丢包率  : "+ self.lost_percentage(self.morning_zero,self.morning_non_zero),"丢包率  : " + self.lost_percentage(self.afternoon_zero,self.afternoon_non_zero)))
        print("{0:39}| {1:37}|".format("| 超时次数: " + self.red(len(self.morning_zero)),"超时次数: " + self.red(len(self.afternoon_zero))))
        print("{0:30}| {1:28}|".format("| 测试次数: " + str(len(self.morning_non_zero) + len(self.morning_zero)),"测试次数: " + str(len(self.afternoon_non_zero) + len(self.afternoon_zero))))



        print("-" * 53)
        print "| {0:37}| {1:37}|".format(self.blue("夜晚统计"), self.blue("半夜统计"))
        print("{0:39}| {1:37}|".format(
            "| 最低延迟: " + self.colored(min(self.night_non_zero) if len(self.night_non_zero) != 0 else 0),
            "最低延迟: " + self.colored(min(self.midnight_non_zero) if len(self.midnight_non_zero) != 0 else 0)))
        print("{0:39}| {1:37}|".format(
            "| 最高延迟: " + self.colored(max(self.night_non_zero) if len(self.night_non_zero) != 0 else 0),
            "最高延迟: " + self.colored(max(self.midnight_non_zero) if len(self.midnight_non_zero) != 0 else 0)))
        print("{0:39}| {1:37}|".format("| 平均延迟: " + self.colored(night_average),
                                       "平均延迟: " + self.colored(midnight_average)))
        print("{0:38}| {1:36}|".format("| 丢包率  : "+ self.lost_percentage(self.night_zero,self.night_non_zero),"丢包率  : " + self.lost_percentage(self.midnight_zero,self.midnight_non_zero)))
        print("{0:39}| {1:37}|".format("| 超时次数: " + self.red(len(self.night_zero)),
                                       "超时次数: " + self.red(len(self.midnight_zero))))
        print("{0:30}| {1:28}|".format("| 测试次数: " + str(len(self.night_non_zero) + len(self.night_zero)),
                                       "测试次数: " + str(len(self.midnight_non_zero) + len(self.midnight_zero))))


        print("-" * 53)
        print "| {0:63}|".format(self.blue("全局统计"))
        print("{0:41}{1:36}|".format("| 最低延迟: " + self.colored(min(total_non_zero) if len(total_non_zero) != 0 else 0),"丢包率    : " + self.lost_percentage(total_zero_list,total_non_zero)))
        print("{0:41}{1:38}|".format("| 最高延迟: " + self.colored(max(total_non_zero) if len(total_non_zero) != 0 else 0),"总超时次数: " + self.red(total_zero)))
        print("{0:41}{1:29}|".format("| 平均延迟: " + self.colored(total_average),"总测试次数: " + str(total_count)))


        print("-" * 53)
        print ("|{0:13}{1:30}{2:22}{3:9}|".format("", self.purple("当前测试Ping值:"), self.colored(self.data[self.data.keys()[-1]]["latency"]),""))
        print("-" * 53)

        print("|{0:12}{1:4}{2:2} 小时{3:2} 分钟{4:2} 秒{5:13}|".format("",self.purple("已耗时:"),int(spend_time/3600)if spend_time/3600 >=1 else 0,(int(spend_time % 3600 /60))if spend_time % 3600 /60 >= 1 else 0,int(spend_time % 3600 %60),""))
        print("-" * 53)



if __name__ == "__main__" :
    os.system("clear")
    print("服务器延迟监测脚本")
    print("Made By 主机博客(zhujiboke.com)")
    print("")
    mytime = time.localtime(time.time())
    print("当前服务器时间为: " + str(mytime[0]) + "年" + str(mytime[1]) + "月" + str(mytime[2]) +"日 "  + str(mytime[3]) + ":" + str(mytime[4]) + ":" + str(mytime[5]) )
    myinput = raw_input("是否正确 (y/n): ")

    if myinput == "y":
        pinghost = raw_input("请输入要Ping的服务器IP/域名:")
        p = Pinger(pinghost)
        p.start()
    else:
        print("\n请将服务器时间调整正确后运行本程序!")

脚本七:Besttrace4Linux

#下载
wget http://cdn.ipip.net/17mon/besttrace4linux.zip
#解压
unzip besttrace4linux.zip
#授权
chmod +x besttrace
#使用
./besttrace -q1 这里是目标IP

回程路由测试-IPIP.net出品

特点

  • Linux(X86/ARM)/Mac/BSD 系统环境下发起 traceroute 请求

  • 附带链路可视化

  • 兼容性强

  • 支持 JSON 格式

如果是64位系统则直接besttrace替换besttrace32

脚本八:Speedtest-Cli

#下载
wget https://raw.github.com/sivel/speedtest-cli/master/speedtest.py
#添加权限
chmod a+rx speedtest.py
#执行
python speedtest.py

国外大佬Sivel作品

特点

  • 测试网络上传/下载速率的一款工具

  • Python2.4至3.4版本下均可运行

如果是64位系统则直接besttrace替换besttrace32

脚本九:PrettyPing.sh

wget https://raw.githubusercontent.com/denilsonsa/prettyping/master/prettyping
mv prettyping /usr/local/bin
chmod +x /usr/local/bin/prettyping
prettyping 目标IP

Denilsonsa大佬写的Ping脚本

特点

  • 基本用途相当于 ping 命令

  • 附带了更美观精细地彩色图示

#!/usr/bin/env bash
#
# Written by Denilson Figueiredo de Sá <denilsonsa@gmail.com>
# MIT license
#
# Requirements:
# * bash (tested on 4.20, should work on older versions too)
# * awk (works with GNU awk, nawk, busybox awk, mawk)
# * ping (from iputils)
#
# More information:
# http://denilsonsa.github.io/prettyping/
# https://github.com/denilsonsa/prettyping
# http://www.reddit.com/r/linux/comments/1op98a/prettypingsh_a_better_ui_for_watching_ping/
# Third-party demonstration video: https://www.youtube.com/watch?v=ziEMY1BcikM

# TODO: Adjust how many items in the legend are printed based on the terminal width.
#
# TODO: Detect the following kinds of message and avoid printing it repeatedly.
# From 192.168.1.11: icmp_seq=4 Destination Host Unreachable
# Request timeout for icmp_seq 378
#
# TODO: Handle when a single message is spread over multiple lines. Specially,
# like in this case: https://bitbucket.org/denilsonsa/small_scripts/issue/5
#
# TODO: Print the destination (also) at the bottom bar. Useful after leaving
# the script running for quite some time.
#
# TODO: Print the destination as escape codes to xterm title.
#
# TODO: Print the current time in the beginning of each line.
#
# TODO: Implement audible ping.
#
# TODO: Autodetect the width of printf numbers, so they will always line up correctly.
#
# TODO: Test the behavior of this script upon receiving out-of-order packets, like these:
#   http://www.blug.linux.no/rfc1149/pinglogg.txt
#
# TODO? How will prettyping behave if it receives a duplicate response?

print_help() {
    cat << EOF
Usage: $MYNAME [prettyping parameters] <standard ping parameters>

This script is a wrapper around the system's "ping" tool. It will substitute
each ping response line by a colored character, giving a very compact overview
of the ping responses.

prettyping parameters:
  --[no]color      Enable/disable color output. (default: enabled)
  --[no]multicolor Enable/disable multi-color unicode output. Has no effect if
                     either color or unicode is disabled. (default: enabled)
  --[no]unicode    Enable/disable unicode characters. (default: enabled)
  --[no]legend     Enable/disable the latency legend. (default: enabled)
  --[no]terminal   Force the output designed to a terminal. (default: auto)
  --last <n>       Use the last "n" pings at the statistics line. (default: 60)
  --columns <n>    Override auto-detection of terminal dimensions.
  --lines <n>      Override auto-detection of terminal dimensions.
  --rttmin <n>     Minimum RTT represented in the unicode graph. (default: auto)
  --rttmax <n>     Maximum RTT represented in the unicode graph. (default: auto)
  --awkbin <exec>  Override the awk interpreter. (default: awk)
  --pingbin <exec> Override the ping tool. (default: ping)
  -6               Shortcut for: --pingbin ping6

ping parameters handled by prettyping:
  -a  Audible ping is not implemented yet.
  -f  Flood mode is not allowed in prettyping.
  -q  Quiet output is not allowed in prettyping.
  -R  Record route mode is not allowed in prettyping.
  -v  Verbose output seems to be the default mode in ping.

All other parameters are passed directly to ping.
EOF
}

# Thanks to people at #bash who pointed me at
# http://bash-hackers.org/wiki/doku.php/scripting/posparams
parse_arguments() {
    USE_COLOR=1
    USE_MULTICOLOR=1
    USE_UNICODE=1
    USE_LEGEND=1

    if [ -t 1 ]; then
        IS_TERMINAL=1
    else
        IS_TERMINAL=0
    fi

    LAST_N=60
    OVERRIDE_COLUMNS=0
    OVERRIDE_LINES=0
    RTT_MIN=auto
    RTT_MAX=auto

    PING_BIN="ping"
    #PING_BIN="./mockping.awk"
    PING_PARAMS=( )

    AWK_BIN="awk"
    AWK_PARAMS=( )

    while [[ $# != 0 ]] ; do
        case "$1" in
            -h | -help | --help )
                print_help
                exit
                ;;

            # Forbidden ping parameters within prettyping:
            -f )
                echo "${MYNAME}: You can't use the -f (flood) option."
                exit 1
                ;;
            -R )
                # -R prints extra information at each ping response.
                echo "${MYNAME}: You can't use the -R (record route) option."
                exit 1
                ;;
            -q )
                echo "${MYNAME}: You can't use the -q (quiet) option."
                exit 1
                ;;
            -v )
                # -v enables verbose output. However, it seems the output with
                # or without this option is the same. Anyway, prettyping will
                # strip this parameter.
                ;;
            # Note:
            #  Small values for -s parameter prevents ping from being able to
            #  calculate RTT.

            # New parameters:
            -a )
                # TODO: Implement audible ping for responses or for missing packets
                ;;

            -color        | --color        ) USE_COLOR=1 ;;
            -nocolor      | --nocolor      ) USE_COLOR=0 ;;
            -multicolor   | --multicolor   ) USE_MULTICOLOR=1 ;;
            -nomulticolor | --nomulticolor ) USE_MULTICOLOR=0 ;;
            -unicode      | --unicode      ) USE_UNICODE=1 ;;
            -nounicode    | --nounicode    ) USE_UNICODE=0 ;;
            -legend       | --legend       ) USE_LEGEND=1 ;;
            -nolegend     | --nolegend     ) USE_LEGEND=0 ;;
            -terminal     | --terminal     ) IS_TERMINAL=1 ;;
            -noterminal   | --noterminal   ) IS_TERMINAL=0 ;;

            -awkbin  | --awkbin  ) AWK_BIN="$2"  ; shift ;;
            -pingbin | --pingbin ) PING_BIN="$2" ; shift ;;
            -6 ) PING_BIN="ping6" ;;

            #TODO: Check if these parameters are numbers.
            -last    | --last    ) LAST_N="$2"           ; shift ;;
            -columns | --columns ) OVERRIDE_COLUMNS="$2" ; shift ;;
            -lines   | --lines   ) OVERRIDE_LINES="$2"   ; shift ;;
            -rttmin  | --rttmin  ) RTT_MIN="$2"          ; shift ;;
            -rttmax  | --rttmax  ) RTT_MAX="$2"          ; shift ;;

            * )
                PING_PARAMS+=("$1")
                ;;
        esac
        shift
    done

    if [[ "${RTT_MIN}" -gt 0 && "${RTT_MAX}" -gt 0 && "${RTT_MIN}" -ge "${RTT_MAX}" ]] ; then
        echo "${MYNAME}: Invalid --rttmin and -rttmax values."
        exit 1
    fi

    if [[ "${#PING_PARAMS[@]}" = 0 ]] ; then
        echo "${MYNAME}: Missing parameters, use --help for instructions."
        exit 1
    fi

    # Workaround for mawk:
    # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=593504
    local version="$(echo | "${AWK_BIN}" -W version 2>&1)"
    if [[ "${version}" == mawk* ]] ; then
        AWK_PARAMS+=(-W interactive)
    fi
}

MYNAME=`basename "$0"`
parse_arguments "$@"


export LC_ALL=C

# Warning! Ugly code ahead!
# The code is so ugly that the comments explaining it are
# bigger than the code itself!
#
# Suppose this:
#
#   cmd_a | cmd_b &
#
# I need the PID of cmd_a. How can I get it?
# In bash, $! will give me the PID of cmd_b.
#
# So, I came up with this ugly solution: open a subshell, like this:
#
# (
#     cmd_a &
#     echo "This is the PID I want $!"
#     wait
# ) | cmd_b


# Ignore Ctrl+C here.
# If I don't do this, this shell script is killed before
# ping and gawk can finish their work.
trap '' 2

# Now the ugly code.
(
    "${PING_BIN}" "${PING_PARAMS[@]}" &
    PING_PID="$!"

    # Commented out, because it looks like this line is not needed
    #trap "kill -2 $PING_PID ; exit 1" 2  # Catch Ctrl+C here

    wait
) 2>&1 | (
    if [ "${IS_TERMINAL}" = 1 ]; then
        # Print a message to notify the awk script about terminal size change.
        trap "echo SIGWINCH" 28
    fi

    # The trap must be in another subshell because otherwise it will interrupt
    # the "wait" commmand.
    while read line; do
        echo -E "$line"
    done
) 2>&1 | "${AWK_BIN}" "${AWK_PARAMS[@]}" '
# Weird that awk does not come with abs(), so I need to implement it.
function abs(x) {
    return ( (x < 0) ? -x : x )
}

# Ditto for ceiling function.
function ceil(x) {
    return (x == int(x)) ? x : int(x) + 1
}

# Local variables MUST be declared in argument list, else they are
# seen as global. Ugly, but that is how awk works.
function get_terminal_size(SIZE, SIZEA, HAS_DETECTED, CMD) {
    HAS_DETECTED = 0

    CMD = "stty -f /dev/tty size 2> /dev/null"

    if ( (CMD | getline SIZE) == 1 ) {
        split(SIZE, SIZEA, " ")
        LINES   = int(SIZEA[1])
        COLUMNS = int(SIZEA[2])
        HAS_DETECTED = 1
    }
    close(CMD)

    if ( HAS_DETECTED == 0 ) {
        CMD = "tput lines"
        if ( (CMD | getline SIZE) == 1 ) {
            LINES = int(SIZE)
            HAS_DETECTED = 1
        }
        close(CMD)

        CMD = "tput cols"
        if ( (CMD | getline SIZE) == 1 ) {
            COLUMNS = int(SIZE)
            HAS_DETECTED = 1
        }
        close(CMD)
    }

    if ( int('"${OVERRIDE_COLUMNS}"') ) { COLUMNS = int('"${OVERRIDE_COLUMNS}"') }
    if ( int('"${OVERRIDE_LINES}"')   ) { LINES   = int('"${OVERRIDE_LINES}"')   }
}

############################################################
# Functions related to cursor handling

# Function called whenever a non-dotted line is printed.
#
# It will move the cursor to the line next to the statistics and
# restore the default color.
function other_line_is_printed() {
    if ( IS_PRINTING_DOTS ) {
        if ( '"${IS_TERMINAL}"' ) {
            printf( ESC_DEFAULT ESC_NEXTLINE ESC_NEXTLINE "\n" )
        } else {
            printf( ESC_DEFAULT "\n" )
            print_statistics_bar()
        }
    }
    IS_PRINTING_DOTS = 0
    CURR_COL = 0
}

# Function called whenever a non-dotted line is repeated.
function other_line_is_repeated() {
    if ( other_line_times < 2 ) {
        return
    }
    if ( '"${IS_TERMINAL}"' ) {
        printf( ESC_DEFAULT ESC_ERASELINE "\r" )
    }
    printf( "Last message repeated %d times.", other_line_times )
    if ( ! '"${IS_TERMINAL}"' ) {
        printf( "\n" )
    }
}

# Function called whenever the repeating line has changed.
function other_line_finished_repeating() {
    if ( other_line_times >= 2 ) {
        if ( '"${IS_TERMINAL}"' ) {
            printf( "\n" )
        } else {
            other_line_is_repeated()
        }
    }
    other_line = ""
    other_line_times = 0
}

# Prints the newlines required for the live statistics.
#
# I need to print some newlines and then return the cursor back to its position
# to make sure the terminal will scroll.
#
# If the output is not a terminal, break lines on every LAST_N dots.
function print_newlines_if_needed() {
    if ( '"${IS_TERMINAL}"' ) {
        # COLUMNS-1 because I want to avoid bugs with the cursor at the last column
        if ( CURR_COL >= COLUMNS-1 ) {
            CURR_COL = 0
        }
        if ( CURR_COL == 0 ) {
            if ( IS_PRINTING_DOTS ) {
                printf( "\n" )
            }
            #printf( "\n" "\n" ESC_PREVLINE ESC_PREVLINE ESC_ERASELINE )
            printf( ESC_DEFAULT "\n" "\n" ESC_CURSORUP ESC_CURSORUP ESC_ERASELINE )
        }
    } else {
        if ( CURR_COL >= LAST_N ) {
            CURR_COL = 0
            printf( ESC_DEFAULT "\n" )
            print_statistics_bar()
        }
    }
    IS_PRINTING_DOTS = 1
}

############################################################
# Functions related to the data structure of "Last N" statistics.

# Clears the data structure.
function clear(d) {
    d["index"] = 0  # The next position to store a value
    d["size"]  = 0  # The array size, goes up to LAST_N
}

# This function stores the value to the passed data structure.
# The data structure holds at most LAST_N values. When it is full,
# a new value overwrite the oldest one.
function store(d, value) {
    d[d["index"]] = value
    d["index"]++
    if ( d["index"] >= d["size"] ) {
        if ( d["size"] < LAST_N ) {
            d["size"]++
        } else {
            d["index"] = 0
        }
    }
}

############################################################
# Functions related to processing the received response

function process_rtt(rtt) {
    # Overall statistics
    last_rtt = rtt
    total_rtt += rtt
    if ( last_seq == 0 ) {
        min_rtt = max_rtt = rtt
    } else {
        if ( rtt < min_rtt ) min_rtt = rtt
        if ( rtt > max_rtt ) max_rtt = rtt
    }

    # "Last N" statistics
    store(lastn_rtt,rtt)
}

function lost_a_packet() {
    print_newlines_if_needed()
    print_missing_response()

    last_seq++
    lost++
    store(lastn_lost, 1)
}

############################################################
# Functions related to printing the fancy ping response

# block_index, n, w are just local variables.
function print_response_legend(i, n, w) {
    if ( ! '"${USE_LEGEND}"' ) {
        return
    }
    if ( BLOCK_LEN > 1 ) {
        # w counts the cursor position in the current line. Because of the
        # escape codes, I need to jump through some hoops in order to count the
        # position correctly.
        w = 0
        n = "0 "
        w += length(n) + 1

        printf( n BLOCK[0] ESC_DEFAULT )

        for ( i=1 ; i<BLOCK_LEN ; i++ ) {
            n = sprintf( "%d ", BLOCK_RTT_MIN + ceil((i-1) * BLOCK_RTT_RANGE / (BLOCK_LEN - 2)) )
            w += length(n) + 1

            # Avoid breaking the legend at the end of the line.
            # Also avoids a background color change right at
            # the edge of the screen. (If it happens, the entire next line
            # will have that background color, which is not desired.)
            if ( '"${IS_TERMINAL}"' && w + 1 >= COLUMNS ) {
                printf( "\n" )
                w = length(n) + 1
            } else {
                printf( " " )
                w += 1
            }

            printf( n BLOCK[i] ESC_DEFAULT )
        }
        printf( " ∞\n" )
    }

    # Useful code for debugging.
    #for ( i=0 ; i<=BLOCK_RTT_MAX ; i++ ) {
    #    print_received_response(i)
    #    printf( ESC_DEFAULT "%4d\n", i )
    #}
}

# block_index is just a local variable.
function print_received_response(rtt, block_index) {
    if ( rtt < BLOCK_RTT_MIN ) {
        block_index = 0
    } else if ( rtt >= BLOCK_RTT_MAX ) {
        block_index = BLOCK_LEN - 1
    } else {
        block_index = 1 + int((rtt - BLOCK_RTT_MIN) * (BLOCK_LEN - 2) / BLOCK_RTT_RANGE)
    }
    printf( BLOCK[block_index] )
    CURR_COL++
}

function print_missing_response(rtt) {
    printf( ESC_RED "!" )
    CURR_COL++
}

############################################################
# Functions related to printing statistics

# All arguments are just local variables.
function print_overall(percentage_lost, avg_rtt) {
    # Handling division by zero.
    # Note that mawk does not consider division by zero an error, while all
    # other awk implementations abort in such case.
    # https://stackoverflow.com/questions/14581966/why-does-awk-produce-different-results-for-division-by-zero

    avg_rtt = ( received > 0 ) ? (total_rtt/received) : 0
    percentage_lost = ( lost+received > 0 ) ? (lost*100/(lost+received)) : 0

    if ( '"${IS_TERMINAL}"' ) {
        printf( "%2d/%3d (%2d%%) lost; %4.0f/" ESC_BOLD "%4.0f" ESC_DEFAULT "/%4.0fms; last: " ESC_BOLD "%4.0f" ESC_DEFAULT "ms",
            lost,
            lost+received,
            percentage_lost,
            min_rtt,
            avg_rtt,
            max_rtt,
            last_rtt )
    } else {
        printf( "%2d/%3d (%2d%%) lost; %4.0f/" ESC_BOLD "%4.0f" ESC_DEFAULT "/%4.0fms",
            lost,
            lost+received,
            percentage_lost,
            min_rtt,
            avg_rtt,
            max_rtt )
    }
}

# All arguments are just local variables.
function print_last_n(i, percentage_lost, sum, min, avg, max, diffs) {
    # Calculate and print the lost packets statistics
    sum = 0
    for ( i=0 ; i<lastn_lost["size"] ; i++ ) {
        sum += lastn_lost[i]
    }
    percentage_lost = (lastn_lost["size"] > 0) ? (sum*100/lastn_lost["size"]) : 0
    printf( "%2d/%3d (%2d%%) lost; ",
        sum,
        lastn_lost["size"],
        percentage_lost )

    # Calculate the min/avg/max rtt times
    sum = diffs = 0
    min = max = lastn_rtt[0]
    for ( i=0 ; i<lastn_rtt["size"] ; i++ ) {
        sum += lastn_rtt[i]
        if ( lastn_rtt[i] < min ) min = lastn_rtt[i]
        if ( lastn_rtt[i] > max ) max = lastn_rtt[i]
    }
    avg = (lastn_rtt["size"]) ? (sum/lastn_rtt["size"]) : 0

    # Calculate mdev (mean absolute deviation)
    for ( i=0 ; i<lastn_rtt["size"] ; i++ ) {
        diffs += abs(lastn_rtt[i] - avg)
    }
    if ( lastn_rtt["size"] > 0 ) {
        diffs /= lastn_rtt["size"]
    }

    # Print the rtt statistics
    printf( "%4.0f/" ESC_BOLD "%4.0f" ESC_DEFAULT "/%4.0f/%4.0fms (last %d)",
        min,
        avg,
        max,
        diffs,
        lastn_rtt["size"] )
}

function print_statistics_bar() {
    if ( '"${IS_TERMINAL}"' ) {
        printf( ESC_SAVEPOS ESC_DEFAULT )

        printf( ESC_NEXTLINE ESC_ERASELINE )
        print_overall()
        printf( ESC_NEXTLINE ESC_ERASELINE )
        print_last_n()

        printf( ESC_UNSAVEPOS )
    } else {
        print_overall()
        printf( "\n" )
        print_last_n()
        printf( "\n" )
    }
}

function print_statistics_bar_if_terminal() {
    if ( '"${IS_TERMINAL}"' ) {
        print_statistics_bar()
    }
}

############################################################
# Initializations
BEGIN {
    # Easy way to get each value from ping output
    FS = "="

    ############################################################
    # General internal variables

    # This is needed to keep track of lost packets
    last_seq = 0

    # The previously printed non-ping-response line
    other_line = ""
    other_line_times = 0

    # Variables to keep the screen clean
    IS_PRINTING_DOTS = 0
    CURR_COL = 0

    ############################################################
    # Variables related to "overall" statistics
    received = 0
    lost = 0
    total_rtt = 0
    min_rtt = 0
    max_rtt = 0
    last_rtt = 0

    ############################################################
    # Variables related to "last N" statistics
    LAST_N = int('"${LAST_N}"')

    # Data structures for the "last N" statistics
    clear(lastn_lost)
    clear(lastn_rtt)

    ############################################################
    # Terminal height and width

    # These are sane defaults, in case we cannot query the actual terminal size
    LINES    = 24
    COLUMNS  = 80

    # Auto-detecting the terminal size
    get_terminal_size()
    if ( '"${IS_TERMINAL}"' && COLUMNS <= 50 ) {
        print "Warning: terminal width is too small."
    }

    ############################################################
    # ANSI escape codes

    # Color escape codes.
    # Fortunately, awk defaults any unassigned variable to an empty string.
    if ( '"${USE_COLOR}"' ) {
        ESC_DEFAULT = "\033[0m"
        ESC_BOLD    = "\033[1m"
        #ESC_BLACK   = "\033[0;30m"
        #ESC_GRAY    = "\033[1;30m"
        ESC_RED     = "\033[0;31m"
        ESC_GREEN   = "\033[0;32m"
        ESC_YELLOW  = "\033[0;33m"
        ESC_BLUE    = "\033[0;34m"
        ESC_MAGENTA = "\033[0;35m"
        ESC_CYAN    = "\033[0;36m"
        ESC_WHITE   = "\033[0;37m"
        ESC_YELLOW_ON_GREEN = "\033[42;33m"
        ESC_RED_ON_YELLOW   = "\033[43;31m"
    }
    # Other escape codes, see:
    # http://en.wikipedia.org/wiki/ANSI_escape_code
    # http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
    ESC_NEXTLINE     = "\n"
    ESC_CURSORUP     = "\033[A"
    ESC_CURSORDOWN   = "\033[B"
    ESC_SCROLLUP     = "\033[S"
    ESC_SCROLLDOWN   = "\033[T"
    ESC_ERASELINEEND = "\033[0K"
    ESC_ERASELINE    = "\033[2K"
    ESC_SAVEPOS      = "\0337"
    ESC_UNSAVEPOS    = "\0338"

    # I am avoiding these escapes as they are not listed in:
    # http://vt100.net/docs/vt100-ug/chapter3.html
    #ESC_PREVLINE   = "\033[F"
    #ESC_SAVEPOS    = "\033[s"
    #ESC_UNSAVEPOS  = "\033[u"

    # I am avoiding this to improve compatibility with (older versions of) tmux
    #ESC_NEXTLINE   = "\033[E"

    ############################################################
    # Unicode characters (based on https://github.com/holman/spark )
    if ( '"${USE_UNICODE}"' ) {
        BLOCK[ 0] = ESC_GREEN "▁"
        BLOCK[ 1] = ESC_GREEN "▂"
        BLOCK[ 2] = ESC_GREEN "▃"
        BLOCK[ 3] = ESC_GREEN "▄"
        BLOCK[ 4] = ESC_GREEN "▅"
        BLOCK[ 5] = ESC_GREEN "▆"
        BLOCK[ 6] = ESC_GREEN "▇"
        BLOCK[ 7] = ESC_GREEN "█"
        BLOCK[ 8] = ESC_YELLOW_ON_GREEN "▁"
        BLOCK[ 9] = ESC_YELLOW_ON_GREEN "▂"
        BLOCK[10] = ESC_YELLOW_ON_GREEN "▃"
        BLOCK[11] = ESC_YELLOW_ON_GREEN "▄"
        BLOCK[12] = ESC_YELLOW_ON_GREEN "▅"
        BLOCK[13] = ESC_YELLOW_ON_GREEN "▆"
        BLOCK[14] = ESC_YELLOW_ON_GREEN "▇"
        BLOCK[15] = ESC_YELLOW_ON_GREEN "█"
        BLOCK[16] = ESC_RED_ON_YELLOW "▁"
        BLOCK[17] = ESC_RED_ON_YELLOW "▂"
        BLOCK[18] = ESC_RED_ON_YELLOW "▃"
        BLOCK[19] = ESC_RED_ON_YELLOW "▄"
        BLOCK[20] = ESC_RED_ON_YELLOW "▅"
        BLOCK[21] = ESC_RED_ON_YELLOW "▆"
        BLOCK[22] = ESC_RED_ON_YELLOW "▇"
        BLOCK[23] = ESC_RED_ON_YELLOW "█"
        if ( '"${USE_MULTICOLOR}"' && '"${USE_COLOR}"' ) {
            # Multi-color version:
            BLOCK_LEN = 24
            BLOCK_RTT_MIN = 10
            BLOCK_RTT_MAX = 230
        } else {
            # Simple version:
            BLOCK_LEN = 8
            BLOCK_RTT_MIN = 25
            BLOCK_RTT_MAX = 175
        }
    } else {
        BLOCK[ 0] = ESC_GREEN "_"
        BLOCK[ 1] = ESC_GREEN "."
        BLOCK[ 2] = ESC_GREEN "o"
        BLOCK[ 3] = ESC_GREEN "O"
        BLOCK[ 4] = ESC_YELLOW "_"
        BLOCK[ 5] = ESC_YELLOW "."
        BLOCK[ 6] = ESC_YELLOW "o"
        BLOCK[ 7] = ESC_YELLOW "O"
        BLOCK[ 8] = ESC_RED "_"
        BLOCK[ 9] = ESC_RED "."
        BLOCK[10] = ESC_RED "o"
        BLOCK[11] = ESC_RED "O"
        if ( '"${USE_MULTICOLOR}"' && '"${USE_COLOR}"' ) {
            # Multi-color version:
            BLOCK_LEN = 12
            BLOCK_RTT_MIN = 20
            BLOCK_RTT_MAX = 220
        } else {
            # Simple version:
            BLOCK_LEN = 4
            BLOCK_RTT_MIN = 75
            BLOCK_RTT_MAX = 225
        }
    }

    if ( int('"${RTT_MIN}"') > 0 && int('"${RTT_MAX}"') > 0 ) {
        BLOCK_RTT_MIN = int('"${RTT_MIN}"')
        BLOCK_RTT_MAX = int('"${RTT_MAX}"')
    } else if ( int('"${RTT_MIN}"') > 0 ) {
        BLOCK_RTT_MIN = int('"${RTT_MIN}"')
        BLOCK_RTT_MAX = BLOCK_RTT_MIN * (BLOCK_LEN - 1)
    } else if ( int('"${RTT_MAX}"') > 0 ) {
        BLOCK_RTT_MAX = int('"${RTT_MAX}"')
        BLOCK_RTT_MIN = int(BLOCK_RTT_MAX / (BLOCK_LEN - 1))
    }

    BLOCK_RTT_RANGE = BLOCK_RTT_MAX - BLOCK_RTT_MIN
    print_response_legend()
}

############################################################
# Main loop
{
    if ( $0 ~ /^[0-9]+ bytes from .*: icmp_[rs]eq=[0-9]+ ttl=[0-9]+ time=[0-9.]+ *ms/ ) {
        # Sample line from ping:
        # 64 bytes from 8.8.8.8: icmp_seq=1 ttl=49 time=184 ms
        if ( other_line_times >= 2 ) {
            other_line_finished_repeating()
        }

        # $1 = useless prefix string
        # $2 = icmp_seq
        # $3 = ttl
        # $4 = time

        # This must be called before incrementing the last_seq variable!
        rtt = int($4)
        process_rtt(rtt)

        seq = int($2)

        while ( last_seq < seq - 1 ) {
            lost_a_packet()
        }

        # Received a packet
        print_newlines_if_needed()
        print_received_response(rtt)

        # In case of receiving multiple responses with the same seq number, it
        # is better to use "last_seq = seq" than to increment last_seq.
        last_seq = seq

        received++
        store(lastn_lost, 0)

        print_statistics_bar_if_terminal()
    } else if ( $0 ~ /^.*onnected to.*, seq=[0-9]+ time=[0-9.]+ *ms/ ) {
        # Sample line from httping:
        # connected to 200.149.119.168:80 (273 bytes), seq=0 time=129.86 ms 
        if ( other_line_times >= 2 ) {
            other_line_finished_repeating()
        }

        seq = $0
        sub(/.* seq=/, "", seq)
        seq = int(seq)

        rtt = $0
        sub(/.* time=/, "", rtt)
        rtt = int(rtt)

        process_rtt(rtt)

        while ( last_seq < seq - 1 ) {
            lost_a_packet()
        }

        # Received a packet
        print_newlines_if_needed()
        print_received_response(rtt)

        # In case of receiving multiple responses with the same seq number, it
        # is better to use "last_seq = seq" than to increment last_seq.
        last_seq = seq

        received++
        store(lastn_lost, 0)

        print_statistics_bar_if_terminal()
    } else if ( $0 == "" ) {
        # Do nothing on blank lines.
    } else if ( $0 == "error shutting down ssl" ) {
        # Common error message when using httping, ignore it.
    } else if ( $0 ~ /^Request timeout for icmp_seq [0-9]+/ ) {
        # Reply timeout is printed on Mac OS X.

        if ( other_line_times >= 2 ) {
            other_line_finished_repeating()
        }

        lost_a_packet()

        # Making sure the last_seq number is correct.
        gsub(/.* icmp_seq /, "")
        seq = int($0)
        last_seq = seq

        print_newlines_if_needed()
        print_statistics_bar_if_terminal()
    } else if ( $0 ~ /^SIGWINCH$/ ) {
        get_terminal_size()

        if ( IS_PRINTING_DOTS ) {
            if ( CURR_COL >= COLUMNS-1 ) {
                # Not enough space anyway.
            } else {
                # Making up room in case the number of lines has changed.
                printf( ESC_NEXTLINE ESC_NEXTLINE ESC_CURSORUP ESC_CURSORUP )
                # Moving to the correct column and erasing the rest of the line.
                printf( "\033[" (CURR_COL+1) "G" ESC_DEFAULT ESC_ERASELINEEND )
            }

            print_newlines_if_needed()
            print_statistics_bar_if_terminal()
        }
    } else {
        other_line_is_printed()
        original_line = $0
        gsub(/icmp_seq[= ][0-9]+/, "")
        if ( $0 == other_line ) {
            other_line_times++
            if ( '"${IS_TERMINAL}"' ) {
                other_line_is_repeated()
            }
        } else {
            other_line_finished_repeating()
            other_line = $0
            other_line_times = 1
            printf( "%s\n", original_line )
        }
    }

    # Not needed when the output is a terminal, but does not hurt either.
    fflush()
}'

脚本十:mPing.sh

wget https://raw.githubusercontent.com/helloxz/mping/master/mping.sh
bash mping.sh

Mr.zou大佬写的脚本

特点

  • 方便测试回程Ping值

  • 目前支持众多区域和各大运营商

#!/bin/bash
#####        一键Ping测试            #####
#####        Author:xiaoz.me            #####
#####        Update:2019-06-03        #####

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin:/sbin
export PATH

#获取服务器公网IP
osip=$(curl https://api.ttt.sh/ip/qqwry/?type=txt)

location=(
        '四川 电信'
        '天津 电信'
        '江苏 电信'
        '四川 联通'
        '河北 联通'
        '浙江 联通'
        '安徽 移动'
        '山东 移动'
        '四川 移动'
        '广东 移动'
    )
#各地区DNS,来源于http://dns.lisect.com/ and https://www.ip.cn/dns.html
dnsip=(
    '61.139.2.69'        #四川 电信
    '219.150.32.132'    #天津 电信
    '218.2.2.2'            #江苏 电信
    '119.6.6.6'            #四川 联通
    '202.99.160.68'        #河北 联通
    '221.12.1.227'        #浙江 联通
    '211.138.180.2'        #安徽 移动
    '218.201.96.130'    #山东 移动
    '223.87.238.22'        #四川 移动
    '211.139.129.222'    #广东 移动
)
echo '---------------------------------------------------------------------------'
echo "您的本机IP为:[$osip]"
function mping(){
    num=0
    #Ping次数
    pnum=$1

    #echo '---------------------------------------------------------------------------'
    echo "正在进行Ping测试,请稍后..."
    echo '---------------------------------------------------------------------------'

    while(( $num<10 ))
    do
        ping ${dnsip[$num]} -c $pnum > /tmp/${dnsip[$num]}.txt
        echo 【${location[$num]}】 - ${dnsip[$num]}
        echo ''
        tail -2 /tmp/${dnsip[$num]}.txt
        echo '---------------------------------------------------------------------------'
        let "num++"
    done
    echo "【参数说明】"
    echo "x% packet loss: 丢包率"
    echo "min: 最低延迟"
    echo "avg: 平均延迟"
    echo "max: 最高延迟"
    echo "mdev: 平均偏差"

    echo '---------------------------------------------------------------------------'
}

function moretrace(){
    #检查besttrace是否存在
    if [ ! -f "./besttrace" ]
    then
        #下载besttrace
        wget -q http://soft.xiaoz.org/linux/besttrace
        #添加执行权限
        chmod +x ./besttrace
    fi

    #进行路由跟踪
    echo '---------------------------------------------------------------------------'
    echo '正在进行路由跟踪,请稍后...'
    echo '---------------------------------------------------------------------------'
    echo '【四川电信】 - 61.139.2.69'
    echo ''
    ./besttrace -q 1 61.139.2.69
    echo '---------------------------------------------------------------------------'

    echo '【河北 联通】- 202.99.160.68'
    echo ''
    ./besttrace -q 1 202.99.160.68
    echo '---------------------------------------------------------------------------'

    echo '【安徽 移动】 - 211.138.180.2'
    echo ''
    ./besttrace -q 1 211.138.180.2
    echo '---------------------------------------------------------------------------'
}

mping 10
echo ''
moretrace
echo ''
echo '此结果由mping生成:https://www.xiaoz.me/archives/13044'
echo ''

脚本十一:Superspeed.sh

wget https://raw.githubusercontent.com/oooldking/script/master/superspeed.sh && chmod +x superspeed.sh && ./superspeed.sh

老鬼大佬的Superspeed测试脚本

特点

  • 一键全面测速功能

  • 测试服务器到全国北方南方,电信,联通,移动的速度

#!/usr/bin/env bash
#
# Description: Test your server's network with Speedtest to China
#
# Copyright (C) 2017 - 2017 Oldking <oooldking@gmail.com>
#
# URL: https://www.oldking.net/305.html
#

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
SKYBLUE='\033[0;36m'
PLAIN='\033[0m'

# check root
[[ $EUID -ne 0 ]] && echo -e "${RED}Error:${PLAIN} This script must be run as root!" && exit 1

# check python
if  [ ! -e '/usr/bin/python' ]; then
        echo -e
        read -p "${RED}Error:${PLAIN} python is not install. You must be install python command at first.\nDo you want to install? [y/n]" is_install
        if [[ ${is_install} == "y" || ${is_install} == "Y" ]]; then
            if [ "${release}" == "centos" ]; then
                        yum -y install python
                else
                        apt-get -y install python
                fi
        else
            exit
        fi
        
fi

# check wget
if  [ ! -e '/usr/bin/wget' ]; then
        echo -e
        read -p "${RED}Error:${PLAIN} wget is not install. You must be install wget command at first.\nDo you want to install? [y/n]" is_install
        if [[ ${is_install} == "y" || ${is_install} == "Y" ]]; then
                if [ "${release}" == "centos" ]; then
                        yum -y install wget
                else
                        apt-get -y install wget
                fi
        else
                exit
        fi
fi


clear
echo "#############################################################"
echo "# Description: Test your server's network with Speedtest    #"
echo "# Intro:  https://www.oldking.net/305.html                  #"
echo "# Author: Oldking <oooldking@gmail.com>                     #"
echo "# Github: https://github.com/oooldking                      #"
echo "#############################################################"
echo
echo "测试服务器到"
echo -ne "1.中国电信 2.中国联通 3.中国移动 4.本地默认 5.全面测速"

while :; do echo
        read -p "请输入数字选择: " telecom
        if [[ ! $telecom =~ ^[1-5]$ ]]; then
                echo "输入错误! 请输入正确的数字!"
        else
                break   
        fi
done

if [[ ${telecom} == 1 ]]; then
        telecomName="电信"
        echo -e "\n选择最靠近你的方位"
    echo -ne "1.北方 2.南方"
    while :; do echo
            read -p "请输入数字选择: " pos
            if [[ ! $pos =~ ^[1-2]$ ]]; then
                    echo "输入错误! 请输入正确的数字!"
            else
                    break
            fi
    done
    echo -e "\n选择最靠近你的城市"
    if [[ ${pos} == 1 ]]; then
        echo -ne "1.郑州 2.襄阳"
        while :; do echo
                read -p "请输入数字选择: " city
                if [[ ! $city =~ ^[1-2]$ ]]; then
                        echo "输入错误! 请输入正确的数字!"
                else
                        break
            fi
        done
        if [[ ${city} == 1 ]]; then
                num=4595
                cityName="郑州"
        fi
        if [[ ${city} == 2 ]]; then
                num=12637
                cityName="襄阳"
        fi
    fi
    if [[ ${pos} == 2 ]]; then
        echo -ne "1.上海 2.杭州 3.南宁 4.南昌 5.长沙 6.深圳 7.重庆 8.成都"
        while :; do echo
                read -p "请输入数字选择: " city
                if [[ ! $city =~ ^[1-8]$ ]]; then
                        echo "输入错误! 请输入正确的数字!"
                else
                        break
            fi
        done
        if [[ ${city} == 1 ]]; then
                num=3633
                cityName="上海"
        fi
        if [[ ${city} == 2 ]]; then
                num=7509
                cityName="杭州"
        fi
        if [[ ${city} == 3 ]]; then
                num=10305
                cityName="南宁"
        fi
        if [[ ${city} == 4 ]]; then
                num=7230
                cityName="南昌"
        fi
        if [[ ${city} == 5 ]]; then
                num=6132
                cityName="长沙"
        fi
        if [[ ${city} == 6 ]]; then
                num=5081
                cityName="深圳"
        fi
        if [[ ${city} == 7 ]]; then
                num=6592
                cityName="重庆"
        fi
        if [[ ${city} == 8 ]]; then
                num=4624
                cityName="成都"
        fi
    fi
fi

if [[ ${telecom} == 2 ]]; then
        telecomName="联通"
    echo -ne "\n1.北方 2.南方"
    while :; do echo
            read -p "请输入数字选择: " pos
            if [[ ! $pos =~ ^[1-2]$ ]]; then
                    echo "输入错误! 请输入正确的数字!"
            else
                    break
            fi
    done
    echo -e "\n选择最靠近你的城市"
    if [[ ${pos} == 1 ]]; then
        echo -ne "1.沈阳 2.长春 3.哈尔滨 4.天津 5.济南 6.北京 7.郑州 8.西安 9.太原 10.宁夏 11.兰州 12.西宁"
        while :; do echo
                read -p "请输入数字选择: " city
                if [[ ! $city =~ ^(([1-9])|(1([0-2]{1})))$ ]]; then
                        echo "输入错误! 请输入正确的数字!"
                else
                        break
            fi
        done
        if [[ ${city} == 1 ]]; then
                num=5017
                cityName="沈阳"
        fi
        if [[ ${city} == 2 ]]; then
                num=9484
                cityName="长春"
        fi
        if [[ ${city} == 3 ]]; then
                num=5460
                cityName="哈尔滨"
        fi
        if [[ ${city} == 4 ]]; then
                num=5475
                cityName="天津"
        fi
        if [[ ${city} == 5 ]]; then
                num=5039
                cityName="济南"
        fi
        if [[ ${city} == 6 ]]; then
                num=5145
                cityName="北京"
        fi
        if [[ ${city} == 7 ]]; then
                num=5131
                cityName="郑州"
        fi
        if [[ ${city} == 8 ]]; then
                num= 4863
                cityName="西安"
        fi
        if [[ ${city} == 9 ]]; then
                num=12868
                cityName="太原"
        fi
        if [[ ${city} == 10 ]]; then
                num=5509
                cityName="宁夏"
        fi
        if [[ ${city} == 11 ]]; then
                num=4690
                cityName="兰州"
        fi
        if [[ ${city} == 12 ]]; then
                num=5992
                cityName="西宁"
        fi
    fi
    if [[ ${pos} == 2 ]]; then
        echo -ne "1.上海 2.杭州 3.南宁 4.合肥 5.南昌 6.长沙 7.深圳 8.广州 9.重庆 10.昆明 11.成都"
        while :; do echo
                read -p "请输入数字选择: " city
                if [[ ! $city =~ ^(([1-9])|(1([0-1]{1})))$ ]]; then
                        echo "输入错误! 请输入正确的数字!"
                else
                        break
            fi
        done
        if [[ ${city} == 1 ]]; then
                num=5083
                cityName="上海"
        fi
        if [[ ${city} == 2 ]]; then
                num=5300
                cityName="杭州"
        fi
        if [[ ${city} == 3 ]]; then
                num=5674
                cityName="南宁"
        fi
        if [[ ${city} == 4 ]]; then
                num=5724
                cityName="合肥"
        fi
        if [[ ${city} == 5 ]]; then
                num=5079
                cityName="南昌"
        fi
        if [[ ${city} == 6 ]]; then
                num=4870
                cityName="长沙"
        fi
        if [[ ${city} == 7 ]]; then
                num=10201
                cityName="深圳"
        fi
        if [[ ${city} == 8 ]]; then
                num=3891
                cityName="广州"
        fi
        if [[ ${city} == 9 ]]; then
                num=5726
                cityName="重庆"
        fi
        if [[ ${city} == 10 ]]; then
                num=5103
                cityName="昆明"
        fi
        if [[ ${city} == 11 ]]; then
                num=2461
                cityName="成都"
        fi
    fi
fi

if [[ ${telecom} == 3 ]]; then
        telecomName="移动"
    echo -ne "\n1.北方 2.南方"
    while :; do echo
            read -p "请输入数字选择: " pos
            if [[ ! $pos =~ ^[1-2]$ ]]; then
                    echo "输入错误! 请输入正确的数字!"
            else
                    break
            fi
    done
    echo -e "\n选择最靠近你的城市"
    if [[ ${pos} == 1 ]]; then
        echo -ne "1.西安"
        while :; do echo
                read -p "请输入数字选择: " city
                if [[ ! $city =~ ^[1]$ ]]; then
                        echo "输入错误! 请输入正确的数字!"
                else
                        break
            fi
        done
        if [[ ${city} == 1 ]]; then
                num=5292
        fi
    fi
    if [[ ${pos} == 2 ]]; then
        echo -ne "1.上海 2.宁波 3.无锡 4.杭州 5.合肥 6.成都"
        while :; do echo
                read -p "请输入数字选择: " city
                if [[ ! $city =~ ^[1-6]$ ]]; then
                        echo "输入错误! 请输入正确的数字!"
                else
                        break
            fi
        done
        if [[ ${city} == 1 ]]; then
                num=4665
                cityName="上海"
        fi
        if [[ ${city} == 2 ]]; then
                num=6715
                cityName="宁波"
        fi
        if [[ ${city} == 3 ]]; then
                num=5122
                cityName="无锡"
        fi
        if [[ ${city} == 4 ]]; then
                num=4647
                cityName="杭州"
        fi
        if [[ ${city} == 5 ]]; then
                num=4377 
                cityName="合肥"
        fi
        if [[ ${city} == 6 ]]; then
                num=4575
                cityName="成都"
        fi
    fi
fi

# install speedtest
if  [ ! -e '/tmp/speedtest.py' ]; then
    wget --no-check-certificate -P /tmp https://raw.github.com/sivel/speedtest-cli/master/speedtest.py > /dev/null 2>&1
fi
chmod a+rx /tmp/speedtest.py

result() {
    download=`cat /tmp/speed.log | awk -F ':' '/Download/{print $2}'`
    upload=`cat /tmp/speed.log | awk -F ':' '/Upload/{print $2}'`
    hostby=`cat /tmp/speed.log | awk -F ':' '/Hosted/{print $1}'`
    latency=`cat /tmp/speed.log | awk -F ':' '/Hosted/{print $2}'`
    clear
    echo "$hostby"
    echo "延迟  : $latency"
    echo "上传  : $upload"
    echo "下载  : $download"
    echo -ne "\n当前时间: "
    echo $(date +%Y-%m-%d" "%H:%M:%S)
}

speed_test(){
    temp=$(python /tmp/speedtest.py --server $1 --share 2>&1)
    is_down=$(echo "$temp" | grep 'Download') 
    if [[ ${is_down} ]]; then
        local REDownload=$(echo "$temp" | awk -F ':' '/Download/{print $2}')
        local reupload=$(echo "$temp" | awk -F ':' '/Upload/{print $2}')
        local relatency=$(echo "$temp" | awk -F ':' '/Hosted/{print $2}')
        temp=$(echo "$relatency" | awk -F '.' '{print $1}')
        if [[ ${temp} -gt 1000 ]]; then
            relatency=" 000.000 ms"
        fi
        local nodeName=$2

        printf "${YELLOW}%-17s${GREEN}%-18s${RED}%-20s${SKYBLUE}%-12s${PLAIN}\n" "${nodeName}" "${reupload}" "${REDownload}" "${relatency}"
    else
        local cerror="ERROR"
    fi
}

if [[ ${telecom} =~ ^[1-3]$ ]]; then
    python /tmp/speedtest.py --server ${num} --share 2>/dev/null | tee /tmp/speed.log 2>/dev/null
    is_down=$(cat /tmp/speed.log | grep 'Download')

    if [[ ${is_down} ]]; then
        result
        echo "测试到 ${cityName}${telecomName} 完成!"
        rm -rf /tmp/speedtest.py
        rm -rf /tmp/speed.log
    else
        echo -e "\n${RED}ERROR:${PLAIN} 当前节点不可用,请更换其他节点,或换个时间段再测试。"
    fi
fi

if [[ ${telecom} == 4 ]]; then
    python /tmp/speedtest.py | tee /tmp/speed.log
    result
    echo "本地测试完成!"
    rm -rf /tmp/speedtest.py
    rm -rf /tmp/speed.log
fi

if [[ ${telecom} == 5 ]]; then
    echo ""
    printf "%-14s%-18s%-20s%-12s\n" "Node Name" "Upload Speed" "Download Speed" "Latency"
    start=$(date +%s) 
    speed_test '6435' '襄阳电信'
    speed_test '7509' '昆明电信'
    speed_test '3633' '上海电信'
    speed_test '4624' '成都电信'
    speed_test '5017' '沈阳联通'
    speed_test '4863' '西安联通'
    speed_test '5083' '上海联通'
    speed_test '5726' '重庆联通'
    speed_test '5292' '西安移动'
    speed_test '16314' '山东移动'
    speed_test '6715' '宁波移动'
    speed_test '4575' '成都移动'
    end=$(date +%s)  
    rm -rf /tmp/speedtest.py
    echo ""
    time=$(( $end - $start ))
    if [[ $time -gt 60 ]]; then
        min=$(expr $time / 60)
        sec=$(expr $time % 60)
        echo -ne "花费时间:${min} 分 ${sec} 秒"
    else
        echo -ne "花费时间:${time} 秒"
    fi
    echo -ne "\n当前时间: "
    echo $(date +%Y-%m-%d" "%H:%M:%S)
    echo "全面测试完成!"
fi

老鬼大佬的脚本已失效,这里找了一个替补脚本

bash <(curl -Lso- https://git.io/superspeed)
#!/usr/bin/env bash

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
PURPLE="\033[0;35m"
CYAN='\033[0;36m'
PLAIN='\033[0m'

checkroot(){
    [[ $EUID -ne 0 ]] && echo -e "${RED}请使用 root 用户运行本脚本!${PLAIN}" && exit 1
}

checksystem() {
    if [ -f /etc/redhat-release ]; then
        release="centos"
    elif cat /etc/issue | grep -Eqi "debian"; then
        release="debian"
    elif cat /etc/issue | grep -Eqi "ubuntu"; then
        release="ubuntu"
    elif cat /etc/issue | grep -Eqi "centos|red hat|redhat"; then
        release="centos"
    elif cat /proc/version | grep -Eqi "debian"; then
        release="debian"
    elif cat /proc/version | grep -Eqi "ubuntu"; then
        release="ubuntu"
    elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then
        release="centos"
    fi
}

checkpython() {
    if  [ ! -e '/usr/bin/python' ]; then
            echo "正在安装 Python"
                if [ "${release}" == "centos" ]; then
                        yum update > /dev/null 2>&1
                        yum -y install python > /dev/null 2>&1
                    else
                        apt-get update > /dev/null 2>&1
                        apt-get -y install python > /dev/null 2>&1
                    fi
            
    fi
}

checkcurl() {
    if  [ ! -e '/usr/bin/curl' ]; then
            echo "正在安装 Curl"
                if [ "${release}" == "centos" ]; then
                    yum update > /dev/null 2>&1
                    yum -y install curl > /dev/null 2>&1
                else
                    apt-get update > /dev/null 2>&1
                    apt-get -y install curl > /dev/null 2>&1
                fi
    fi
}

checkwget() {
    if  [ ! -e '/usr/bin/wget' ]; then
            echo "正在安装 Wget"
                if [ "${release}" == "centos" ]; then
                    yum update > /dev/null 2>&1
                    yum -y install wget > /dev/null 2>&1
                else
                    apt-get update > /dev/null 2>&1
                    apt-get -y install wget > /dev/null 2>&1
                fi
    fi
}

checkspeedtest() {
    if  [ ! -e './speedtest-cli/speedtest' ]; then
        echo "正在安装 Speedtest-cli"
        wget --no-check-certificate -qO speedtest.tgz https://bintray.com/ookla/download/download_file?file_path=ookla-speedtest-1.0.0-$(uname -m)-linux.tgz > /dev/null 2>&1
    fi
    mkdir -p speedtest-cli && tar zxvf speedtest.tgz -C ./speedtest-cli/ > /dev/null 2>&1 && chmod a+rx ./speedtest-cli/speedtest
}

speed_test(){
    speedLog="./speedtest.log"
    true > $speedLog
        speedtest-cli/speedtest -p no -s $1 --accept-license > $speedLog 2>&1
        is_upload=$(cat $speedLog | grep 'Upload')
        if [[ ${is_upload} ]]; then
            local REDownload=$(cat $speedLog | awk -F ' ' '/Download/{print $3}')
            local reupload=$(cat $speedLog | awk -F ' ' '/Upload/{print $3}')
            local relatency=$(cat $speedLog | awk -F ' ' '/Latency/{print $2}')
            
            local nodeID=$1
            local nodeLocation=$2
            local nodeISP=$3
            
            strnodeLocation="${nodeLocation}      "
            LANG=C
            #echo $LANG
            
            temp=$(echo "${REDownload}" | awk -F ' ' '{print $1}')
            if [[ $(awk -v num1=${temp} -v num2=0 'BEGIN{print(num1>num2)?"1":"0"}') -eq 1 ]]; then
                printf "${RED}%-6s${YELLOW}%s%s${GREEN}%-24s${CYAN}%s%-10s${BLUE}%s%-10s${PURPLE}%-8s${PLAIN}\n" "${nodeID}"  "${nodeISP}" "|" "${strnodeLocation:0:24}" "↑ " "${reupload}" "↓ " "${REDownload}" "${relatency}" | tee -a $log
            fi
        else
            local cerror="ERROR"
        fi
}

preinfo() {
    echo "———————————————————SuperSpeed 全面测速版——————————————————"
    echo "       bash <(curl -Lso- https://git.io/superspeed)"
    echo "       全部节点列表:  https://git.io/superspeedList"
    echo "       节点更新: 2020/04/09  | 脚本更新: 2020/04/09"
    echo "——————————————————————————————————————————————————————————"
}

selecttest() {
    echo -e "  测速类型:    ${GREEN}1.${PLAIN} 三网测速    ${GREEN}2.${PLAIN} 取消测速"
    echo -ne "               ${GREEN}3.${PLAIN} 电信节点    ${GREEN}4.${PLAIN} 联通节点    ${GREEN}5.${PLAIN} 移动节点"
    while :; do echo
            read -p "  请输入数字选择测速类型: " selection
            if [[ ! $selection =~ ^[1-5]$ ]]; then
                    echo -ne "  ${RED}输入错误${PLAIN}, 请输入正确的数字!"
            else
                    break   
            fi
    done
}

runtest() {
    [[ ${selection} == 2 ]] && exit 1

    if [[ ${selection} == 1 ]]; then
        echo "——————————————————————————————————————————————————————————"
        echo "ID    测速服务器信息       上传/Mbps   下载/Mbps   延迟/ms"
        start=$(date +%s) 

         speed_test '3633' '上海' '电信'
         speed_test '24012' '内蒙古呼和浩特' '电信'
         speed_test '27377' '北京5G' '电信'
         speed_test '29026' '四川成都' '电信'
        # speed_test '29071' '四川成都' '电信'
         speed_test '17145' '安徽合肥5G' '电信'
         speed_test '27594' '广东广州5G' '电信'
        # speed_test '27810' '广西南宁' '电信'
         speed_test '27575' '新疆乌鲁木齐' '电信'
        # speed_test '26352' '江苏南京5G' '电信'
         speed_test '5396' '江苏苏州5G' '电信'
        # speed_test '5317' '江苏连云港5G' '电信'
        # speed_test '7509' '浙江杭州' '电信'
         speed_test '23844' '湖北武汉' '电信'
         speed_test '29353' '湖北武汉5G' '电信'
         speed_test '28225' '湖南长沙5G' '电信'
         speed_test '3973' '甘肃兰州' '电信'
        # speed_test '19076' '重庆' '电信'
        #***
        # speed_test '21005' '上海' '联通'
         speed_test '24447' '上海5G' '联通'
        # speed_test '5103' '云南昆明' '联通'
         speed_test '5145' '北京' '联通'
        # speed_test '5505' '北京' '联通'
        # speed_test '9484' '吉林长春' '联通'
         speed_test '2461' '四川成都' '联通'
         speed_test '27154' '天津5G' '联通'
        # speed_test '5509' '宁夏银川' '联通'
        # speed_test '5724' '安徽合肥' '联通'
        # speed_test '5039' '山东济南' '联通'
         speed_test '26180' '山东济南5G' '联通'
         speed_test '26678' '广东广州5G' '联通'
        # speed_test '16192' '广东深圳' '联通'
        # speed_test '6144' '新疆乌鲁木齐' '联通'
         speed_test '13704' '江苏南京' '联通'
         speed_test '5485' '湖北武汉' '联通'
        # speed_test '26677' '湖南株洲' '联通'
         speed_test '4870' '湖南长沙' '联通'
        # speed_test '4690' '甘肃兰州' '联通'
        # speed_test '4884' '福建福州' '联通'
        # speed_test '31985' '重庆' '联通'
         speed_test '4863' '陕西西安' '联通'
        #***
        # speed_test '30154' '上海' '移动'
        # speed_test '25637' '上海5G' '移动'
        # speed_test '26728' '云南昆明' '移动'
        # speed_test '27019' '内蒙古呼和浩特' '移动'
         speed_test '30232' '内蒙呼和浩特5G' '移动'
        # speed_test '30293' '内蒙古通辽5G' '移动'
         speed_test '25858' '北京' '移动'
         speed_test '16375' '吉林长春' '移动'
        # speed_test '24337' '四川成都' '移动'
         speed_test '17184' '天津5G' '移动'
        # speed_test '26940' '宁夏银川' '移动'
        # speed_test '31815' '宁夏银川' '移动'
        # speed_test '26404' '安徽合肥5G' '移动'
         speed_test '27151' '山东临沂5G' '移动'
        # speed_test '25881' '山东济南5G' '移动'
        # speed_test '27100' '山东青岛5G' '移动'
        # speed_test '26501' '山西太原5G' '移动'
         speed_test '31520' '广东中山' '移动'
        # speed_test '6611' '广东广州' '移动'
        # speed_test '4515' '广东深圳' '移动'
        # speed_test '15863' '广西南宁' '移动'
        # speed_test '16858' '新疆乌鲁木齐' '移动'
         speed_test '26938' '新疆乌鲁木齐5G' '移动'
        # speed_test '17227' '新疆和田' '移动'
        # speed_test '17245' '新疆喀什' '移动'
        # speed_test '17222' '新疆阿勒泰' '移动'
        # speed_test '27249' '江苏南京5G' '移动'
        # speed_test '21845' '江苏常州5G' '移动'
        # speed_test '26850' '江苏无锡5G' '移动'
        # speed_test '17320' '江苏镇江5G' '移动'
         speed_test '25883' '江西南昌5G' '移动'
        # speed_test '17223' '河北石家庄' '移动'
        # speed_test '26331' '河南郑州5G' '移动'
        # speed_test '6715' '浙江宁波5G' '移动'
        # speed_test '4647' '浙江杭州' '移动'
        # speed_test '16503' '海南海口' '移动'
        # speed_test '28491' '湖南长沙5G' '移动'
        # speed_test '16145' '甘肃兰州' '移动'
         speed_test '16171' '福建福州' '移动'
        # speed_test '18444' '西藏拉萨' '移动'
         speed_test '16398' '贵州贵阳' '移动'
         speed_test '25728' '辽宁大连' '移动'
        # speed_test '16167' '辽宁沈阳' '移动'
        # speed_test '17584' '重庆' '移动'
        # speed_test '26380' '陕西西安' '移动'
        # speed_test '29105' '陕西西安5G' '移动'
        # speed_test '29083' '青海西宁5G' '移动'
        # speed_test '26656' '黑龙江哈尔滨' '移动'

        end=$(date +%s)  
        rm -rf speedtest*
        echo "——————————————————————————————————————————————————————————"
        time=$(( $end - $start ))
        if [[ $time -gt 60 ]]; then
            min=$(expr $time / 60)
            sec=$(expr $time % 60)
            echo -ne "  测试完成, 本次测速耗时: ${min} 分 ${sec} 秒"
        else
            echo -ne "  测试完成, 本次测速耗时: ${time} 秒"
        fi
        echo -ne "\n  当前时间: "
        echo $(date +%Y-%m-%d" "%H:%M:%S)
        echo -e "  ${GREEN}# 三网测速中为避免节点数不均及测试过久,每部分未使用所${PLAIN}"
        echo -e "  ${GREEN}# 有节点,如果需要使用全部节点,可分别选择三网节点检测${PLAIN}"
    fi

    if [[ ${selection} == 3 ]]; then
        echo "——————————————————————————————————————————————————————————"
        echo "ID    测速服务器信息       上传/Mbps   下载/Mbps   延迟/ms"
        start=$(date +%s) 

         speed_test '3633' '上海' '电信'
         speed_test '24012' '内蒙古呼和浩特' '电信'
         speed_test '27377' '北京5G' '电信'
         speed_test '29026' '四川成都' '电信'
         speed_test '29071' '四川成都' '电信'
         speed_test '17145' '安徽合肥5G' '电信'
         speed_test '27594' '广东广州5G' '电信'
         speed_test '27810' '广西南宁' '电信'
         speed_test '27575' '新疆乌鲁木齐' '电信'
         speed_test '26352' '江苏南京5G' '电信'
         speed_test '5396' '江苏苏州5G' '电信'
         speed_test '5317' '江苏连云港5G' '电信'
         speed_test '7509' '浙江杭州' '电信'
         speed_test '23844' '湖北武汉' '电信'
         speed_test '29353' '湖北武汉5G' '电信'
         speed_test '28225' '湖南长沙5G' '电信'
         speed_test '3973' '甘肃兰州' '电信'
         speed_test '19076' '重庆' '电信'

        end=$(date +%s)  
        rm -rf speedtest*
        echo "——————————————————————————————————————————————————————————"
        time=$(( $end - $start ))
        if [[ $time -gt 60 ]]; then
            min=$(expr $time / 60)
            sec=$(expr $time % 60)
            echo -ne "  测试完成, 本次测速耗时: ${min} 分 ${sec} 秒"
        else
            echo -ne "  测试完成, 本次测速耗时: ${time} 秒"
        fi
        echo -ne "\n  当前时间: "
        echo $(date +%Y-%m-%d" "%H:%M:%S)
    fi

    if [[ ${selection} == 4 ]]; then
        echo "——————————————————————————————————————————————————————————"
        echo "ID    测速服务器信息       上传/Mbps   下载/Mbps   延迟/ms"
        start=$(date +%s) 

         speed_test '21005' '上海' '联通'
         speed_test '24447' '上海5G' '联通'
         speed_test '5103' '云南昆明' '联通'
         speed_test '5145' '北京' '联通'
         speed_test '5505' '北京' '联通'
         speed_test '9484' '吉林长春' '联通'
         speed_test '2461' '四川成都' '联通'
         speed_test '27154' '天津5G' '联通'
         speed_test '5509' '宁夏银川' '联通'
         speed_test '5724' '安徽合肥' '联通'
         speed_test '5039' '山东济南' '联通'
         speed_test '26180' '山东济南5G' '联通'
         speed_test '26678' '广东广州5G' '联通'
         speed_test '16192' '广东深圳' '联通'
         speed_test '6144' '新疆乌鲁木齐' '联通'
         speed_test '13704' '江苏南京' '联通'
         speed_test '5485' '湖北武汉' '联通'
         speed_test '26677' '湖南株洲' '联通'
         speed_test '4870' '湖南长沙' '联通'
         speed_test '4690' '甘肃兰州' '联通'
         speed_test '4884' '福建福州' '联通'
         speed_test '31985' '重庆' '联通'
         speed_test '4863' '陕西西安' '联通'

        end=$(date +%s)  
        rm -rf speedtest*
        echo "——————————————————————————————————————————————————————————"
        time=$(( $end - $start ))
        if [[ $time -gt 60 ]]; then
            min=$(expr $time / 60)
            sec=$(expr $time % 60)
            echo -ne "  测试完成, 本次测速耗时: ${min} 分 ${sec} 秒"
        else
            echo -ne "  测试完成, 本次测速耗时: ${time} 秒"
        fi
        echo -ne "\n  当前时间: "
        echo $(date +%Y-%m-%d" "%H:%M:%S)
    fi

    if [[ ${selection} == 5 ]]; then
        echo "——————————————————————————————————————————————————————————"
        echo "ID    测速服务器信息       上传/Mbps   下载/Mbps   延迟/ms"
        start=$(date +%s) 

         speed_test '30154' '上海' '移动'
         speed_test '25637' '上海5G' '移动'
         speed_test '26728' '云南昆明' '移动'
         speed_test '27019' '内蒙古呼和浩特' '移动'
         speed_test '30232' '内蒙呼和浩特5G' '移动'
         speed_test '30293' '内蒙古通辽5G' '移动'
         speed_test '25858' '北京' '移动'
         speed_test '16375' '吉林长春' '移动'
         speed_test '24337' '四川成都' '移动'
         speed_test '17184' '天津5G' '移动'
         speed_test '26940' '宁夏银川' '移动'
         speed_test '31815' '宁夏银川' '移动'
         speed_test '26404' '安徽合肥5G' '移动'
         speed_test '27151' '山东临沂5G' '移动'
         speed_test '25881' '山东济南5G' '移动'
         speed_test '27100' '山东青岛5G' '移动'
         speed_test '26501' '山西太原5G' '移动'
         speed_test '31520' '广东中山' '移动'
         speed_test '6611' '广东广州' '移动'
         speed_test '4515' '广东深圳' '移动'
         speed_test '15863' '广西南宁' '移动'
         speed_test '16858' '新疆乌鲁木齐' '移动'
         speed_test '26938' '新疆乌鲁木齐5G' '移动'
         speed_test '17227' '新疆和田' '移动'
         speed_test '17245' '新疆喀什' '移动'
         speed_test '17222' '新疆阿勒泰' '移动'
         speed_test '27249' '江苏南京5G' '移动'
         speed_test '21845' '江苏常州5G' '移动'
         speed_test '26850' '江苏无锡5G' '移动'
         speed_test '17320' '江苏镇江5G' '移动'
         speed_test '25883' '江西南昌5G' '移动'
         speed_test '17223' '河北石家庄' '移动'
         speed_test '26331' '河南郑州5G' '移动'
         speed_test '6715' '浙江宁波5G' '移动'
         speed_test '4647' '浙江杭州' '移动'
         speed_test '16503' '海南海口' '移动'
         speed_test '28491' '湖南长沙5G' '移动'
         speed_test '16145' '甘肃兰州' '移动'
         speed_test '16171' '福建福州' '移动'
         speed_test '18444' '西藏拉萨' '移动'
         speed_test '16398' '贵州贵阳' '移动'
         speed_test '25728' '辽宁大连' '移动'
         speed_test '16167' '辽宁沈阳' '移动'
         speed_test '17584' '重庆' '移动'
         speed_test '26380' '陕西西安' '移动'
         speed_test '29105' '陕西西安5G' '移动'
         speed_test '29083' '青海西宁5G' '移动'
         speed_test '26656' '黑龙江哈尔滨' '移动'

        end=$(date +%s)  
        rm -rf speedtest*
        echo "——————————————————————————————————————————————————————————"
        time=$(( $end - $start ))
        if [[ $time -gt 60 ]]; then
            min=$(expr $time / 60)
            sec=$(expr $time % 60)
            echo -ne "  测试完成, 本次测速耗时: ${min} 分 ${sec} 秒"
        else
            echo -ne "  测试完成, 本次测速耗时: ${time} 秒"
        fi
        echo -ne "\n  当前时间: "
        echo $(date +%Y-%m-%d" "%H:%M:%S)
    fi
}

runall() {
    checkroot;
    checksystem;
    checkpython;
    checkcurl;
    checkwget;
    checkspeedtest;
    clear
    speed_test;
    preinfo;
    selecttest;
    runtest;
    rm -rf speedtest*
}

runall

脚本十二:一键开启BBR/BBR Plus加速

#!/usr/bin/env bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

#=================================================
#    System Required: CentOS 6/7,Debian 8/9,Ubuntu 16+
#    Description: BBR+BBR魔改版+BBRplus+Lotserver
#    Version: 1.3.2
#    Author: 千影,cx9208
#    Blog: https://www.94ish.me/
#=================================================

sh_ver="1.3.2"
github="raw.githubusercontent.com/chiakge/Linux-NetSpeed/master"

Green_font_prefix="\033[32m" && Red_font_prefix="\033[31m" && Green_background_prefix="\033[42;37m" && Red_background_prefix="\033[41;37m" && Font_color_suffix="\033[0m"
Info="${Green_font_prefix}[信息]${Font_color_suffix}"
Error="${Red_font_prefix}[错误]${Font_color_suffix}"
Tip="${Green_font_prefix}[注意]${Font_color_suffix}"

#安装BBR内核
installbbr(){
    kernel_version="4.11.8"
    if [[ "${release}" == "centos" ]]; then
        rpm --import http://${github}/bbr/${release}/RPM-GPG-KEY-elrepo.org
        yum install -y http://${github}/bbr/${release}/${version}/${bit}/kernel-ml-${kernel_version}.rpm
        yum remove -y kernel-headers
        yum install -y http://${github}/bbr/${release}/${version}/${bit}/kernel-ml-headers-${kernel_version}.rpm
        yum install -y http://${github}/bbr/${release}/${version}/${bit}/kernel-ml-devel-${kernel_version}.rpm
    elif [[ "${release}" == "debian" || "${release}" == "ubuntu" ]]; then
        mkdir bbr && cd bbr
        wget http://security.debian.org/debian-security/pool/updates/main/o/openssl/libssl1.0.0_1.0.1t-1+deb8u10_amd64.deb
        wget -N --no-check-certificate http://${github}/bbr/debian-ubuntu/linux-headers-${kernel_version}-all.deb
        wget -N --no-check-certificate http://${github}/bbr/debian-ubuntu/${bit}/linux-headers-${kernel_version}.deb
        wget -N --no-check-certificate http://${github}/bbr/debian-ubuntu/${bit}/linux-image-${kernel_version}.deb
    
        dpkg -i libssl1.0.0_1.0.1t-1+deb8u10_amd64.deb
        dpkg -i linux-headers-${kernel_version}-all.deb
        dpkg -i linux-headers-${kernel_version}.deb
        dpkg -i linux-image-${kernel_version}.deb
        cd .. && rm -rf bbr
    fi
    detele_kernel
    BBR_grub
    echo -e "${Tip} 重启VPS后,请重新运行脚本开启${Red_font_prefix}BBR/BBR魔改版${Font_color_suffix}"
    stty erase '^H' && read -p "需要重启VPS后,才能开启BBR/BBR魔改版,是否现在重启 ? [Y/n] :" yn
    [ -z "${yn}" ] && yn="y"
    if [[ $yn == [Yy] ]]; then
        echo -e "${Info} VPS 重启中..."
        reboot
    fi
}

#安装BBRplus内核
installbbrplus(){
    kernel_version="4.14.129-bbrplus"
    if [[ "${release}" == "centos" ]]; then
        wget -N --no-check-certificate https://${github}/bbrplus/${release}/${version}/kernel-${kernel_version}.rpm
        yum install -y kernel-${kernel_version}.rpm
        rm -f kernel-${kernel_version}.rpm
        kernel_version="4.14.129_bbrplus" #fix a bug
    elif [[ "${release}" == "debian" || "${release}" == "ubuntu" ]]; then
        mkdir bbrplus && cd bbrplus
        wget -N --no-check-certificate http://${github}/bbrplus/debian-ubuntu/${bit}/linux-headers-${kernel_version}.deb
        wget -N --no-check-certificate http://${github}/bbrplus/debian-ubuntu/${bit}/linux-image-${kernel_version}.deb
        dpkg -i linux-headers-${kernel_version}.deb
        dpkg -i linux-image-${kernel_version}.deb
        cd .. && rm -rf bbrplus
    fi
    detele_kernel
    BBR_grub
    echo -e "${Tip} 重启VPS后,请重新运行脚本开启${Red_font_prefix}BBRplus${Font_color_suffix}"
    stty erase '^H' && read -p "需要重启VPS后,才能开启BBRplus,是否现在重启 ? [Y/n] :" yn
    [ -z "${yn}" ] && yn="y"
    if [[ $yn == [Yy] ]]; then
        echo -e "${Info} VPS 重启中..."
        reboot
    fi
}

#安装Lotserver内核
installlot(){
    if [[ "${release}" == "centos" ]]; then
        rpm --import http://${github}/lotserver/${release}/RPM-GPG-KEY-elrepo.org
        yum remove -y kernel-firmware
        yum install -y http://${github}/lotserver/${release}/${version}/${bit}/kernel-firmware-${kernel_version}.rpm
        yum install -y http://${github}/lotserver/${release}/${version}/${bit}/kernel-${kernel_version}.rpm
        yum remove -y kernel-headers
        yum install -y http://${github}/lotserver/${release}/${version}/${bit}/kernel-headers-${kernel_version}.rpm
        yum install -y http://${github}/lotserver/${release}/${version}/${bit}/kernel-devel-${kernel_version}.rpm
    elif [[ "${release}" == "ubuntu" ]]; then
        bash <(wget --no-check-certificate -qO- "http://${github}/Debian_Kernel.sh")
    elif [[ "${release}" == "debian" ]]; then
        bash <(wget --no-check-certificate -qO- "http://${github}/Debian_Kernel.sh")
    fi
    detele_kernel
    BBR_grub
    echo -e "${Tip} 重启VPS后,请重新运行脚本开启${Red_font_prefix}Lotserver${Font_color_suffix}"
    stty erase '^H' && read -p "需要重启VPS后,才能开启Lotserver,是否现在重启 ? [Y/n] :" yn
    [ -z "${yn}" ] && yn="y"
    if [[ $yn == [Yy] ]]; then
        echo -e "${Info} VPS 重启中..."
        reboot
    fi
}

#启用BBR
startbbr(){
    remove_all
    echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
    echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
    sysctl -p
    echo -e "${Info}BBR启动成功!"
}

#启用BBRplus
startbbrplus(){
    remove_all
    echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
    echo "net.ipv4.tcp_congestion_control=bbrplus" >> /etc/sysctl.conf
    sysctl -p
    echo -e "${Info}BBRplus启动成功!"
}

#编译并启用BBR魔改
startbbrmod(){
    remove_all
    if [[ "${release}" == "centos" ]]; then
        yum install -y make gcc
        mkdir bbrmod && cd bbrmod
        wget -N --no-check-certificate http://${github}/bbr/tcp_tsunami.c
        echo "obj-m:=tcp_tsunami.o" > Makefile
        make -C /lib/modules/$(uname -r)/build M=`pwd` modules CC=/usr/bin/gcc
        chmod +x ./tcp_tsunami.ko
        cp -rf ./tcp_tsunami.ko /lib/modules/$(uname -r)/kernel/net/ipv4
        insmod tcp_tsunami.ko
        depmod -a
    else
        apt-get update
        if [[ "${release}" == "ubuntu" && "${version}" = "14" ]]; then
            apt-get -y install build-essential
            apt-get -y install software-properties-common
            add-apt-repository ppa:ubuntu-toolchain-r/test -y
            apt-get update
        fi
        apt-get -y install make gcc
        mkdir bbrmod && cd bbrmod
        wget -N --no-check-certificate http://${github}/bbr/tcp_tsunami.c
        echo "obj-m:=tcp_tsunami.o" > Makefile
        ln -s /usr/bin/gcc /usr/bin/gcc-4.9
        make -C /lib/modules/$(uname -r)/build M=`pwd` modules CC=/usr/bin/gcc-4.9
        install tcp_tsunami.ko /lib/modules/$(uname -r)/kernel
        cp -rf ./tcp_tsunami.ko /lib/modules/$(uname -r)/kernel/net/ipv4
        depmod -a
    fi
    

    echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
    echo "net.ipv4.tcp_congestion_control=tsunami" >> /etc/sysctl.conf
    sysctl -p
    cd .. && rm -rf bbrmod
    echo -e "${Info}魔改版BBR启动成功!"
}

#编译并启用BBR魔改
startbbrmod_nanqinlang(){
    remove_all
    if [[ "${release}" == "centos" ]]; then
        yum install -y make gcc
        mkdir bbrmod && cd bbrmod
        wget -N --no-check-certificate https://raw.githubusercontent.com/chiakge/Linux-NetSpeed/master/bbr/centos/tcp_nanqinlang.c
        echo "obj-m := tcp_nanqinlang.o" > Makefile
        make -C /lib/modules/$(uname -r)/build M=`pwd` modules CC=/usr/bin/gcc
        chmod +x ./tcp_nanqinlang.ko
        cp -rf ./tcp_nanqinlang.ko /lib/modules/$(uname -r)/kernel/net/ipv4
        insmod tcp_nanqinlang.ko
        depmod -a
    else
        apt-get update
        if [[ "${release}" == "ubuntu" && "${version}" = "14" ]]; then
            apt-get -y install build-essential
            apt-get -y install software-properties-common
            add-apt-repository ppa:ubuntu-toolchain-r/test -y
            apt-get update
        fi
        apt-get -y install make gcc-4.9
        mkdir bbrmod && cd bbrmod
        wget -N --no-check-certificate https://raw.githubusercontent.com/chiakge/Linux-NetSpeed/master/bbr/tcp_nanqinlang.c
        echo "obj-m := tcp_nanqinlang.o" > Makefile
        make -C /lib/modules/$(uname -r)/build M=`pwd` modules CC=/usr/bin/gcc-4.9
        install tcp_nanqinlang.ko /lib/modules/$(uname -r)/kernel
        cp -rf ./tcp_nanqinlang.ko /lib/modules/$(uname -r)/kernel/net/ipv4
        depmod -a
    fi
    

    echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
    echo "net.ipv4.tcp_congestion_control=nanqinlang" >> /etc/sysctl.conf
    sysctl -p
    echo -e "${Info}魔改版BBR启动成功!"
}

#启用Lotserver
startlotserver(){
    remove_all
    if [[ "${release}" == "centos" ]]; then
        yum install ethtool
    else
        apt-get update
        apt-get install ethtool
    fi
    bash <(wget --no-check-certificate -qO- https://raw.githubusercontent.com/chiakge/lotServer/master/Install.sh) install
    sed -i '/advinacc/d' /appex/etc/config
    sed -i '/maxmode/d' /appex/etc/config
    echo -e "advinacc=\"1\"
maxmode=\"1\"">>/appex/etc/config
    /appex/bin/lotServer.sh restart
    start_menu
}

#卸载全部加速
remove_all(){
    rm -rf bbrmod
    sed -i '/net.core.default_qdisc/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_congestion_control/d' /etc/sysctl.conf
    sed -i '/fs.file-max/d' /etc/sysctl.conf
    sed -i '/net.core.rmem_max/d' /etc/sysctl.conf
    sed -i '/net.core.wmem_max/d' /etc/sysctl.conf
    sed -i '/net.core.rmem_default/d' /etc/sysctl.conf
    sed -i '/net.core.wmem_default/d' /etc/sysctl.conf
    sed -i '/net.core.netdev_max_backlog/d' /etc/sysctl.conf
    sed -i '/net.core.somaxconn/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_tw_reuse/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_tw_recycle/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_fin_timeout/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_keepalive_time/d' /etc/sysctl.conf
    sed -i '/net.ipv4.ip_local_port_range/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_max_syn_backlog/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_max_tw_buckets/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_rmem/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_wmem/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_mtu_probing/d' /etc/sysctl.conf
    sed -i '/net.ipv4.ip_forward/d' /etc/sysctl.conf
    sed -i '/fs.inotify.max_user_instances/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_fin_timeout/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_tw_reuse/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_max_syn_backlog/d' /etc/sysctl.conf
    sed -i '/net.ipv4.ip_local_port_range/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_max_tw_buckets/d' /etc/sysctl.conf
    sed -i '/net.ipv4.route.gc_timeout/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_synack_retries/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_syn_retries/d' /etc/sysctl.conf
    sed -i '/net.core.somaxconn/d' /etc/sysctl.conf
    sed -i '/net.core.netdev_max_backlog/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_timestamps/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_max_orphans/d' /etc/sysctl.conf
    if [[ -e /appex/bin/lotServer.sh ]]; then
        bash <(wget --no-check-certificate -qO- https://github.com/MoeClub/lotServer/raw/master/Install.sh) uninstall
    fi
    clear
    echo -e "${Info}:清除加速完成。"
    sleep 1s
}

#优化系统配置
optimizing_system(){
    sed -i '/fs.file-max/d' /etc/sysctl.conf
    sed -i '/fs.inotify.max_user_instances/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_fin_timeout/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_tw_reuse/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_max_syn_backlog/d' /etc/sysctl.conf
    sed -i '/net.ipv4.ip_local_port_range/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_max_tw_buckets/d' /etc/sysctl.conf
    sed -i '/net.ipv4.route.gc_timeout/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_synack_retries/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_syn_retries/d' /etc/sysctl.conf
    sed -i '/net.core.somaxconn/d' /etc/sysctl.conf
    sed -i '/net.core.netdev_max_backlog/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_timestamps/d' /etc/sysctl.conf
    sed -i '/net.ipv4.tcp_max_orphans/d' /etc/sysctl.conf
    sed -i '/net.ipv4.ip_forward/d' /etc/sysctl.conf
    echo "fs.file-max = 1000000
fs.inotify.max_user_instances = 8192
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1
net.core.somaxconn = 32768
net.core.netdev_max_backlog = 32768
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_max_orphans = 32768
# forward ipv4
net.ipv4.ip_forward = 1">>/etc/sysctl.conf
    sysctl -p
    echo "*               soft    nofile           1000000
*               hard    nofile          1000000">/etc/security/limits.conf
    echo "ulimit -SHn 1000000">>/etc/profile
    read -p "需要重启VPS后,才能生效系统优化配置,是否现在重启 ? [Y/n] :" yn
    [ -z "${yn}" ] && yn="y"
    if [[ $yn == [Yy] ]]; then
        echo -e "${Info} VPS 重启中..."
        reboot
    fi
}
#更新脚本
Update_Shell(){
    echo -e "当前版本为 [ ${sh_ver} ],开始检测最新版本..."
    sh_new_ver=$(wget --no-check-certificate -qO- "http://${github}/tcp.sh"|grep 'sh_ver="'|awk -F "=" '{print $NF}'|sed 's/\"//g'|head -1)
    [[ -z ${sh_new_ver} ]] && echo -e "${Error} 检测最新版本失败 !" && start_menu
    if [[ ${sh_new_ver} != ${sh_ver} ]]; then
        echo -e "发现新版本[ ${sh_new_ver} ],是否更新?[Y/n]"
        read -p "(默认: y):" yn
        [[ -z "${yn}" ]] && yn="y"
        if [[ ${yn} == [Yy] ]]; then
            wget -N --no-check-certificate http://${github}/tcp.sh && chmod +x tcp.sh
            echo -e "脚本已更新为最新版本[ ${sh_new_ver} ] !"
        else
            echo && echo "    已取消..." && echo
        fi
    else
        echo -e "当前已是最新版本[ ${sh_new_ver} ] !"
        sleep 5s
    fi
}

#开始菜单
start_menu(){
clear
echo && echo -e " TCP加速 一键安装管理脚本 ${Red_font_prefix}[v${sh_ver}]${Font_color_suffix}
  -- 就是爱生活 | 94ish.me --
  
 ${Green_font_prefix}0.${Font_color_suffix} 升级脚本
————————————内核管理————————————
 ${Green_font_prefix}1.${Font_color_suffix} 安装 BBR/BBR魔改版内核
 ${Green_font_prefix}2.${Font_color_suffix} 安装 BBRplus版内核 
 ${Green_font_prefix}3.${Font_color_suffix} 安装 Lotserver(锐速)内核
————————————加速管理————————————
 ${Green_font_prefix}4.${Font_color_suffix} 使用BBR加速
 ${Green_font_prefix}5.${Font_color_suffix} 使用BBR魔改版加速
 ${Green_font_prefix}6.${Font_color_suffix} 使用暴力BBR魔改版加速(不支持部分系统)
 ${Green_font_prefix}7.${Font_color_suffix} 使用BBRplus版加速
 ${Green_font_prefix}8.${Font_color_suffix} 使用Lotserver(锐速)加速
————————————杂项管理————————————
 ${Green_font_prefix}9.${Font_color_suffix} 卸载全部加速
 ${Green_font_prefix}10.${Font_color_suffix} 系统配置优化
 ${Green_font_prefix}11.${Font_color_suffix} 退出脚本
————————————————————————————————" && echo

    check_status
    if [[ ${kernel_status} == "noinstall" ]]; then
        echo -e " 当前状态: ${Green_font_prefix}未安装${Font_color_suffix} 加速内核 ${Red_font_prefix}请先安装内核${Font_color_suffix}"
    else
        echo -e " 当前状态: ${Green_font_prefix}已安装${Font_color_suffix} ${_font_prefix}${kernel_status}${Font_color_suffix} 加速内核 , ${Green_font_prefix}${run_status}${Font_color_suffix}"
        
    fi
echo
read -p " 请输入数字 [0-11]:" num
case "$num" in
    0)
    Update_Shell
    ;;
    1)
    check_sys_bbr
    ;;
    2)
    check_sys_bbrplus
    ;;
    3)
    check_sys_Lotsever
    ;;
    4)
    startbbr
    ;;
    5)
    startbbrmod
    ;;
    6)
    startbbrmod_nanqinlang
    ;;
    7)
    startbbrplus
    ;;
    8)
    startlotserver
    ;;
    9)
    remove_all
    ;;
    10)
    optimizing_system
    ;;
    11)
    exit 1
    ;;
    *)
    clear
    echo -e "${Error}:请输入正确数字 [0-11]"
    sleep 5s
    start_menu
    ;;
esac
}
#############内核管理组件#############

#删除多余内核
detele_kernel(){
    if [[ "${release}" == "centos" ]]; then
        rpm_total=`rpm -qa | grep kernel | grep -v "${kernel_version}" | grep -v "noarch" | wc -l`
        if [ "${rpm_total}" > "1" ]; then
            echo -e "检测到 ${rpm_total} 个其余内核,开始卸载..."
            for((integer = 1; integer <= ${rpm_total}; integer++)); do
                rpm_del=`rpm -qa | grep kernel | grep -v "${kernel_version}" | grep -v "noarch" | head -${integer}`
                echo -e "开始卸载 ${rpm_del} 内核..."
                rpm --nodeps -e ${rpm_del}
                echo -e "卸载 ${rpm_del} 内核卸载完成,继续..."
            done
            echo --nodeps -e "内核卸载完毕,继续..."
        else
            echo -e " 检测到 内核 数量不正确,请检查 !" && exit 1
        fi
    elif [[ "${release}" == "debian" || "${release}" == "ubuntu" ]]; then
        deb_total=`dpkg -l | grep linux-image | awk '{print $2}' | grep -v "${kernel_version}" | wc -l`
        if [ "${deb_total}" > "1" ]; then
            echo -e "检测到 ${deb_total} 个其余内核,开始卸载..."
            for((integer = 1; integer <= ${deb_total}; integer++)); do
                deb_del=`dpkg -l|grep linux-image | awk '{print $2}' | grep -v "${kernel_version}" | head -${integer}`
                echo -e "开始卸载 ${deb_del} 内核..."
                apt-get purge -y ${deb_del}
                echo -e "卸载 ${deb_del} 内核卸载完成,继续..."
            done
            echo -e "内核卸载完毕,继续..."
        else
            echo -e " 检测到 内核 数量不正确,请检查 !" && exit 1
        fi
    fi
}

#更新引导
BBR_grub(){
    if [[ "${release}" == "centos" ]]; then
        if [[ ${version} = "6" ]]; then
            if [ ! -f "/boot/grub/grub.conf" ]; then
                echo -e "${Error} /boot/grub/grub.conf 找不到,请检查."
                exit 1
            fi
            sed -i 's/^default=.*/default=0/g' /boot/grub/grub.conf
        elif [[ ${version} = "7" ]]; then
            if [ ! -f "/boot/grub2/grub.cfg" ]; then
                echo -e "${Error} /boot/grub2/grub.cfg 找不到,请检查."
                exit 1
            fi
            grub2-set-default 0
        fi
    elif [[ "${release}" == "debian" || "${release}" == "ubuntu" ]]; then
        /usr/sbin/update-grub
    fi
}

#############内核管理组件#############



#############系统检测组件#############

#检查系统
check_sys(){
    if [[ -f /etc/redhat-release ]]; then
        release="centos"
    elif cat /etc/issue | grep -q -E -i "debian"; then
        release="debian"
    elif cat /etc/issue | grep -q -E -i "ubuntu"; then
        release="ubuntu"
    elif cat /etc/issue | grep -q -E -i "centos|red hat|redhat"; then
        release="centos"
    elif cat /proc/version | grep -q -E -i "debian"; then
        release="debian"
    elif cat /proc/version | grep -q -E -i "ubuntu"; then
        release="ubuntu"
    elif cat /proc/version | grep -q -E -i "centos|red hat|redhat"; then
        release="centos"
    fi
}

#检查Linux版本
check_version(){
    if [[ -s /etc/redhat-release ]]; then
        version=`grep -oE  "[0-9.]+" /etc/redhat-release | cut -d . -f 1`
    else
        version=`grep -oE  "[0-9.]+" /etc/issue | cut -d . -f 1`
    fi
    bit=`uname -m`
    if [[ ${bit} = "x86_64" ]]; then
        bit="x64"
    else
        bit="x32"
    fi
}

#检查安装bbr的系统要求
check_sys_bbr(){
    check_version
    if [[ "${release}" == "centos" ]]; then
        if [[ ${version} -ge "6" ]]; then
            installbbr
        else
            echo -e "${Error} BBR内核不支持当前系统 ${release} ${version} ${bit} !" && exit 1
        fi
    elif [[ "${release}" == "debian" ]]; then
        if [[ ${version} -ge "8" ]]; then
            installbbr
        else
            echo -e "${Error} BBR内核不支持当前系统 ${release} ${version} ${bit} !" && exit 1
        fi
    elif [[ "${release}" == "ubuntu" ]]; then
        if [[ ${version} -ge "14" ]]; then
            installbbr
        else
            echo -e "${Error} BBR内核不支持当前系统 ${release} ${version} ${bit} !" && exit 1
        fi
    else
        echo -e "${Error} BBR内核不支持当前系统 ${release} ${version} ${bit} !" && exit 1
    fi
}

check_sys_bbrplus(){
    check_version
    if [[ "${release}" == "centos" ]]; then
        if [[ ${version} -ge "6" ]]; then
            installbbrplus
        else
            echo -e "${Error} BBRplus内核不支持当前系统 ${release} ${version} ${bit} !" && exit 1
        fi
    elif [[ "${release}" == "debian" ]]; then
        if [[ ${version} -ge "8" ]]; then
            installbbrplus
        else
            echo -e "${Error} BBRplus内核不支持当前系统 ${release} ${version} ${bit} !" && exit 1
        fi
    elif [[ "${release}" == "ubuntu" ]]; then
        if [[ ${version} -ge "14" ]]; then
            installbbrplus
        else
            echo -e "${Error} BBRplus内核不支持当前系统 ${release} ${version} ${bit} !" && exit 1
        fi
    else
        echo -e "${Error} BBRplus内核不支持当前系统 ${release} ${version} ${bit} !" && exit 1
    fi
}


#检查安装Lotsever的系统要求
check_sys_Lotsever(){
    check_version
    if [[ "${release}" == "centos" ]]; then
        if [[ ${version} == "6" ]]; then
            kernel_version="2.6.32-504"
            installlot
        elif [[ ${version} == "7" ]]; then
            yum -y install net-tools
            kernel_version="3.10.0-327"
            installlot
        else
            echo -e "${Error} Lotsever不支持当前系统 ${release} ${version} ${bit} !" && exit 1
        fi
    elif [[ "${release}" == "debian" ]]; then
        if [[ ${version} = "7" || ${version} = "8" ]]; then
            if [[ ${bit} == "x64" ]]; then
                kernel_version="3.16.0-4"
                installlot
            elif [[ ${bit} == "x32" ]]; then
                kernel_version="3.2.0-4"
                installlot
            fi
        elif [[ ${version} = "9" ]]; then
            if [[ ${bit} == "x64" ]]; then
                kernel_version="4.9.0-4"
                installlot
            fi
        else
            echo -e "${Error} Lotsever不支持当前系统 ${release} ${version} ${bit} !" && exit 1
        fi
    elif [[ "${release}" == "ubuntu" ]]; then
        if [[ ${version} -ge "12" ]]; then
            if [[ ${bit} == "x64" ]]; then
                kernel_version="4.4.0-47"
                installlot
            elif [[ ${bit} == "x32" ]]; then
                kernel_version="3.13.0-29"
                installlot
            fi
        else
            echo -e "${Error} Lotsever不支持当前系统 ${release} ${version} ${bit} !" && exit 1
        fi
    else
        echo -e "${Error} Lotsever不支持当前系统 ${release} ${version} ${bit} !" && exit 1
    fi
}

check_status(){
    kernel_version=`uname -r | awk -F "-" '{print $1}'`
    kernel_version_full=`uname -r`
    if [[ ${kernel_version_full} = "4.14.129-bbrplus" ]]; then
        kernel_status="BBRplus"
    elif [[ ${kernel_version} = "3.10.0" || ${kernel_version} = "3.16.0" || ${kernel_version} = "3.2.0" || ${kernel_version} = "4.4.0" || ${kernel_version} = "3.13.0"  || ${kernel_version} = "2.6.32" || ${kernel_version} = "4.9.0" ]]; then
        kernel_status="Lotserver"
    elif [[ `echo ${kernel_version} | awk -F'.' '{print $1}'` == "4" ]] && [[ `echo ${kernel_version} | awk -F'.' '{print $2}'` -ge 9 ]] || [[ `echo ${kernel_version} | awk -F'.' '{print $1}'` == "5" ]]; then
        kernel_status="BBR"
    else 
        kernel_status="noinstall"
    fi

    if [[ ${kernel_status} == "Lotserver" ]]; then
        if [[ -e /appex/bin/lotServer.sh ]]; then
            run_status=`bash /appex/bin/lotServer.sh status | grep "LotServer" | awk  '{print $3}'`
            if [[ ${run_status} = "running!" ]]; then
                run_status="启动成功"
            else 
                run_status="启动失败"
            fi
        else 
            run_status="未安装加速模块"
        fi
    elif [[ ${kernel_status} == "BBR" ]]; then
        run_status=`grep "net.ipv4.tcp_congestion_control" /etc/sysctl.conf | awk -F "=" '{print $2}'`
        if [[ ${run_status} == "bbr" ]]; then
            run_status=`lsmod | grep "bbr" | awk '{print $1}'`
            if [[ ${run_status} == "tcp_bbr" ]]; then
                run_status="BBR启动成功"
            else 
                run_status="BBR启动失败"
            fi
        elif [[ ${run_status} == "tsunami" ]]; then
            run_status=`lsmod | grep "tsunami" | awk '{print $1}'`
            if [[ ${run_status} == "tcp_tsunami" ]]; then
                run_status="BBR魔改版启动成功"
            else 
                run_status="BBR魔改版启动失败"
            fi
        elif [[ ${run_status} == "nanqinlang" ]]; then
            run_status=`lsmod | grep "nanqinlang" | awk '{print $1}'`
            if [[ ${run_status} == "tcp_nanqinlang" ]]; then
                run_status="暴力BBR魔改版启动成功"
            else 
                run_status="暴力BBR魔改版启动失败"
            fi
        else 
            run_status="未安装加速模块"
        fi
    elif [[ ${kernel_status} == "BBRplus" ]]; then
        run_status=`grep "net.ipv4.tcp_congestion_control" /etc/sysctl.conf | awk -F "=" '{print $2}'`
        if [[ ${run_status} == "bbrplus" ]]; then
            run_status=`lsmod | grep "bbrplus" | awk '{print $1}'`
            if [[ ${run_status} == "tcp_bbrplus" ]]; then
                run_status="BBRplus启动成功"
            else 
                run_status="BBRplus启动失败"
            fi
        else 
            run_status="未安装加速模块"
        fi
    fi
}

#############系统检测组件#############
check_sys
check_version
[[ ${release} != "debian" ]] && [[ ${release} != "ubuntu" ]] && [[ ${release} != "centos" ]] && echo -e "${Error} 本脚本不支持当前系统 ${release} !" && exit 1
start_menu



分享到:
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接

    Powered By Z-BlogPHP 1.7.2

    Copyright © 2018-2022 Ray Tianjiu.All Rights Reserved.

    您是本站第3244名访客 当前在线 1 人 欢迎你第一次访问网站!