/oat/task_engine/shells/precheck.sh

metadb check /data/log1 avail disk usage 24 GB < MEM * 3 (48 GB) ... EXPECT > MEM * 3 (48 GB)-CSDN博客

复制代码
[root@0b9dc47b15b4 shells]# ls -l
total 84
drwxr-xr-x 4 root root    39 Feb  4  2026 clonescripts
-rwxr-xr-x 1 root root  1098 Aug 21  2023 config_local_dns_in_docker.sh
-rwxr-xr-x 1 root root  2792 Sep  4  2025 config_local_dns.sh
-rwxr-xr-x 1 root root 10176 Dec 12  2025 config_lvm.sh
-rwxr-xr-x 1 root root  4902 Dec 12  2025 install_docker.sh
-rwxr-xr-x 1 root root 54307 Aug 10 19:40 precheck.sh
[root@0b9dc47b15b4 shells]#
[root@0b9dc47b15b4 shells]# pwd
/oat/task_engine/shells
[root@0b9dc47b15b4 shells]#
[root@0b9dc47b15b4 shells]#
[root@0b9dc47b15b4 shells]#
[root@0b9dc47b15b4 shells]#
复制代码
[root@localhost ~]# docker exec -it oat bash
[root@0b9dc47b15b4 oat]#
[root@0b9dc47b15b4 oat]#
[root@0b9dc47b15b4 oat]# ll
bash: ll: command not found
[root@0b9dc47b15b4 oat]# ls
antman             distribution      locale      oat         oat_exporter  Pipfile.lock  requirements.txt  task_engine
cleanup_script.sh  hardware_monitor  manage.py   oatcli      oceanbase     prometheus    static
config.yaml        LEGAL.md          mime.types  oatcli.log  Pipfile       pytest.ini    static_root
[root@0b9dc47b15b4 oat]#
[root@0b9dc47b15b4 oat]# pwd
/oat
[root@0b9dc47b15b4 oat]# cd task_engine/
[root@0b9dc47b15b4 task_engine]#
[root@0b9dc47b15b4 task_engine]# ls
airflow.cfg  dags  logs  plugins  __pycache__  shells  software_packages  webserver_config.py
[root@0b9dc47b15b4 task_engine]#
[root@0b9dc47b15b4 task_engine]# cd plugins/
[root@0b9dc47b15b4 plugins]#
[root@0b9dc47b15b4 plugins]# ls
common.py  hooks  oat_orm.py  operators  __pycache__  sensors  shared_conf.py  utils.py
[root@0b9dc47b15b4 plugins]#
[root@0b9dc47b15b4 plugins]# cd ..
[root@0b9dc47b15b4 task_engine]# ls
airflow.cfg  dags  logs  plugins  __pycache__  shells  software_packages  webserver_config.py
[root@0b9dc47b15b4 task_engine]#
[root@0b9dc47b15b4 task_engine]# cd shells/
[root@0b9dc47b15b4 shells]#
[root@0b9dc47b15b4 shells]# ls
clonescripts  config_local_dns_in_docker.sh  config_local_dns.sh  config_lvm.sh  install_docker.sh  precheck.sh
[root@0b9dc47b15b4 shells]#
[root@0b9dc47b15b4 shells]# pwd
/oat/task_engine/shells
[root@0b9dc47b15b4 shells]#
[root@0b9dc47b15b4 shells]# grep -n -A10 -B5 "avail_log1" precheck.sh
391-    fi
392-
393-    if [[ $dir == "$EXPECT_LOG_DIR" ]] && [[ $machine_role == "observer" ]]; then  # only pure observer check ob log dir, metadb check when create
394-        total_mem_triple=$(grep MemTotal /proc/meminfo | awk '{print int($2/1024/1024*3)}')
395-        total_mem_quadruple=$(grep MemTotal /proc/meminfo | awk '{print int($2/1024/1024*4)}')
396:        avail_log1=$(df "$dir" | tail -n 1 | awk '{print int($4/1024/1024)}')
397-        if is_loose_mode; then
398-            target_mem=$total_mem_triple
399-        else
400-            target_mem=$total_mem_quadruple
401-        fi
402:        if [[ $avail_log1 -ge $target_mem ]]; then
403:            echo_pass "check $dir avail disk usage $avail_log1 GB >= MEM * 4 ($total_mem_quadruple GB)"
404-        else
405:            echo_warn "check $dir avail disk usage $avail_log1 GB < MEM * 4 ($total_mem_quadruple GB) ... EXPECT > MEM * 3 ($total_mem_triple GB) in loose mode and >= MEM * 4 ($total_mem_quadruple GB) in strict mode"
406-            echo_warn_hint "expand disk of $dir, must > MEM * 3 ($total_mem_triple GB) in loose mode and >= MEM * 4 ($total_mem_quadruple GB) in strict mode"
407-        fi
408-    fi
409-}
410-
411-check_user() {
412-    for user_pass in "${EXPECT_USER_PASSWORD[@]}"
413-    do
414-        user=$(echo "$user_pass" | awk -F'/' '{print $1}')
415-        USER_EXIST=true
[root@0b9dc47b15b4 shells]#
[root@0b9dc47b15b4 shells]#
复制代码
[root@localhost ~]# docker cp oat:/oat/task_engine/shells/precheck.sh /root/precheck.sh.bak
Successfully copied 56.3kB to /root/precheck.sh.bak
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# ll
总用量 722728
-rw------- 1 root root      2519  7月  8  2025 anaconda-ks.cfg
drwxrwxr-x 2 1000 1000       146 10月 26  2023 docker
-rw-r--r-- 1 root root  69831072  8月  5 17:56 docker-24.0.7.tgz
-rw-r--r-- 1 root root      2793  7月  8  2025 initial-setup-ks.cfg
-rw-r--r-- 1 root root 669227311  8月  5 18:08 oat_4.4.1_20260206_x86.tgz
-rwxr-xr-x 1 root root     54307  8月 10 19:40 precheck.sh.bak
-rw-r--r-- 1 root root    942380  7月 30 16:03 zabbix-agent-6.0.41-4.ky10.x86_64.rpm
[root@localhost ~]#
[root@localhost ~]#
复制代码
precheck.sh

#!/bin/bash
export LANG="en_US.UTF-8"

REMOTE_WORKING_DIR="$(dirname "$0")"
pre_check_summary_file=${REMOTE_WORKING_DIR}/pre_check_summary.log
rm -rf $pre_check_summary_file
pre_check_warning_summary_file=${REMOTE_WORKING_DIR}/pre_check_warning_summary.log
rm -rf $pre_check_warning_summary_file

check_ip_addr() {
    echo $1|grep "^[0-9]\{1,3\}\.\([0-9]\{1,3\}\.\)\{2\}[0-9]\{1,3\}$" > /dev/null;
    if [ $? -ne 0 ]; then
        return 1
    fi
    ipaddr=$1
    a=`echo $ipaddr|awk -F . '{print $1}'`
    b=`echo $ipaddr|awk -F . '{print $2}'`
    c=`echo $ipaddr|awk -F . '{print $3}'`
    d=`echo $ipaddr|awk -F . '{print $4}'`
    for num in $a $b $c $d
    do
        if [ $num -gt 255 ] || [ $num -lt 0 ]; then
            return 1
        fi
    done
    return 0
}

is_centos7_or_uosc(){
    if [[ -f /etc/redhat-release ]] && grep -q 'release 7' /etc/redhat-release &>/dev/null ; then
        return 0
    elif [[ -f /etc/system-release ]] && [[ -f /etc/os-version ]] &&  grep -Eiq 'uos|uniontech' /etc/system-release && grep -q "=c" /etc/os-version ; then
        return 0
    else
        return 1
    fi
}

is_kylin_like(){
  if [[ -f /etc/kylin-release ]]; then
    return 0
  elif [[ -f /etc/system-release ]] && [[ -f /etc/os-version ]] && grep -Eiq 'uos|uniontech' /etc/system-release && grep -q "=[ae]" /etc/os-version ; then
    return 0
  elif [[ -f /etc/os-release ]] && grep -Eqi 'redflag|openeuler|nfschina|anolis|fusionos|bclinux|hopestage' /etc/os-release &>/dev/null; then
    return 0
  elif [[ -f /etc/redhat-release ]] && grep -q 'release 8' /etc/redhat-release &>/dev/null; then
    return 0
  else
    return 1
  fi
}

is_suse(){
    which zypper &> /dev/null
}

is_debian() {
    which apt-get &> /dev/null
}

# check if processer is ARM
is_arm() {
    uname -m | grep -qi aarch64
}

is_x86() {
    uname -m | grep -qi x86_64
}

is_intel() {
    grep vendor_id /proc/cpuinfo | grep -i intel &>/dev/null
}

is_hygon() {
    lscpu | grep -i Hygon &>/dev/null
}

is_kunpeng() {
    lscpu 2>/dev/null | grep -iq "kunpeng" || dmidecode 2>/dev/null | grep -iq "kunpeng"
}

is_loose_mode() {
    test "$OAT_RUN_MODE" = loose
}

usage() {
    cat <<EOF
Usage: sh $0

Options:
  -h, --help                   Print help and exit
  -V, --version                Print version
  -m, --machine-role string    Current machine role, example: [ observer | obproduct | arbitrationservice | both ], default: ocp
  -l, --ip-list string         Peer ip list, check clock diff and packet loss, example: 1.1.1.1,2.2.2.2

Example:
  sh $0
  sh $0 -m ob
  sh $0 -m ob -l 1.1.1.1,2.2.2.2

EOF
}

while true; do
    case $1 in
        -h | --help ) usage; exit 0;;
        -V | --version ) echo -e "$0 ($0 $VERSION)\nCopyright (c) 2007-2019 Alipay Inc."; exit 0;;
        -m | --machine-role )
            if [ "$2" ]; then
                if [[ "$2" != "observer" && "$2" != "obproduct" && "$2" != "arbitrationservice" && "$2" != "both" ]]; then
                    echo -e "incorrect machine role, must be [ observer | obproduct | arbitrationservice | both ].\n"; usage; exit 1
                fi
                machine_role=$2; shift 2
            else
                echo -e "$1 requires an argument.\n"; usage; exit 1
            fi
            ;;
        -l | --ip-list )
            if [ "$2" ]; then
                mapfile -t observer_ip_list < <(echo "$2" | awk -F ',' '{for(i=1;i<=NF;i++){print $i}}' | sort)
                for ip in "${observer_ip_list[@]}"
                do
                    ip="${ip// /}"
                    check_ip_addr "$ip"
                    if ! check_ip_addr "$ip"; then
                        echo -e "incorrect ip: $ip, please check.\n"; usage; exit 1
                    fi
                done
                shift 2
            else
                echo -e "$1 requires an argument.\n"; usage; exit 1
            fi
            ;;
        -- ) shift; break ;;
        -?* ) echo -e "unknown flag: $1.\n"; usage; exit 1;;
        * ) break
    esac
