#!/bin/sh

export PATH=/bin/:/sbin:/usr/bin/:/usr/sbin:/usr/local/sbin/:/usr/local/bin/:$PATH
timestamp=$(date +%Y%m%d%H%M%S)
[ ! -e /var/tmp/server_hw_deliver/${timestamp} ] && mkdir -p  /var/tmp/server_hw_deliver/${timestamp}
[ ! -e /var/lock/server_hw_deliver ] && mkdir -p /var/lock/server_hw_deliver
workdir="/var/tmp/server_hw_deliver/${timestamp}"
hwsn=$(dmidecode  -t 1 | grep "Serial Number" | awk -F ":" '{print$2}')

#定义一个颜色输出字符串函数
echo_color(){
    case $1 in
        green)
            echo -e "\033[32m[ OK ] $2\033[0m"
            ;;
        red)
            #echo -e "\033[31m\033[01m\033[05m$2\033[0m"
            echo -e  "\033[31m\033[01m[FAIL] $2\033[0m"
            ;;
        yellow)
            echo -e "\033[33m[WARN] $2\033[0m"
            ;;
        *)
            echo "Example: echo_color red string"
    esac
}

# 定义一个退出打印语句
echo_sayno(){
    echo_color red  "result:${hwsn}==========>已退出,请检查后重试!!!"
}


# 判断安装镜像
if [ -e /etc/redhat-release ];then
    os_ver=1
elif [ -e  /etc/debian_version ];then
    os_ver=2
else 
    echo_color red "result:${hwsn}==========>未知镜像系统!"
    echo_sayno && exit 110  
fi

# 1.基础配置
basic_setup(){

    # 配置dns
    if [ ${os_ver} -eq 1 ];then 
        ping -c 3 -w 3 baidui.com &>/dev/null
        if [ $? -ne 0 ];then
            echo -e 'nameserver 223.5.5.5' > /etc/resolv.conf
            ping -c 3 -w 3 baidui.com &>/dev/null
            if [ $? -ne 0 ];then
                echo_color red "result:${hwsn}==========>1.1-外网不通!"
                echo_sayno && exit 110
            fi
        fi
    fi

    # 配置软件源
    if [ ! -e /var/lock/server_hw_deliver/yum.pid ];then
        if [ ${os_ver} -eq 1 ];then
            command  -v wget &>/dev/null || yum  -y install  wget &>/dev/null
            mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_backup_`date +%F-%H-%M-%S`
            wget http://centos.yum.sandai.net/.help/CentOS-Base7.repo -O /etc/yum.repos.d/CentOS-Base.repo -o /dev/null &>/dev/null
            rpm -ivh http://centos.yum.sandai.net/epel/epel-release-latest-7.noarch.rpm  &>/dev/null
            mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo_backup_`date +%F-%H-%M-%S`
            wget http://centos.yum.sandai.net/.help/epel7.repo -O /etc/yum.repos.d/epel.repo -o /dev/null &>/dev/null
            wget http://centos.yum.sandai.net/epel/RPM-GPG-KEY-EPEL-7 -O /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 -o /dev/null &>/dev/null
            yum clean all &>/dev/null
            yum makecache &>/dev/null

            #安装基础软件包
            yum install epel-release -y &>/dev/null
            yum -y install bc fio jq &>/dev/null
            if [ $? -ne 0 ];then
                echo_color red "result:${hwsn}==========>1.1-软件源配置失败!"
                echo_sayno && exit 110
            fi
        elif [ ${os_ver} -eq 2 ];then 
            apt-get update &>/dev/null
            apt install -y fio bc jq &>/dev/null 2>/dev/null
            if [ $? -ne 0 ];then
               echo_color red "result:${hwsn}==========>1.1-软件源配置失败!"
               echo_sayno && exit 110
            fi
        fi
    fi
  
    echo_color green "result:${hwsn}==========>1-基础环境必要软件包安装完成!"
}

# 2 检查CPU
check_cpu(){
    
    check_cpu_sno=0

    # 检查CPU性能模式
    if [ $(cat /proc/cpuinfo | grep  -i mhz | sort | uniq | wc -l) -ne 1 ];then
        echo_color yellow  "result:${hwsn}==========>2.1-CPU高性能模式检测不通过,非必选,建议调整!"
        check_cpu_sno=1
    fi
    
    # CPU压测2分钟
    cpu_press(){
        CPU_NUM=`grep processor /proc/cpuinfo|wc -l`
        CPU_NUM_TEST=$(echo ${CPU_NUM} | awk '{print int($0*9/10)}') 
        for i in `seq $CPU_NUM_TEST`;do
            {
                echo "scale=16;$i/39"|bc -l &>/dev/null
                echo "scale=3000; 4*a(1)"|bc -l &>/dev/null
            }&
        done
        wait
    }
 
    LIMITTIME=$(echo $(date +%s) + 120 | bc)
    while true;do
        CURTIME=`date +%s`
        [ ${CURTIME} -gt ${LIMITTIME} ] && break
        cpu_press
    done

    # 检查cpu错误日志 
    if [ $(grep -c 'Machine check events' /var/log/messages) -ne 0 ];then
        echo_color red "result:${hwsn}==========>2.2-CPU存在mce错误日志!"
        check_cpu_sno=1
    fi
 
    if [ ${check_cpu_sno} -eq 0 ];then
         echo_color green  "result:${hwsn}==========>2-CPU检测通过!"
    fi
}

