#!/bin/bash
# 一键检查双路服务器两颗 CPU 步进(Stepping)是否一致
# 适用: x86 Linux (RHEL/CentOS/Ubuntu/Debian 等), 仅依赖 bash/awk, 无需 root
# 用法: bash check_cpu_stepping.sh

export LC_ALL=C

# ---------- 获取主 IP ----------
get_main_ip() {
    local ip=""
    # 1. 走默认路由的源地址
    if command -v ip >/dev/null 2>&1; then
        ip=$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="src"){print $(i+1); exit}}')
    fi
    # 2. hostname -I 第一个地址
    if [ -z "$ip" ] && command -v hostname >/dev/null 2>&1; then
        ip=$(hostname -I 2>/dev/null | awk '{print $1}')
    fi
    # 3. ip addr 第一个非 lo 的 IPv4
    if [ -z "$ip" ] && command -v ip >/dev/null 2>&1; then
        ip=$(ip -4 -o addr show scope global 2>/dev/null | awk '{split($4,a,"/"); print a[1]; exit}')
    fi
    # 4. ifconfig
    if [ -z "$ip" ] && command -v ifconfig >/dev/null 2>&1; then
        ip=$(ifconfig 2>/dev/null | awk '/inet /&&$2!="127.0.0.1"{sub("addr:","",$2); print $2; exit}')
    fi
    echo "${ip:-未知}"
}

# ---------- 按物理 CPU(socket)读取步进 ----------
# 输出格式: "<physical_id> <stepping>" 每颗 CPU 一行
get_stepping_per_socket() {
    awk '
    BEGIN { RS=""; FS="\n" }
    {
        pid=""; st=""
        for (i=1; i<=NF; i++) {
            if ($i ~ /^physical id/) { split($i, a, ":"); gsub(/[ \t]/, "", a[2]); pid=a[2] }
            if ($i ~ /^stepping/)    { split($i, b, ":"); gsub(/[ \t]/, "", b[2]); st=b[2] }
        }
        if (st != "") {
            if (pid == "") pid = "0"
            if (!(pid in seen)) { seen[pid]=st; order[++n]=pid }
            else if (index("," seen[pid] ",", "," st ",") == 0) seen[pid]=seen[pid] "/" st
        }
    }
    END { for (i=1; i<=n; i++) print order[i], seen[order[i]] }
    ' /proc/cpuinfo 2>/dev/null | sort -n
}

MAIN_IP=$(get_main_ip)
DATA=$(get_stepping_per_socket)

if [ -z "$DATA" ]; then
    echo "错误: 无法从 /proc/cpuinfo 读取 CPU 步进信息(可能不是 x86 Linux)。"
    exit 1
fi

# 读入数组
STEPS=()
while read -r pid st; do
    STEPS+=("$st")
done <<< "$DATA"

COUNT=${#STEPS[@]}

echo "----------------------------------------"
echo "CPU 型号: $(awk -F: '/model name/{gsub(/^[ \t]+/,"",$2); print $2; exit}' /proc/cpuinfo)"
echo "物理 CPU 数量: $COUNT"
echo "----------------------------------------"

if [ "$COUNT" -eq 2 ]; then
    S1="${STEPS[0]}"
    S2="${STEPS[1]}"
    if [ "$S1" = "$S2" ]; then
        echo "该服务器 主ip:${MAIN_IP},两颗cpu情况,第一颗步进:${S1} 第二颗步进:${S2}"
        echo "两颗cpu步进一致,无需调整。"
    else
        echo "该服务器 主ip:${MAIN_IP},两颗cpu情况,第一颗步进:${S1} 第二颗步进:${S2}"
        echo "步进不一,请标记故障,填写:第一颗步进:${S1} 第二颗步进:${S2}   两颗cpu需要调整为步进一致。"
    fi
elif [ "$COUNT" -eq 1 ]; then
    echo "该服务器 主ip:${MAIN_IP},仅检测到 1 颗物理CPU,步进:${STEPS[0]}(单路服务器或虚拟机,无需比对)"
else
    # 3 颗及以上(四路/八路)
    MSG="该服务器 主ip:${MAIN_IP},检测到 ${COUNT} 颗CPU:"
    UNIQ=$(printf '%s\n' "${STEPS[@]}" | sort -u | wc -l)
    for i in "${!STEPS[@]}"; do
        MSG="${MSG} 第$((i+1))颗步进:${STEPS[$i]}"
    done
    echo "$MSG"
    if [ "$UNIQ" -eq 1 ]; then
        echo "所有cpu步进一致,无需调整。"
    else
        echo "步进不一,请标记故障,所有cpu需要调整为步进一致。"
    fi
fi