done

port_in_config=$(grep -E "^Port " /etc/ssh/sshd_config| head -1 | awk '{print $2}')
if [ "$port_in_config" != "" ]; then
    ssh_port=$port_in_config
else
    ssh_port=22
fi

if [[ "$machine_role" == "" ]]; then
    machine_role="both"
fi

## expect values
if [[ "$machine_role" == "arbitrationservice" ]]; then  # support 4C 8G
    EXPECT_CPU=4
    EXPECT_MEM=7
elif is_loose_mode; then
  EXPECT_CPU=${MIN_CPU-8}
  EXPECT_MEM=${MIN_MEMORY-30}
else
  EXPECT_CPU=${MIN_CPU-32}
  EXPECT_MEM=${MIN_MEMORY-120}
fi
EXPECT_USER=${OB_OS_USER-admin}
EXPECT_DATA_DIR=${OB_DATA_DIR:-/data/1}
EXPECT_LOG_DIR=${OB_LOG_DIR:-/data/log1}
EXPECT_SOFTWARE_DIR=${OB_SOFTWARE_DIR:-/home/"$EXPECT_USER"}
IP_PROTOCOL=${IP_PROTOCOL:-IPv4}

EXPECT_SELINUX="Disabled"
if [[ "$machine_role" == "obproduct" ]] || [[ "$machine_role" == "arbitrationservice" ]]; then
  EXPECT_DIR_LIST=("$EXPECT_SOFTWARE_DIR")
else
  EXPECT_DIR_LIST=("$EXPECT_DATA_DIR" "$EXPECT_LOG_DIR" "$EXPECT_SOFTWARE_DIR")
fi

EXPECT_DIR_PERCENT=50
EXPECT_USER_PASSWORD=("$EXPECT_USER"/xxx)
EXPECT_OFFSET=50
if [[ "$IP_PROTOCOL" == "IPv4" ]]; then
    EXPECT_SYSCTL="net.core.somaxconn = 2048;net.core.netdev_max_backlog = 10000;net.core.rmem_default = 16777216;net.core.wmem_default = 16777216;net.core.rmem_max = 16777216;net.core.wmem_max = 16777216;net.ipv4.conf.default.rp_filter = 1;net.ipv4.conf.default.accept_source_route = 0;net.ipv4.tcp_syncookies = 1;net.ipv4.tcp_rmem = 4096 87380 16777216;net.ipv4.tcp_wmem = 4096 65536 16777216;net.ipv4.tcp_max_syn_backlog = 16384;net.ipv4.tcp_fin_timeout = 15;net.ipv4.tcp_max_syn_backlog = 16384;net.ipv4.tcp_tw_reuse = 1;net.ipv4.tcp_slow_start_after_idle = 0;vm.swappiness = 0;kernel.core_pattern = |/bin/bash -c \"\\\$@\" -- eval zstd -T4 -o ${EXPECT_DATA_DIR%/}/core-%e-%p-%t.zst;vm.max_map_count = 655360;fs.aio-max-nr=1048576;vm.overcommit_memory = 0;vm.nr_hugepages = 0"
else
    EXPECT_SYSCTL="net.core.somaxconn = 2048;net.core.netdev_max_backlog = 10000;net.core.rmem_default = 16777216;net.core.wmem_default = 16777216;net.core.rmem_max = 16777216;net.core.wmem_max = 16777216;net.ipv6.conf.default.accept_source_route = 0;net.ipv4.tcp_rmem = 4096 87380 16777216;net.ipv4.tcp_wmem = 4096 65536 16777216;net.ipv4.tcp_max_syn_backlog = 16384;net.ipv4.tcp_fin_timeout = 15;net.ipv4.tcp_max_syn_backlog = 16384;net.ipv4.tcp_slow_start_after_idle = 0;vm.swappiness = 0;kernel.core_pattern = |/bin/bash -c \"\\\$@\" -- eval zstd -T4 -o ${EXPECT_DATA_DIR%/}/core-%e-%p-%t.zst;vm.max_map_count = 655360;fs.aio-max-nr=1048576;vm.overcommit_memory = 0;vm.nr_hugepages = 0"
fi

# 如果服务器内存小于8G,不设置vm.min_free_kbytes, 使用系统默认值,也不去检查
total_mem_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}')
if [[ $((total_mem_kb/1024/1024)) -ge 30 ]]; then
    target_mem_kb=$((total_mem_kb/200))
    EXPECT_SYSCTL="$EXPECT_SYSCTL;vm.min_free_kbytes = $target_mem_kb"
fi

if [[ "$machine_role" == "observer"  ]]; then
    if [[ "$IP_PROTOCOL" == "IPv4" ]]; then
        EXPECT_SYSCTL="$EXPECT_SYSCTL;net.ipv4.ip_forward = 0;net.ipv4.ip_local_port_range = 3500 65535"
    else
        EXPECT_SYSCTL="$EXPECT_SYSCTL;net.ipv6.conf.all.forwarding = 0;net.ipv4.ip_local_port_range = 3500 65535"
    fi
else
    if [[ "$IP_PROTOCOL" == "IPv4" ]]; then
        EXPECT_SYSCTL="$EXPECT_SYSCTL;net.ipv4.ip_forward = 1;net.ipv4.ip_local_port_range = 10000 65535"
    else
        EXPECT_SYSCTL="$EXPECT_SYSCTL;net.ipv6.conf.all.forwarding = 1;net.ipv4.ip_local_port_range = 10000 65535"
    fi
fi
EXPECT_LIMITS=(-n/655350/open_files/nofile -u/655350/max_user_processes/nproc -s/10240/stack_size/stack -c/unlimited/core_file_size/core -t/unlimited/cpu_time/cpu)
EXPECT_SECTOR_SIZE=512
EXPECT_LOSS_RATE=0

if is_arm; then
    EXPECT_PHY_CLOCKSOURCE="arch_sys_counter"
else
    EXPECT_PHY_CLOCKSOURCE="tsc"
fi

IS_CHECK_PASS="true"

is_virtual_machine() {
    if which systemd-detect-virt &>/dev/null; then
        systemd-detect-virt &> /dev/null
    else
        dmidecode -s system-product-name | grep -iq ecs
    fi
}

# check red-hat release 6
is_rhel_6 () {
  if [[ -f /etc/redhat-release ]]; then
    if [[ `grep "release 6" /etc/redhat-release | wc -l` -gt 0 ]]; then
      return 0
    else
      return 1
    fi
  else
    return 1
  fi
}