# 3 检查内存
check_mem(){

    check_mem_sno=0    
 
    # 压测内存
    mem_press(){
        total_mem=$(cat /proc/meminfo  | awk '/MemTotal/ {print int($2/1024/1024*9/10)}')
        for i in `seq ${total_mem}`;do
            {
                if [ -d /tmp/memory$i ];then
	            rm -rf /tmp/memory$i/block
		    umount -f /tmp/memory$i
		    rm -rf /tmp/memory$i
	        else
		    mkdir /tmp/memory$i
		    mount -t tmpfs -o size=1G tmpfs /tmp/memory$i
		    dd if=/dev/zero of=/tmp/memory$i/block bs=1M count=1024 &>/dev/null
		    rm -rf /tmp/memory$i/block
		    umount /tmp/memory$i
		    rmdir /tmp/memory$i
	        fi
	} &
	done
	wait  
   }

   LIMITTIME=$(echo $(date +%s) + 120 | bc)
   while true;do
       CURTIME=`date +%s`
       [ ${CURTIME} -gt ${LIMITTIME} ] && break
       mem_press
    done
 
   # 检查内存检测校验包
   mem_ce_error=$(grep /sys/devices/system/edac/mc/mc*/csrow*/ch*_ce_count | awk -F':' '$NF>0 {print$0}')
   if [ -n "${mem_ce_error}" ];then
       echo_color red "result:${hwsn}==========>3.1-内存存在CE错误日志![${mem_ce_error}]"
       check_mem_sno=1
   fi
  
   if [ ${check_mem_sno} -eq  0 ];then
       echo_color green  "result:${hwsn}==========>3-内存检测通过!"
   fi

}


# 4检测磁盘性能
check_disk(){

    check_disk_sno=0
    
    # 检测数据磁盘可写
#    sys_disk=$(mount | grep -w '/' | awk '{print$1}' | awk -F '/' '{print$NF}' | sed s/[0-9]//g)
	sys_disk=$(lsblk -l|egrep -B 1 "/$|boot|swap"|grep -v luks|awk '{print $1}'|grep sd|sed -e '/sd/s/[0-9]//' -e '/nvme/s/p[0-9]//' -e '/vd/s/[0-9]//'|sort|uniq)
#    data_disk=$(lsblk  | grep "^s|^n" | awk '{print$1}' | grep -Ev "${sys_disk}|sr0")
    #data_disk=$(lsblk  | grep "^s" | awk '{print$1}' | grep -Ev "${sys_disk}|sr0")
	data_disk=$(lsblk  | grep "disk" | awk '{print$1}' | grep -Ev "${sys_disk}|sr0")
    for i in  ${data_disk};do
        dd if=/dev/zero of=/dev/${i} bs=1M count=1000 &>/dev/null
        if [ $? -ne 0 ];then
            echo_color red "result:${hwsn}==========>4.1-${i}数据盘不可写,请检查后再试!"
            check_disk_sno=1
        fi
    done
    # 测试磁盘性能10s
    disk_press(){
        dev=${i}
		#grep -q静默模式，返回退出码0：找到匹配项，1：未找到匹配项，2：发生错误
        if echo ${dev} | grep -q ${sys_disk};then
            #fio -direct=1 -ioengine=libaio -iodepth=32 -bs=4k -size=4G -filename=/tmp/fiotest -name=/fiotest -runtime=10 -output-format=json -rw=randread -thread -time_base > ${workdir}/${dev}.json
			#tmpfs文件系统无法直接I/O，即-direct=1；改用缓冲I/O即-direct=0：
			fio -direct=0 -ioengine=libaio -iodepth=32 -bs=4k -size=4G -filename=/tmp/fiotest -name=fiotest -runtime=10 -output-format=json -rw=randread -thread -time_base > ${workdir}/${dev}.json
            #read_iops=$(cat ${workdir}/${dev}.json | jq '.jobs|.[].read.iops' | awk '{print int($0)}')
			#备用选择，前一条read_iops=容易出问题
			read_iops=$(cat ${workdir}/${dev}.json |grep iops | sed -n 1p|sed -n 's/.* : //; s/\..*//; p')
            read_lat_ns=$(cat ${workdir}/${dev}.json | jq '.jobs|.[].read.lat_ns.mean' | awk '{print int($0/1000000)}')
            if [[ ${read_iops} -lt  30000 ]];then 
                echo_color red "result:${hwsn}==========>4.2${i}系统盘不合格,要求读IOPS大于30000,当前${read_iops}."
                check_disk_sno=1
            fi
            if [[ ${read_lat_ns} -ge 5 ]];then 
                echo_color red "result:${hwsn}==========>4.3-${i}系统盘不合格,要求读awit小于5毫秒,当前${read_lat_ns}."
                check_disk_sno=1
            fi
            
        else
            fio -direct=1 -ioengine=libaio -iodepth=32 -bs=4k -size=4G -filename=/dev/${dev} -name=/${dev}/fiotest -runtime=10 -output-format=json -rw=randrw -rwmixread=80 -thread -time_base > ${workdir}/${dev}.json
            read_iops=$(cat ${workdir}/${dev}.json | jq '.jobs|.[].read.iops' | awk '{print int($0)}')
			#echo "${dev} read_iops:${read_iops}"
            write_iops=$(cat ${workdir}/${dev}.json | jq '.jobs|.[].write.iops' | awk '{print int($0)}')
			#echo "${dev} write_iops:${write_iops}"
            read_lat_ns=$(cat ${workdir}/${dev}.json | jq '.jobs|.[].read.lat_ns.mean' | awk '{print int($0/1000000)}')
			#echo "${dev} read_lat_ns:${read_lat_ns}"
            vol=$(lsblk -b | grep  "^${dev}" | awk '{print int($4/1000/1000/1000)}')       
            
            if [[ ${read_iops} -gt 2000 ]];then
                # SSD
                if [[ ${read_iops} -lt 35000 ]];then     
                    echo_color red "result:${hwsn}==========>4.4-${i}数据盘SSD不合格,要求读IOPS大于35000,当前${read_iops}."
                    check_disk_sno=1
                fi
                if [[ ${write_iops} -lt 8000 ]];then     
                    echo_color red "result:${hwsn}==========>4.5-${i}数据盘SSD不合格,要求写IOPS大于8000,当前${write_iops}."
                    check_disk_sno=1
                fi
                if [[ ${read_lat_ns} -gt 5 ]];then     
                    echo_color red "result:${hwsn}==========>4.6-${i}数据盘SSD不合格,要求读await小于5毫秒,当前${read_lat_ns}."
                    check_disk_sno=1
                fi   
                echo "SSD ${dev} ${vol}" >> ${workdir}/data_disk_list.log
            else
                # HDD
                if [[ ${read_iops} -lt 100 ]];then     
                    echo_color yellow "result:${hwsn}==========>4.7-${i}数据盘HDD不合格,要求读IOPS大于100,当前${read_iops}."
                    check_disk_sno=1
                fi
                if [[ ${write_iops} -lt 20 ]];then     
                    echo_color red "result:${hwsn}==========>4.8-${i}数据盘SSD不合格,要求写IOPS大于20,当前${write_iops}."
                    check_disk_sno=1
                fi
                if [[ ${read_lat_ns} -gt 50 ]];then     
                    echo_color red "result:${hwsn}==========>4.9-${i}数据盘HDD不合格,要求读await小于50毫秒,当前${read_lat_ns}."
                    check_disk_sno=1
                 fi        
                echo "HDD ${dev} ${vol}" >> ${workdir}/data_disk_list.log
            fi 
        fi   
    }

    all_disk=$(lsblk |  grep -E  "^sd|^n" | awk '{print$1}' | sort)
    for i in  ${all_disk};do
        disk_press ${i}
    done
    
    if [ $check_disk_sno -eq 0 ];then
        echo_color green "result:${hwsn}==========>4-磁盘性能检测通过!" 
    fi
}