#
# check red-hat release 7
#
is_rhel_7 () {
  if [[ -f /etc/redhat-release ]]; then
    if [[ `grep "release 7" /etc/redhat-release | wc -l` -gt 0 ]]; then
      return 0
    else
      return 1
    fi
  else
    return 0
  fi
}

echo_error() {
    echo -e " Warnning: """ $1
}

echo_pass() {
    echo -e "$1 ... PASS "
}

# error summary
echo_fail() {
    echo -e "$1 ... FAIL " | tee -a $pre_check_summary_file
    IS_CHECK_PASS="false"
}

# error hint
echo_hint() {
    echo -e "TIPS: $1" | tee -a $pre_check_summary_file
}

# warning summary
echo_warn() {
    echo -e "\x01$1  WARN " | tee -a $pre_check_warning_summary_file
    IS_CHECK_PASS="false"
}

# warning hint
echo_warn_hint() {
    echo -e "\x01TIPS: $1" | tee -a $pre_check_warning_summary_file
}

set_sshtunnel() {
    if [ ! -f /root/.ssh/id_rsa -o ! -f /root/.ssh/id_rsa.pub ]; then
        echo | ssh-keygen -t rsa -f /root/.ssh/id_rsa -q -P ''
    fi
    ssh -o PreferredAuthentications=publickey -o StrictHostKeyChecking=no -p ${ssh_port} 127.0.0.1 "date"
    if [ "$?" -eq 0 ]; then
        return
    else
        cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
    fi
}

check_resource() {
    cpu_count=$(cat /proc/cpuinfo | grep "processor" | wc -l)
    if [ $cpu_count -lt $EXPECT_CPU ]; then
        echo_fail "check CPU count: $cpu_count < $EXPECT_CPU ... EXPECT >= $EXPECT_CPU"
        echo_hint "replace another machine with more CPU"
    else
        echo_pass "check CPU count: $cpu_count > $EXPECT_CPU"
    fi

    total_mem=$(cat /proc/meminfo | grep MemTotal | awk '{print int($2/1024/1024)}')
    if [ $total_mem -lt $EXPECT_MEM ]; then
        echo_fail "check total MEM: $total_mem GB < $EXPECT_MEM GB ... EXPECT >= $EXPECT_MEM GB"
        echo_hint "replace another machine with more MEM"
    else
        echo_pass "check total MEM: $total_mem GB > $EXPECT_MEM GB"
    fi

    if [[ -f /usr/sbin/getenforce ]]; then
        selinux_status=$(/usr/sbin/getenforce)
        if [ "$selinux_status" != $EXPECT_SELINUX ]; then
            if echo "$selinux_status" | grep -iwq permissive; then  # permissive then check config
                if grep -iq '^[[:space:]]*selinux=disabled' /etc/selinux/config; then
                    echo_pass "check SELinux status: $selinux_status, selinux=disabled is in /etc/selinux/config"
                else
                    echo_fail "check SELinux status: $selinux_status ... selinux=disabled is not in /etc/selinux/config"
                    echo_hint "disable SELinux\n  sed -i 's/enforcing/disabled/g' /etc/selinux/config\n  /usr/sbin/setenforce 0"
                fi
            else
                echo_fail "check SELinux status: $selinux_status ... EXPECT $EXPECT_SELINUX"
                echo_hint "disable SELinux\n  sed -i 's/enforcing/disabled/g' /etc/selinux/config\n  /usr/sbin/setenforce 0"
            fi
        else
            echo_pass "check SELinux status: $selinux_status"
        fi
    else
        echo_pass "SELinux is not installed. "
    fi
}

check_folder() {
    for dir in "${EXPECT_DIR_LIST[@]}"
    do
        if [[ "$dir" == "$EXPECT_DATA_DIR" || "$dir" == "$EXPECT_LOG_DIR" ]]; then
            if [[ ! -d "$dir" ]]; then
                echo_fail "check $dir, NOT exist ... EXPECT mounted as individual disk"
                echo_hint "create the $dir folder and re-part disk to mount $dir"
                continue
            fi

            local ret
            dir=$(readlink -f "${dir}")
            ret=$(df -l | grep -cw "${dir}$")
            qdfs_ret=$(df -T | grep "qdfs" | grep -cw "${dir}")
            if [[ $ret -eq 1 ]] || [[ $qdfs_ret -eq 1 ]]; then
                echo_pass "check $dir: exist and mounted as individual disk"
                check_dir_param "$dir"
            else
                echo_fail "check $dir, NOT mounted ... EXPECT mounted as individual disk"
                echo_hint "re-part disk to mount $dir"
            fi
        else
            if [ -d "$dir" ]; then
                echo_pass "check $dir, exist"
                check_dir_param "$dir"
            else
                echo_fail "check $dir, NOT exist ... EXPECT exist"
                echo_hint "create $dir\n  mkdir -p $dir && chown $EXPECT_USER:$EXPECT_USER $dir"
            fi
        fi
    done
}

check_dir_param() {
    dir=$1
    owner=$(ls -ld $dir | awk '{print $3}')
    if [[ $owner = "$EXPECT_USER" ]]; then
        echo_pass "check $dir owner: $EXPECT_USER"
    else
        echo_fail "check $dir owner: $owner ... EXPECT $EXPECT_USER"
        echo_hint "modify owner of $dir\n  chown $EXPECT_USER:$EXPECT_USER $dir"
    fi

    size_info=$(df -h $dir | tail -n 1 | awk '{print "total: "$2", used: "$3", use%: "$5}')
    use_percent=$(df -h $dir | tail -n 1 | awk '{print $5}' | sed "s/%//g")

    local expect_dir_percentage
    if [[ $dir = "$EXPECT_DATA_DIR" ]]; then
        expect_dir_percentage=91
    else
        expect_dir_percentage=$EXPECT_DIR_PERCENT
    fi

    if [ "$use_percent" -lt "$expect_dir_percentage" ]; then
        echo_pass "check $dir disk usage, $size_info < $expect_dir_percentage%"
    else
        echo_fail "check $dir disk usage, $size_info > $expect_dir_percentage% ... EXPECT < $expect_dir_percentage%"
        echo_hint "expand disk of $dir"
    fi

    if [[ $dir == "$EXPECT_LOG_DIR" ]] && [[ $machine_role == "observer" ]]; then  # only pure observer check ob log dir, metadb check when create
        total_mem_triple=$(grep MemTotal /proc/meminfo | awk '{print int($2/1024/1024*3)}')
        total_mem_quadruple=$(grep MemTotal /proc/meminfo | awk '{print int($2/1024/1024*4)}')
        avail_log1=$(df "$dir" | tail -n 1 | awk '{print int($4/1024/1024)}')
        if is_loose_mode; then
            target_mem=$total_mem_triple
        else
            target_mem=$total_mem_quadruple
        fi
        if [[ $avail_log1 -ge $target_mem ]]; then
            echo_pass "check $dir avail disk usage $avail_log1 GB >= MEM * 4 ($total_mem_quadruple GB)"
        else
            echo_warn "check $dir avail disk usage $avail_log1 GB < MEM * 4 ($total_mem_quadruple GB) ... EXPECT > MEM * 3 ($total_mem_triple GB) in loose mode and >= MEM * 4 ($total_mem_quadruple GB) in strict mode"
            echo_warn_hint "expand disk of $dir, must > MEM * 3 ($total_mem_triple GB) in loose mode and >= MEM * 4 ($total_mem_quadruple GB) in strict mode"
        fi
    fi
}

check_user() {
    for user_pass in "${EXPECT_USER_PASSWORD[@]}"
    do
        user=$(echo "$user_pass" | awk -F'/' '{print $1}')
        USER_EXIST=true

        if grep -q "^$user:" /etc/passwd; then
            HOME_PATH=$(grep "^$user:" /etc/passwd | cut -d':' -f 6)
            if [[ ! -d $HOME_PATH ]]; then
                echo_fail "check [$user] home dir, NOT exist ... EXPECT exist"
                echo_hint "create home dir of $user\n  su $user -c \"mkdir -p /home/$user\""
                USER_EXIST=false
            fi
        else
            echo_fail "check user [$user], NOT exist ... EXPECT exist"
            echo_hint "add user [$user]\n  useradd $user"
            USER_EXIST=false
        fi

        if $USER_EXIST;then
            echo_pass "check account [$user] and home dir, exist"
        else
            IS_CHECK_PASS="false"
        fi
    done
}