# 2.4检验硬件配置，入门配置20c+32G+240GSSD系统盘+2*1TSSD + 数据盘
check_hardware(){

    check_hardware_sno=0
    
    cpu_threads=$(lscpu | grep "^CPU(s)" | awk '{print$2}')
    # 内存
    mem_total=$(cat /proc/meminfo | grep MemTotal | awk '{print int($2/1024/1024)}')
    # 硬盘
    #disk_sys_drive=$(mount | grep -w "\/" | awk -F"[/ ]" '{print$3}' | sed s#[0-9]##g)
	disk_sys_drive=$(lsblk -l|egrep -B 1 "/$|boot|swap"|grep -v luks|awk '{print $1}'|grep sd|sed -e '/sd/s/[0-9]//' -e '/nvme/s/p[0-9]//' -e '/vd/s/[0-9]//'|sort|uniq)
    #disk_sys_drive_capacity=$(lsblk -b | grep "^${disk_sys_drive}" | awk '{print int($4/1000/1000/1000)}')
	disk_sys_drive_capacity=$(lsblk|grep -w "/" |awk '{print $5}'|awk '{ sub(/G/, "", $0); print int($0) }')
    ssd_vol=$(cat ${workdir}/data_disk_list.log | grep "^SSD" | awk '{sum+= $3} END{print int(sum)}')
    hdd_vol=$(cat ${workdir}/data_disk_list.log | grep "^HDD" | awk '{sum+= $3} END{print int(sum)}')
    ssd_phy=$(cat ${workdir}/data_disk_list.log | grep "^SSD" | awk '{print$3"G"}' | sort | uniq -c | sed 's/^[ \t]*//g' | sed s/[[:space:]]/*/g | tr '\n' '+' | sed 's#+$# #g' | sed s/[[:space:]]//g )
    hdd_phy=$(cat ${workdir}/data_disk_list.log | grep "^HDD" | awk '{print$3"G"}' | sort | uniq -c | sed 's/^[ \t]*//g' | sed s/[[:space:]]/*/g | tr '\n' '+' | sed 's#+$# #g' | sed s/[[:space:]]//g)
    phy_summ=$(echo "cpu:${cpu_threads}c+内存:${mem_total}g+系统盘:1*${disk_sys_drive_capacity}GSSD+数据盘:SSD:${ssd_phy} HDD:${hdd_phy:-"0"}")
   
      
    if [ $(echo ${disk_sys_drive} | grep -c sda) -eq 0 ];then
        echo_color red "result:${hwsn}==========>5.1-系统盘符无法确认为sda：当前系统盘符：[${disk_sys_drive}]"
        check_hardware_sno=1
    fi
  
    
    if [[ ${disk_sys_drive_capacity} -lt 200 ]];then
        echo_color red "result:${hwsn}==========>5.2-硬件最低配置检测不通过! 系统盘容量小于240G.当前配置：[${phy_summ}]"
        check_hardware_sno=1
    fi

    if [[ ${check_hardware_sno} -eq 0 ]];then
        echo_color green "result:${hwsn}==========>5.2-硬件配置检测通过!当前配置：[${phy_summ}]"
    fi
}

#2.5检查网卡速率
check_network(){
   
    check_network_sno=0    

    net_dev=$(cat /proc/net/dev | grep -v "tun\|face\|lo\|Inter\|ppp\|docker\|galaxy\|virbr\|macvlan\|docker0\|docker0\|edge-hub-dummy" | awk -F":" '{print$1}' | sed s/[[:space:]]//g | sort)
    for i in $(echo ${net_dev});do
        net_dev_speed=$(ethtool ${i} | grep Speed| sed s/[^[:digit:]]//g)
        net_dev_comb=$(ethtool -l ${i} |  grep Combined |  head -n1 |awk -F":" '{print$2}'|sed s/[[:space:]]//g)
        net_ports=$(ethtool $i | grep 'Supported ports' | awk '{print $(NF-1)}')
        if [ ${net_dev_comb} -lt 8 ];then
            echo_color red "result:${hwsn}==========>6.1-网卡队列数检测不通过! 要求不少于8.当前配置：[${net_dev_comb}]"
            check_network_sno=1
        fi
        echo "${net_dev_speed}Mbps ${net_ports}" >> ${workdir}/net_list.log 
    done
   
    all_net_dev=$(cat ${workdir}/net_list.log | sort -n | uniq -c | sed 's/^[ ]*//g' | sed s/' '/*/ | sed s/[[:space:]]//g)
    
    if [ ${check_network_sno} -eq 0 ];then
        echo_color green "result:${hwsn}==========>6-网卡检查通过!当前配置：[${all_net_dev}]"
    fi
}


# 5.1清除临时文件
clear_temp_file() {
    cd /tmp
    rm -rf ./init
    echo_color green "result:${hwsn}==========>7-清除临时文件完毕!"
}

# 5.2重启服务器
host_reboot(){
    sync;sync;sync
    echo_color green "result:${hwsn}==========>8-主机取消重启!"
    echo_color green "result:${hwsn}==========>硬件检查通过!!!"
}


# 0 主函数
main(){
   
    echo_color green "result:${hwsn}==========>0-开始检测中，请等待5~10分钟!"
   
    # 环境检查
    basic_setup

    # 具体检测
    check_cpu
    check_mem
    check_disk
    check_hardware
    check_network
    
    # 清理临时文件
    clear_temp_file
    host_reboot
}

# 执行入口
main