check_clock_sync() {
    ps -C ntpd &> /dev/null
    if [ $? -eq 0 ]; then
        ntp_server=$(ntpq -np | grep -e '^*' | awk '{print $1}' | sed 's/*//g')
        if [[ "$ntp_server" != "" ]]; then
            echo_pass "check clock sync service: ntpd, ntp server: $ntp_server"
            clock_offset=$(ntpq -np | grep -e '^*' | awk '{print ($9>0)?$9:-$9}')
            if echo "${clock_offset}" $EXPECT_OFFSET | awk '{if($1 > $2) exit 1}'; then
                echo_pass "check ntp clock offset: ${clock_offset}ms <= ${EXPECT_OFFSET}ms"
            else
                echo_fail "check ntp clock offset: ${clock_offset}ms > ${EXPECT_OFFSET}ms, time NOT sync ... EXPECT <= ${EXPECT_OFFSET}ms"
                echo_hint "force sync ntp date\n  ntpdate -b $ntp_server"
            fi
        else
            echo_fail "check clock sync service: ntpd, ntp server NOT found ... EXPECT ntp server"
            echo_hint "check ntpd service\n  systemctl status ntpd\n  ntpq -np"
        fi
        return
    fi

    ps -C chronyd &> /dev/null
    if [ $? -eq 0 ]; then
        chrony_server=$(chronyc sources | grep -e '^\^\*' | awk '{print $2}')
        if [[ "$chrony_server" != "" ]]; then
            echo_pass "check clock sync service: chronyd, chrony server: $chrony_server"
            clock_offset=$(chronyc sources | grep -e '^\^\*' | sed 's/.*\[\(.*\)\].*/\1/g' | sed 's/ //g')
            unit=$(echo $clock_offset | sed "s/${clock_offset:0:1}[0-9]*\(.*\)/\1/g")
            original_offset=$(echo ${clock_offset:1} | sed "s/$unit//g")
            if [[ "$unit" == "ns" ]]; then
                clock_offset=0
            elif [[ "$unit" == "us" ]]; then
                clock_offset=$(echo | awk '{printf ("%.3f\n","'$original_offset'"/1000)}')
            elif [[ "$unit" == "ms" ]]; then
                clock_offset=$(echo | awk '{printf ("%.3f\n","'$original_offset'"/1)}')
            elif [[ "$unit" == "s" ]]; then
                clock_offset=$(echo | awk '{printf ("%.3f\n","'$original_offset'"*1000)}')
            else
                echo_fail "ERROR while checking clock offset"
            fi
            if echo "${clock_offset}" $EXPECT_OFFSET | awk '{if($1 > $2) exit 1}'; then
                echo_pass "check chrony clock offset: ${clock_offset}ms <= ${EXPECT_OFFSET}ms"
            else
                echo_fail "check chrony clock offset: ${clock_offset}ms > ${EXPECT_OFFSET}ms, time NOT sync ... EXPECT <= ${EXPECT_OFFSET}ms"
                echo_hint "force sync time\n  chronyc makestep"
            fi
        else
            echo_fail "check clock sync service: chronyd, chrony server NOT found ... EXPECT chrony server"
            echo_hint "check chronyd service\n  systemctl status chronyd\n  chronyc sources"
        fi
        return
    fi

    echo_fail "check clock sync service, NOT found ... EXPECT ntpd/chronyd"
    echo_hint "install, config and start chronyd/ntpd service"
    return
}

check_transparent_hugepage() {
    # never enable transparent hugepage, jiyuan and junyuan required
    if [ -f /sys/kernel/mm/transparent_hugepage/enabled ]; then
        if grep -q '\[never\]' /sys/kernel/mm/transparent_hugepage/enabled ;then
            echo_pass "check hugepage: disabled"
        else
            echo_fail "check hugepage: enabled ... EXPECT disabled"
            echo_hint "disable hugepage\n  echo never > /sys/kernel/mm/transparent_hugepage/enabled"
        fi
    elif [ -f /sys/kernel/mm/redhat_transparent_hugepage/enabled ]; then
        if grep -q '\[never\]' /sys/kernel/mm/redhat_transparent_hugepage/enabled ;then
            echo_pass "check hugepage: disabled"
            #cat /sys/kernel/mm/transparent_hugepage/enabled
        else
            echo_fail "check hugepage: enabled ... EXPECT disabled"
            echo_hint "disable hugepage\n  echo never > /sys/kernel/mm/redhat_transparent_hugepage/enabled"
        fi
    else
        echo_fail "check hugepage: can not get THP status ... EXPECT disabled"
    fi
}

check_default_proc() {
    ps aux | grep -i -E $1 | grep -v grep > /dev/null
    if [ $? -ne 0 ];then
        echo_fail "check proc $1, NOT running ... EXPECT running"
        echo_hint "start $1 service\n  systemctl start $1"
    else
        echo_pass "check proc $1, running"
    fi
}

check_default_procs() {
  #-----------check default process----------
  check_default_proc crond
  #check_default_proc irqbalance
  check_default_proc ntpd
  check_default_proc sshd
  check_default_proc syslog-ng
}

check_one(){
    CONFIG=`echo $1 | cut -d"=" -f1 | sed "s/ //g"`
    NAME=/proc/sys/`echo $1 | cut -d"=" -f1 | tr "." "/" | sed "s/ //g"`
    VALUE1=`cat $NAME | tr "\t" " "`
    VALUE2=`echo $1 | cut -d"=" -f2| sed 's/^ //g'`

    if [ "$VALUE1" != "$VALUE2" ]; then
        echo_fail "sysctl $NAME = $VALUE1, NOT correct ... EXPECT $VALUE2"
        curr_sysctl_value=$(cat /etc/sysctl.conf | grep -i -E "^$CONFIG" | awk '{print $2}')
        if [[ "$curr_sysctl_value" == "" ]]; then
            echo_hint "modify config in /etc/sysctl.conf\n  echo '$CONFIG = $VALUE2' >> /etc/sysctl.conf\n  sysctl -p"
        else
            echo_hint "modify config in /etc/sysctl.conf\n  sed -i '/^$CONFIG/c$CONFIG = $VALUE2' /etc/sysctl.conf\n  sysctl -p"
        fi
        echo_hint "If the above method still doesn't work, please check $CONFIG configuration in other profile releated config files, e.g./etc/sysctl.d/*、/etc/profile.d/* and update these settings correspondingly."
    else
        echo_pass "sysctl $NAME = $VALUE1, correct"
    fi
}

check_sysctl() {
    echo "$EXPECT_SYSCTL" | awk -F ';' '{for(i=1;i<=NF;i++){print $i}}' > ${REMOTE_WORKING_DIR}/expect_sysctl
    while read line
    do
        check_one "$line"
    done < ${REMOTE_WORKING_DIR}/expect_sysctl
    rm -rf ${REMOTE_WORKING_DIR}/expect_sysctl
}

check_reboot() {
    REBOOT_TIME=`last |  grep -E -i "^reboot" | wc -l`
    if [ $REBOOT_TIME -lt 2 ];then
        echo_fail "check OS, NOT reboot ... EXPECT reboot"
        return
    else
        echo_pass "check OS, already rebooted"
    fi
}


modify_grub_warning_tips() {
    local action=$1  # add/remove
    local args=$2
    # calculate grub file location
    os_id=`source /etc/os-release;echo $ID`
    if [[ -d "/sys/firmware/efi" ]]; then
        if [ -f "/boot/efi/EFI/$os_id/grub.cfg" ]; then
            GRUB_CFG_FILE="/boot/efi/EFI/$os_id/grub.cfg"
        else
            GRUB_CFG_FILE=$(find /boot/efi -name grub.cfg)
        fi
    else
        if [[ -f "/boot/grub2/grub.cfg" ]]; then
            GRUB_CFG_FILE="/boot/grub2/grub.cfg"
        else
            GRUB_CFG_FILE="/boot/grub/grub.cfg"
        fi
    fi

    if which grub2-mkconfig &>/dev/null; then
        GRUB_COMMAND="grub2-mkconfig"
    else
        GRUB_COMMAND="grub-mkconfig"
    fi

    if which grubby &>/dev/null; then
        if [[ "$action" == "add" ]]; then
            echo_warn_hint "The steps to set ${args} in kernel startup parameters can be refer to:
1, grubby --update-kernel=ALL --args=\"${args}\"
2, reboot the system
3, if steps 1 and 2 do not work, try executing $GRUB_COMMAND -o $GRUB_CFG_FILE and then reboot"
        elif [[ "$action" == 'remove' ]]; then
            echo_warn_hint "The steps to set ${args} in kernel startup parameters  can be refer to:
1, grubby --update-kernel=ALL --remove-args=\"${args}\"
2, reboot the system
3, if steps 1 and 2 do not work, try executing $GRUB_COMMAND -o $GRUB_CFG_FILE and then reboot"
        fi
    else
        if [[ "$action" == "add" ]]; then
            echo_warn_hint "The steps to set ${args} in kernel startup parameters can be refer to:
1, add \"${args}\" at the end of kernel command line(GRUB_CMDLINE_LINUX) in boot loader configuration file(/etc/default/grub), for example: GRUB_CMDLINE_LINUX=\"rd.lvm.lv=rhel_vm-210/root rd.lvm.lv=rhel_vm-210/swap vconsole.font=latarcyrheb-sun16 crashkernel=auto  vconsole.keymap=us rhgb quiet ${args}\"
2, $GRUB_COMMAND -o $GRUB_CFG_FILE
3, reboot the system"
        elif [[ "$action" == 'remove' ]]; then
            echo_warn_hint "The steps to remove ${args} in kernel startup parameters can be refer to:
1, remove \"${args}\" at the end of kernel command line(GRUB_CMDLINE_LINUX) in boot loader configuration file(/etc/default/grub)
2, $GRUB_COMMAND -o $GRUB_CFG_FILE
3, reboot the system"
        fi
    fi
}

check_numa() {
    if is_virtual_machine || is_loose_mode; then
      echo_pass "not phy machine or in loose mode, skip check numa stat, pass"
      return
    fi

    if is_intel; then  # 20250508 intel numa insensitive but can not bios on and kernel off
        if [[ "$WARNING_WHEN_INTEL_NUMA_OFF" == "true" ]] && grep "numa=off" /proc/cmdline; then
            echo_warn "check numa stat failed"
            echo_warn_hint "The current kernel startup parameters are configured with numa=off, please make sure that numa is also turned off in the BIOS/UEFI. If you need to ignore the numa check for Intel CPUs, you can modify the system parameter oat.server.warning_when_intel_numa_off to false"
        else
            echo_pass "check numa stat, pass"
        fi
    else
        # check current numa stat
        num_node=`ls /sys/devices/system/node | grep "^node" | wc -w`
        if [[ $num_node == 1 ]]; then
            echo_warn "check numa stat, node number is $num_node ... EXPECT ARM and Hygon numa on"
            echo_warn_hint "Please turn on numa in BIOS or UEFI, with BIOS/UEFI settings done, if numa is still off, you need to turn on numa in system level."
            modify_grub_warning_tips "add" "numa=on"
        else
            echo_pass "check numa stat, pass"
        fi
    fi
}

check_smmu() {
    if is_virtual_machine || is_loose_mode; then
        echo_pass "not phy machine or in loose mode, skip check smmu/iommu stat, pass"
        return
    fi

    if is_hygon; then
        if ! grep "iommu=off" /proc/cmdline && ! grep "iommu=pt" /proc/cmdline && ! grep "iommu.passthrough=1" /proc/cmdline; then
            echo_warn "check IOMMU failed"
            echo_warn_hint "The kernel startup parameters do not disable IOMMU. If IOMMU has been disabled in BIOS/UEFI, ignore this error. Otherwise you need to set iommu=pt"
            modify_grub_warning_tips "add" "iommu=pt"
        else
            echo_pass "check IOMMU stat, pass"
        fi
    elif is_kunpeng; then
        if ! grep "iommu.passthrough=1" /proc/cmdline; then
            echo_warn "check SMMU failed"
            echo_warn_hint "The kernel startup parameters do not disable SMMU. If SMMU has been disabled in BIOS/UEFI, ignore this error. Otherwise you need to set iommu.passthrough=1"
            modify_grub_warning_tips "add" "iommu.passthrough=1"
        else
            echo_pass "check SMMU stat, pass"
        fi
    fi
}


check_other_grub() {
    if is_loose_mode; then
        if ! grep "mitigations=off" /proc/cmdline; then
            echo_warn "check kernel startup parameters mitigations status failed, need to be set to mitigations=off"
            modify_grub_warning_tips "add" "mitigations=off"
        fi
        if ! grep "tsc=noirqtime" /proc/cmdline; then
            echo_warn "check kernel startup parameters tsc status failed, need to be set to tsc=noirqtime"
            modify_grub_warning_tips "add" "tsc=noirqtime"
        fi
        if (is_hygon || is_kunpeng) && ! grep "nohz=off" /proc/cmdline; then
            echo_warn "check kernel startup parameters nohz status failed, need to be set to nohz=off"
            modify_grub_warning_tips "add" "nohz=off"
        fi
    fi
}


check_elevator() {
    EXPECT_ELEVATOR=deadline  # deadline (rhel 7) or mq-deadline (rhel 8) is ok
    ELEVATOR_OK=true
    if ls /sys/block/sd[a-z] &> /dev/null; then
        for DISK in /sys/block/sd[a-z]
        do
            elevator=$(grep -Eo "\[.*\]" "$DISK"/queue/scheduler)
            if ! (echo "$elevator" | grep -q "$EXPECT_ELEVATOR"); then
                echo_warn "check elevator of $DISK is $elevator ... EXPECT $EXPECT_ELEVATOR"
                echo_warn_hint "set elevator policy to deadline or mq-deadline\n echo <deadline or mq-deadline> > $DISK/queue/scheduler"
                ELEVATOR_OK=false
            fi
        done
    fi

    if [[ $ELEVATOR_OK = true ]]; then
        echo_pass "check elevator policy: deadline or mq-deadline"
    else
        IS_CHECK_PASS="false"
    fi
}

check_limit_conf() {
    #ls -lFa >> /var/clone/some.log
    if [ -e "/etc/security/limits.d/oceanbase_limits.conf" ];then
        echo_pass "check oceanbase_limits.conf, exist"
    else
        echo_fail "check oceanbase_limits.conf, NOT exist ... EXPECT exist"
        echo_hint "copy oceanbase_limits.conf\n  cp dist/oceanbase_limits.conf /etc/security/limits.d/oceanbase_limits.conf"
    fi
}

compare_ulimit() {
  local current_val=$1
  local expect_val=$2

  [[ $current_val = unlimited ]] && current_val=999999999
  [[ $expect_val = unlimited ]] && expect_val=999999999

  if [ $current_val -lt $expect_val ]; then
    return 1
  else
    return 0
  fi
}

check_limit() {
    limit_type_list=(-H/hard -S/soft)
    for limit in "${EXPECT_LIMITS[@]}"
    do
        limit_option=$(echo $limit | awk -F'/' '{print $1}')
        expect_limit=$(echo $limit | awk -F'/' '{print $2}')
        limit_description=$(echo $limit | awk -F'/' '{print $3}')
        limit_item=$(echo $limit | awk -F'/' '{print $4}')
        for limit_type in "${limit_type_list[@]}"
        do
            limit_type_option=$(echo $limit_type | awk -F'/' '{print $1}')
            limit_type_description=$(echo $limit_type | awk -F'/' '{print $2}')
            get_limit_cmd="ulimit $limit_type_option $limit_option"
            # check new session
            current_limit=$(runuser - "$EXPECT_USER" -c "$get_limit_cmd")
            if ! compare_ulimit "$current_limit" "$expect_limit"; then
                echo_fail "check permanent $limit_type_description limit of $limit_description ($get_limit_cmd): $current_limit != $expect_limit ... EXPECT $expect_limit"
                echo_hint "modify /etc/security/limits.d/oceanbase_limits.conf\n  echo \"*   $limit_type_description    $limit_item    $expect_limit\" >> /etc/security/limits.d/oceanbase_limits.conf"
            else
                echo_pass "check $limit_type_description limit of new session $limit_description ($get_limit_cmd): $current_limit"
            fi
            # check current session
            current_limit=$($get_limit_cmd)
            if ! compare_ulimit "$current_limit" "$expect_limit"; then
                if [[ "$limit_option" == "-c" ]]; then
                    echo "check current session $limit_type_description limit of $limit_description ($get_limit_cmd): $current_limit != $expect_limit ... EXPECT $expect_limit"
                else
                    echo_fail "check current session $limit_type_description limit of $limit_description ($get_limit_cmd): $current_limit != $expect_limit ... EXPECT $expect_limit"
                    echo_hint "excute: ulimit $limit_option $expect_limit"
                fi
            else
                echo_pass "check $limit_type_description limit of $limit_description ($get_limit_cmd): $current_limit"
            fi

        done
    done
}

check_ssh() {
    #check_sshd_config "PermitRootLogin" "yes"
    check_sshd_config "PubkeyAuthentication" "yes"
    check_sshd_config "UseDNS" "no"
    check_sshd_config "ClientAliveInterval" "60"
    check_sshd_config "ClientAliveCountMax" "10"
}

check_sshd_config() {
    option=$1
    expect_value=$2
    curr_value=$(cat /etc/ssh/sshd_config | grep -i -E "^$option" | tail -1 | awk '{print $2}')
    if [[ "$curr_value" == "$expect_value" ]];then
        echo_pass "check sshd_config $option: $expect_value"
    else
        echo_fail "check sshd_config $option: $curr_value ... EXPECT $expect_value"
        if [[ "$curr_value" == "" ]]; then
            echo_hint "modify config in /etc/ssh/sshd_config\n  echo '$option $expect_value' >> /etc/ssh/sshd_config\n  systemctl restart sshd"
        else
            echo_hint "modify config in /etc/ssh/sshd_config\n  sed -i '/^$option/c$option $expect_value' /etc/ssh/sshd_config\n  systemctl restart sshd"
        fi
    fi
}

check_single_service() {
    origin_service_name="${1}.service"
    servict_status=$(systemctl list-unit-files --type service | grep "^${origin_service_name}" | awk '{print $2}')
    if [[ "$servict_status" == "alias" ]]; then
        service_name=$(systemctl show -p Id $origin_service_name 2>/dev/null | cut -d= -f2)
        servict_status=$(systemctl list-unit-files --type service | grep "^${service_name}" | awk '{print $2}')
    fi
    echo $servict_status
}

check_service() {
    if is_rhel_6; then
        service_on=(crond netfs network ntpd sshd syslog-ng)
        for i in "${service_on[@]}"
        do
            if ! chkconfig --list $i|grep -q '3:on' > /dev/null;then
                echo_fail "check service [$i]: off ... EXPECT on"
                return
            fi
            echo_pass "check service [$i]: on"
        done
    else
        service_on=(crond cron ntpd sshd syslog-ng)  # The service names of different OS may not be compatible. If they cannot be found, just ignore them.
        for i in "${service_on[@]}"
        do
            service_status=`check_single_service ${i}`
            if [[ "$service_status" != "" ]]; then
                if ! echo $service_status | grep -Eq "enabled|generated"; then
                    if [[ $i == "ntpd" ]]; then
                        i="chronyd"
                        service_status=`check_single_service ${i}`
                        if ! echo $service_status | grep "^enabled" > /dev/null; then
                            echo_fail "check service ["ntpd"/"chronyd"]: $service_status ... EXPECT enabled"
                            echo_hint "enable chronyd/ntpd service\n  systemctl enable chronyd or systemctl enable ntpd"
                            # return
                        fi
                    else
                        echo_fail "check service [$i]: $service_status ... EXPECT enabled"
                        echo_hint "enable $i service\n  systemctl enable $i"
                        # return
                    fi
                else
                    echo_pass "check service [$i]: enabled"
                fi
            fi
        done
    fi
}

check_firewalld() {
    if is_suse; then
        firewalld_name="SuSEfirewall2"
    else
        firewalld_name="firewalld"
    fi
    service_status=$(systemctl is-active $firewalld_name)
    if [[ "$service_status" != "active" ]]; then
        echo_pass "check service [$firewalld_name]: inactive"
    else
        echo_fail "check service [$firewalld_name]: active ... EXPECT inactive"
        echo_hint "stop $firewalld_name service\n  systemctl stop $firewalld_name"
    fi

    service_on=$(systemctl is-enabled $firewalld_name)
    if [[ "$service_on" != "enabled" ]]; then
        echo_pass "check service [$firewalld_name]: disabled"
    else
        echo_fail "check service [$firewalld_name]: enabled ... EXPECT disabled"
        echo_hint "disabled $firewalld_name service\n  systemctl disable $firewalld_name"
    fi
}

check_tsc_timer() {
    local target_timer
    if grep -q kvm-clock /sys/devices/system/clocksource/clocksource0/available_clocksource; then
      target_timer=kvm-clock
    else
      target_timer=$EXPECT_PHY_CLOCKSOURCE
    fi
    curr_clocksource=$(cat /sys/devices/system/clocksource/clocksource0/current_clocksource)
    if [[ "$curr_clocksource" = "$target_timer" ]]; then
        echo_pass "check current_clocksource: $curr_clocksource"
    else
        echo_fail "check current_clocksource: $curr_clocksource ... EXPECT $target_timer"
        echo_hint "modify current_clocksource to $target_timer. eg: append clocksource=$target_timer to GRUB_CMDLINE_LINUX in grub.cfg"
    fi
}

check_irq_affinity() {
    echo "checking irq affinity ..."
    if is_virtual_machine; then
      echo_pass "not phy machine, skip check irq affinity, pass"
      return
    fi

    total_core_num=`grep -c processor /proc/cpuinfo`
    core_num=$((${total_core_num}/8 + 3))

    if [ "${core_num}" -eq 0 ]; then
        echo_fail "check irq affinity, CPU core num NOT found ... EXPECT CPU core num"
        echo_hint "check /proc/cpuinfo"
        return 1
    fi

    phy_net_dev=$(ls /sys/class/net/ | grep -v "$(ls /sys/devices/virtual/net/)" | grep -v bonding_masters)
    net_dev=()
    for dev in $phy_net_dev
    do
        for item in $(ip addr | grep "state UP" | awk '{print $2}' | sed "s/://g")
        do
            if [[ "$dev" == "$item" ]]; then
                net_dev=("${net_dev[@]}" "$dev")
            fi
        done
    done

    if [ "${#net_dev[@]}" -eq 0 ]; then
        echo_fail "check irq affinity, NIC name NOT found ... EXPECT NIC name"
        echo_hint "check network interface card info"
        return 1
    fi

    net_irq_core_num=$core_num

    for nic in "${net_dev[@]}"
    do
        echo "checking ${nic} ..."
        EXPECT_COMBINED=$(ethtool -l ${nic} | grep Combined | head -1 | awk '{print $2}')
        current_combined=$(ethtool -l ${nic}  | grep Combined | tail -1 | awk '{print $2}')
        if [[ "$current_combined" = "$EXPECT_COMBINED" ]]; then  # support rhel8 n/a output
            echo_pass "check irq channels, NIC: $nic, Channel Combined: $current_combined"
        elif [[ $current_combined -lt $EXPECT_COMBINED && $current_combined -lt $core_num ]]; then
            min_num=${EXPECT_COMBINED}
            if [[ ${core_num} -lt ${EXPECT_COMBINED} ]]; then
                min_num=${core_num}
            fi
            echo_fail "check ${nic} irq channels, NIC: $nic, Channel Combined: $current_combined < $min_num ... EXPECT $min_num"
            echo_hint "set irq channels:\n  ethtool -L ${nic} combined $min_num"
            continue
        else
            echo_pass "check irq channels, NIC: $nic, Channel Combined: $current_combined"
        fi

        net_irq=()
        for dev in "${net_dev[@]}"; do
            # try nic name
            grep -q "$dev" /proc/interrupts
            if [ $? -eq 0 ]; then
                net_irq+=(`awk '/'${dev}'[-_]/{print $1}' /proc/interrupts | sed 's/[: ]//g'`)
            else
                # try pci bus num
                bus_id=$(cd /sys/class/net/${dev}/device; pwd -P | awk -F/ '{print $NF}')
                grep -q "$bus_id" /proc/interrupts
                if [ $? -eq 0 ]; then
                    net_irq+=(`awk '/'${bus_id}'/{print $1}' /proc/interrupts | sed 's/[: ]//g'`)
                else
                    # try ethx
                    eth_name=$(ip link |grep "$phy_net_dev" | awk '{if($2 ~ /'$dev'/) print "eth"NR-1 }')
                    if (grep -q "${eth_name}-" /proc/interrupts); then
                        net_irq+=(`awk '/'${eth_name}'-/{print $1}' /proc/interrupts | sed 's/[: ]//g'`)
                    else  # try hinic, the last try
                        net_irq+=(`awk '/hinic_[tr]xq/{print $1}' /proc/interrupts  | sed 's/[: ]//g'`)
                    fi
                fi
            fi
        done

        net_q=${#net_irq[@]}
        if [ "$net_q" -eq 0 ]; then
            echo_fail "check irq affinity, NIC: $nic, NIC queue NOT found ... EXPECT NIC queue"
            echo_hint "check irq affinity of NIC $nic"
            continue
        fi
        if [[ $net_irq_core_num -lt $net_q ]]; then
            EXPECT_SMP_AFFINITY=$net_irq_core_num
        else
            EXPECT_SMP_AFFINITY=$net_q
        fi
        # h=0
        # for irq in ${net_irq[@]}
        # do
        #     net_irq_hit[$h]=$( for((i=0;i<$core_num;i++)) ; do awk -v n=$((i+2)) '/ '$irq':/{print $n}' /proc/interrupts; done | sort -rn | head -1 )
        #     ((h++))
        # done

        rm -rf smp_affinity.tmp && touch smp_affinity.tmp
        for((i=0;i<$net_q;i++))
        do
            irq=${net_irq[i]}
            smp_affinity=$(</proc/irq/$irq/smp_affinity)
            echo ${smp_affinity} >> smp_affinity.tmp
        done
        smp_affinity_count=$(sort smp_affinity.tmp | uniq | wc -l)
        if [ $smp_affinity_count -lt $EXPECT_SMP_AFFINITY ]; then
            echo_fail "check irq affinity, NIC: $nic, smp_affinity count: $smp_affinity_count < $EXPECT_SMP_AFFINITY ... EXPECT $EXPECT_SMP_AFFINITY"
            echo_hint "check irq affinity of NIC $nic"
        else
            echo_pass "check irq affinity, NIC: $nic, smp_affinity count: $smp_affinity_count"
        fi
        rm -rf smp_affinity.tmp
    done

    irqbalance_status=$(systemctl is-active irqbalance)
    irqbalance_service_on=$(systemctl is-enabled irqbalance)

    if [[ "$irqbalance_status" != "active" ]]; then
        echo_pass "check irqbalance status: $irqbalance_status"
    else
        echo_fail "check irqbalance status: $irqbalance_status != inactive ... EXPECT inactive"
        echo_hint "stop irqbalance service on PHY\n  systemctl stop irqbalance"
    fi
    if [[ "$irqbalance_service_on" != "enabled" ]]; then
        echo_pass "check irqbalance service: $irqbalance_service_on"
    else
        echo_fail "check irqbalance service: $irqbalance_service_on != disabled ... EXPECT disabled"
        echo_hint "enable irqbalance service on PHY\n  systemctl disable irqbalance"
    fi
}

check_sector_size() {
    mapfile -t dev_list < <(lsblk | awk '{print $1" "$6}' | grep "disk$" | awk '{print $1}')
    for dev in "${dev_list[@]}"; do
        curr_sector_size=$(cat /sys/block/"$dev"/queue/hw_sector_size)
        if [[ "$curr_sector_size" == "$EXPECT_SECTOR_SIZE" ]]; then
            echo_pass "check logical sector size of /dev/$dev: $curr_sector_size"
        else
            echo_fail "check logical sector size of /dev/$dev: $curr_sector_size ... EXPECT $EXPECT_SECTOR_SIZE"
            echo_hint "only 512 sector is supported before OB 3.1.2 bp3. You may ignore this warn if want to install OB 3.1.2 bp3 or above"
        fi
    done
}

check_cpufreq_governor() {
    if ! is_virtual_machine; then
        IS_CPUFREQ_OK="true"
        if [[ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ]]; then
            performance_cpu_num=`cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor | grep 'performance' | wc -l`
            cpu_num=`cat /proc/cpuinfo | grep ^processor | wc -l`
            if [[ $performance_cpu_num -eq $cpu_num ]]; then
                echo_pass "cpufreq scaling_governor is performance"
            else
                let cpu_num=$cpu_num-1
                for i in $(seq 0 $cpu_num); do
                    scaling_governor=`cat /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor`
                    if [[ $scaling_governor != 'performance' ]]; then
                        echo_fail "cpu$i cpufreq scaling_governor is $scaling_governor ... EXPECT == performance"
                        IS_CPUFREQ_OK="false"
                    fi
                done
            fi
            if [[ "$IS_CPUFREQ_OK" == "false" ]]; then
                echo_hint "modify cpufreq scaling_governor to performance\n  for i in \`ls /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor\`; do echo performance > \$i; done"
            fi
        fi
    fi
}

function version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
function version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" == "$1"; }
function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }

check_rpms() {
    if is_suse; then
        install_cmd="zypper in -y"
        query_cmd="rpm -qa"
    elif is_debian; then
        install_cmd="apt-get -y install"
        query_cmd="dpkg -l"
    elif is_kylin_like; then
        install_cmd="yum install -y"
        query_cmd="rpm -qa"
    else
        install_cmd="yum install -y"
        query_cmd="rpm -qa"
    fi

    for rpm in $NEED_RPM
    do
        grep_rpm=$(echo $rpm | sed 's/+/\\+/g')  # like gcc-g++
        if is_debian; then
            result=$($query_cmd | grep -E "$grep_rpm" | head -n 1 | awk '{printf "%s",$1}')
            if [[ "$result" == "ii" ]]; then
                echo_pass "check RPM: ${rpm} is installed"
            else
                echo_warn "check RPM: $rpm NOT installed ... EXPECT $rpm"
                echo_warn_hint "install RPM $rpm\n  $install_cmd $rpm"
            fi
        else
            result=$($query_cmd | grep -E "$grep_rpm" | head -n 1 | awk '{printf "%s ",$1}')
            if [[ $result != "" ]]; then
                echo_pass "check RPM: ${result}is installed"
            else
                echo_warn "check RPM: $rpm NOT installed ... EXPECT $rpm"
                echo_warn_hint "install RPM $rpm\n  $install_cmd $rpm"
            fi
        fi
    done
}

check_mysql_client() {
    result=$(mysql --version)
    if [[ $result != "" && $? -eq 0 ]]; then
        echo_pass "check mysql client, working"
        major_version=$(mysql -V | awk '{print $3}' | cut -d'.' -f 1)
        [ "$major_version" = "8" ] && echo_warn "check mysql client, version is 8.x ... EXPECT client using mysql_native_password auth or add mariadb to the system parameter oat.server.ignore_deps to ignore this check"
    else
        echo_fail "check mysql client, NOT working ... EXPECT mysql client"
        echo_hint "install mysql client or add mariadb to the system parameter oat.server.ignore_deps to ignore this check"
    fi
}

check_command() {
    echo "need check command is ${NEED_CMD}"
    if is_debian; then
        alter_cmd='update-alternatives'
    else
        alter_cmd='alternatives'
    fi
    for i in $NEED_CMD; do
        if [[ "$i" == "fio" ]]; then
            which $i >/dev/null 2>&1 || echo_warn "can not find command $i. If the observer version to be installed is 4.x or later, you can ignore this or add fio to the system parameter oat.server.ignore_deps."
        elif [[ "$i" == "mysql" ]]; then
            check_mysql_client
        elif [[ "$i" == "python" ]]; then
            python_version=$(python -V 2>&1 | awk '{print $2}')
            if ! echo "$python_version"|grep -q "^2"; then
                echo_warn 'the default "python" command is not version 2.x.'
                echo_warn_hint "install python2 and try use \"${alter_cmd} --install /usr/bin/python python /usr/bin/python2 1\" to set. If the observer version to be installed is 4.2.1.7 or later, you can ignore this or add python2 to the system parameter oat.server.ignore_deps."
            fi
        elif [[ "$i" == "python3" ]]; then
            python_version=$(python -V 2>&1 | awk '{print $2}')
            if ! echo "$python_version"|grep -q "^3"; then
                echo_warn 'the default "python" command is not version 3.x.'
                echo_warn_hint "install python3 and try use \"${alter_cmd} --install /usr/bin/python python /usr/bin/python3 1\" to set or add python3 to the system parameter oat.server.ignore_deps."
            fi
        else
            which $i >/dev/null 2>&1 || echo_warn "can not find command $i"
        fi
    done
}


check_filesystem_type() {
    ## if ob data dir larger than 16T, file system type must be xfs, due to ext4 not allowed to create single file larger than 16T
    if [[ "$machine_role" = "obproduct" ]] || [[ "$machine_role" == "arbitrationservice" ]]; then
        return
    fi
    if [[ ! -d "$EXPECT_DATA_DIR" || ! -d "$EXPECT_LOG_DIR" ]]; then
        echo_fail "check $EXPECT_DATA_DIR and $EXPECT_LOG_DIR filesystem type, $EXPECT_DATA_DIR or $EXPECT_LOG_DIR NOT exist ... EXPECT mounted as individual disk"
        echo_hint "create the $EXPECT_DATA_DIR or $EXPECT_LOG_DIR folder and re-part disk to mount $EXPECT_DATA_DIR or $EXPECT_LOG_DIR with suitable filesystem"
        return
    fi

    real_data_dir=$(readlink -f "${EXPECT_DATA_DIR}")
    total_data1=$(df "$real_data_dir" | tail -n 1 | awk '{print int($2/1024/1024/1024)}')
    if [[ $total_data1 -ge 16 ]]; then
        type_data1=$(df --output=fstype "$real_data_dir" | tail -1)
        if [[ $type_data1 == "ext4" ]]; then
            echo_fail "check $real_data_dir file system type: ${type_data1}, NOT correct ... EXPECT xfs with size larger than 16TB"
            echo_hint "reformat $real_data_dir filesystem with xfs type"
        fi
    fi
    is_loose_mode && return
    # check xfs su if production
    for d in "$EXPECT_DATA_DIR" "$EXPECT_LOG_DIR";
    do
        d=$(readlink -f "${d}")
        if [[ $(df --output=fstype "$d" | tail -1) = xfs ]]; then
            log_sunit=$(xfs_info "$d" | grep sunit= | tail -1  | awk '{print substr($3,7)}')
            if [[ $log_sunit -gt 8 ]]; then
                echo_warn "check $d xfs log sunit: $log_sunit > 8, may cause write amplification"
                echo_warn_hint "reformat $d xfs filesystem with option \"-l su=32k\""
            fi
        fi
    done
}

check_taskset() {
    taskset_output=$(taskset -a -p 1)
    if [[ $taskset_output = *:* ]]; then # chinese
        mask=$(echo "$taskset_output" | awk -F':' '{print $NF}')
    else
        mask=$(echo "$taskset_output" | awk '{print $NF}')
    fi
    mask_bin=$(echo "$mask" | python -c "import sys; a=sys.stdin.read().strip(); print(bin(int(a,16))[2:])")
    if [[ "$mask_bin" =~ '0' ]]; then
        echo_warn "taskset mask for pid 1 is ${mask}"
        echo_warn_hint "make sure bind all cores for observer"
    fi
}

check_clock_diff() {
    for observer in "${observer_ip_list[@]}"
    do
        echo -e "check clock offset (localhost -> $observer): \c"
        clock_offset=$(clockdiff -o "$observer" 2>&1 | awk '{print $3}')
        if [[ $clock_offset == "down" ]]; then
            echo_fail "$observer is unavailable ... EXPECT online"
        else
            if [[ ${clock_offset/-/} -le $EXPECT_OFFSET ]]; then
                echo_pass "${clock_offset}ms <= ${EXPECT_OFFSET}ms"
            else
                echo_fail "${clock_offset}ms > ${EXPECT_OFFSET}ms, time NOT sync ... EXPECT <= ${EXPECT_OFFSET}ms"
                echo_hint "check chronyd/ntpd service, force sync date if needed"
            fi
        fi
    done
}

check_packet_loss() {
    for observer in "${observer_ip_list[@]}"
    do
        echo -e "check packet loss (localhost -> $observer): \c"
        loss_rate=$(mtr -r -c 10000 -i 0.001 -n "$observer" | grep "$observer" | awk '{print $3}')
        if [[ "$loss_rate" == "" ]]; then
            echo_fail "NOT get Loss%, maybe ICMP disabled or network unavailable ... EXPECT Loss%"
            echo_hint "check ICMP config or network availability"
            continue
        fi

        if echo "${loss_rate:0:-1}" "$EXPECT_LOSS_RATE" | awk '{if($1>$2) {exit 0} else {exit 1}}' ; then
            echo_fail "$loss_rate > $EXPECT_LOSS_RATE% ... EXPECT $EXPECT_LOSS_RATE%"
            echo_hint "check network hardware"
        else
            echo_pass "$loss_rate == $EXPECT_LOSS_RATE%"
        fi
    done
}

rc_file(){
    if is_centos7_or_uosc || is_kylin_like; then
      echo "/etc/rc.d/rc.local"
    elif is_suse; then
      echo "/etc/rc.d/after.local"
    else
      if [[ -f /etc/rc.d/rc.local ]]; then
        echo "/etc/rc.d/rc.local"
      else
        echo "/etc/rc.local"
      fi
    fi
}

rc_file=`rc_file`

check_nic_speed() {
    if [[ "$machine_role" != "obproduct" ]] && [[ "$machine_role" != "arbitrationservice" ]]; then  # OB_IP from env
        if [[ "$IP_PROTOCOL" == "IPv4" ]]; then
            dev_name=$(ip -o a | grep -w "inet" | grep -w "${OB_IP//\./\\.}" | awk '{print $2}')
        else
            dev_name=$(ip -o a | grep -w "inet6" | grep -w "$OB_IP" | awk '{print $2}')
        fi
        if [[ -z $dev_name ]]; then
            echo_fail "can not get nic name by ip $OB_IP"
            echo_hint "Please use the local ip to add the server"
        fi
        speed=$(cat /sys/class/net/"$dev_name"/speed)
        if [[ "$speed" -ge 10000 ]]; then
            echo_pass "NIC speed of $dev_name check pass"
        else
            chmod 755 $rc_file
            echo_warn "NIC speed of $dev_name check failed(speed: $speed), observer use it to config network settings"
        fi
    fi
}


check_cpu_instruction_set() {
    if [[ "$machine_role" != "obproduct" ]]; then
        if is_x86; then
#            if lscpu | grep Flags | grep -Eq "\bavx"; then
#                echo_pass "avx instruction set check on x86 architecture CPU pass"
            echo_pass "avx instruction set check on x86 architecture CPU pass"
#            else
#                echo_fail "avx instruction set check on x86 architecture CPU fail"
#                echo_hint "Installing observer requires an x86 architecture CPU that supports the avx instruction set. If the observer version to be installed is 4.2.5 BP6+ (for 4.2.x branch), 4.3.5 BP4+ (for 4.3.x branch), 4.4.1+ or later, you can ignore this avx error"
#            fi
        elif is_arm; then
            if lscpu | grep Flags | grep -Eq "\batomics"; then
                echo_pass "LSE instruction set check on ARM architecture CPU pass"
            else
                echo_fail "LSE instruction set check on ARM architecture CPU fail"
                echo_hint "Installing 3.x and 4.x versions of observer requires an ARM architecture CPU that supports the LSE instruction set. Please change a server. If you install the 2.x version of observer, you can ignore this error."
            fi
        fi
    fi
}



show_summary() {
    if [[ "$IS_CHECK_PASS" != "true" ]]; then
        if [[ -f $pre_check_summary_file ]]; then
            echo -e "\n\n### SUMMARY OF ERROR ISSUES IN PRE-CHECK ###" > /dev/stderr
            cat $pre_check_summary_file > /dev/stderr
            rm -f $pre_check_summary_file
        fi
        if [[ -f $pre_check_warning_summary_file ]]; then
            echo -e "\x01\n\n### SUMMARY OF WARN ISSUES IN PRE-CHECK ###" > /dev/stderr
            cat $pre_check_warning_summary_file > /dev/stderr
            rm -f $pre_check_warning_summary_file
        fi
    fi
}

### main ###
echo -e "Machine Role: $machine_role "
echo -e "Peer IP List: ${observer_ip_list[*]}"

echo

check_resource
check_folder
check_user
check_clock_sync
check_sysctl
check_service
check_firewalld
check_ssh
check_transparent_hugepage
check_limit_conf
check_limit
check_numa
check_smmu
check_other_grub
check_elevator
check_tsc_timer
check_sector_size

check_cpufreq_governor
check_rpms
check_command  # ocp install obproxy need nc
check_irq_affinity
check_filesystem_type
check_taskset
check_clock_diff
check_nic_speed
check_packet_loss
check_cpu_instruction_set
show_summary

if [ $IS_CHECK_PASS == "true" ]; then
    exit 0
else
    exit 1
fi
相关推荐
云贝贝贝5 天前
OceanBase认证体系介绍与备考指南
运维·服务器·oceanbase·1024程序员节
OceanBase数据库官方博客5 天前
让 DRP全域数据智能流转OceanBase AI 数据库支撑央国企落地穿透式监
数据库·人工智能·oceanbase
云贝教育-郑老师6 天前
揭开极速引擎的面纱,OceanBase 单分区事务 (局部事务) 的“一阶段”生死狂飙
学习·oceanbase
marvelyu6 天前
每天10分钟学会OceanBase系列(Day 19):数据库备份与恢复实战——给数据上”保险”
数据库·oracle·oceanbase
颜挺锐6 天前
如何提取ob数据库中30个分区下不同分区的数据,简单实操
数据库·oceanbase
云贝教育-郑老师8 天前
OceanBase 是如何搞定海量数据分片(Sharding)的?
学习·oceanbase·dba
OceanBase数据库官方博客11 天前
OceanBase DataPilot AIP:Ontology 承载AI能力面的另一条路
人工智能·oceanbase
spencer_tseng13 天前
oceanbase-4.3.5.5-105020022025121200.el7.x86_64.rpm
linux·oceanbase·kylin
OceanBase数据库官方博客1 个月前
OceanBase DataStudio:让 AI数据生产从拼装走向一体化(技术解析与
人工智能·oceanbase