服务器身份之谜:一键脚本,看清物理机与虚拟机的真面目

Thumbnail image

缘起:一个让运维人员夜不能寐的问题

"这到底是不是虚拟机?"

这个问题看似简单,却困扰着无数运维工程师、系统管理员和开发人员。记得那是一个周五的深夜,我们正在为某个关键业务系统进行性能调优。监控显示某台数据库服务器响应异常,我本能地开始检查硬件状态——内存频率、磁盘队列、CPU缓存……

直到三个小时后,一位同事偶然发现:这特么根本就是一台虚拟机!我们一直在用排查物理机的方法去诊断虚拟机的问题,就像用修汽车的工具去修飞机一样荒谬。

那一刻我意识到,必须有一个可靠的方法来快速、准确地识别服务器环境。这就是我开发这个检测脚本的初衷。

现实困境:为什么环境识别如此重要却如此困难?

性能调优的迷思
物理机和虚拟机的性能特征天差地别。物理机的瓶颈可能在硬件本身,而虚拟机的性能问题往往源于资源分配或虚拟化层。用错了调优方法,就像给鱼开车——再努力也是白费劲。

成本核算的困惑
企业IT成本核算时,物理机的折旧与虚拟机的资源计费完全不同的。错误的环境识别可能导致成本分配不公,甚至引发部门间的矛盾。

安全合规的隐患
某些安全策略对物理机和虚拟机有不同的要求。错误的环境判断可能导致安全配置不当,给系统留下致命漏洞。

故障排查的误区
我曾亲眼见过团队花了两天时间排查"物理网卡故障",最后发现是虚拟机的网络驱动问题。这种时间浪费在紧急故障处理时是致命的。

破局之道:从人工猜测到自动化检测

传统方法的局限性

过去,我们依赖零散的命令来猜测服务器身份:

dmidecode -s system-manufacturer
lscpu | grep Hypervisor
dmesg | grep -i virtual

这种方法就像盲人摸象,每个命令只能看到真相的一个侧面,而且容易漏掉关键证据。

我们的解决方案:多维度证据链分析
受税务检查中"证据链"概念的启发,我在AI的协助下,开发了基于多维度交叉验证的检测方法。核心思想是:单一证据可能误导,但多个独立证据形成的证据链很难伪造。

硬件证据层

系统固件信息:如同服务器的"身份证"

CPU特征指纹:物理CPU与虚拟CPU的微妙差异

内存分布模式:物理内存条与虚拟内存的分配特征

软件证据层

设备驱动特征:virtio、vmxnet等虚拟化驱动的存在

系统服务痕迹:VMware Tools、Cloud-Init等服务进程

内核模块指纹:特定的虚拟化内核模块

网络证据层

MAC地址归属:各虚拟化平台的专属地址段

网络接口特征:驱动类型和命名规则

云元数据服务:访问云厂商的内部元数据端点

性能证据层

磁盘I/O模式:物理磁盘与虚拟存储的性能特征

CPU调度特征:物理核心与虚拟CPU的调度差异

时钟源行为:不同时钟源在虚拟化环境下的表现

实战检验:脚本的精彩破案时刻

案例1:神秘的"物理服务器"
某服务公司一直将一台数据库服务器当作物理机管理,直到性能监控显示异常。我们的脚本在30秒内给出结论:这是一台VMware虚拟机!原来当初的运维文档记录有误,导致后续的性能调优全部走错了方向。

案例2:云中的"伪装者"
一家电商企业的日志服务器表现异常,团队以为是硬件故障。脚本检测发现这是阿里云ECS实例,结合云监控发现是磁盘IOPS配额用尽。问题在5分钟内定位,避免了不必要的工单和等待。

案例3:容器里的"套娃"
开发团队报告测试环境性能问题,脚本立即警告:"当前运行在Docker容器中"。这才发现容器嵌套导致资源竞争,根本不是硬件问题。

如何使用这个侦探工具如何使用这个侦探工具

1、创建脚本文件

# 使用你喜欢的编辑器创建文件
cd /usr/local/bin/
vi server_detective.sh
# 或者
nano server_detective.sh

2、将完整的检测脚本代码粘贴到文件中

#!/bin/bash

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# 检测结果存储
VIRTUAL_INDICATORS=()
PHYSICAL_INDICATORS=()
INCONCLUSIVE_INDICATORS=()

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_debug() {
    echo -e "${PURPLE}[DEBUG]${NC} $1"
}

# 检查命令是否存在
check_command() {
    if command -v "$1" &> /dev/null; then
        return 0
    else
        return 1
    fi
}

# 检查 root 权限
check_root() {
    if [[ $EUID -eq 0 ]]; then
        return 0
    else
        return 1
    fi
}

# 显示权限警告
show_permission_warning() {
    if ! check_root; then
        log_warning "当前未使用root权限运行,部分检测可能无法执行"
        log_warning "建议使用: sudo $0"
        echo
    fi
}

# 1. 检查系统制造商和产品名称
check_system_manufacturer() {
    if check_command dmidecode; then
        log_info "检查系统制造商信息..."

        if check_root; then
            local sys_man=$(dmidecode -s system-manufacturer 2>/dev/null | head -1)
            local sys_prod=$(dmidecode -s system-product-name 2>/dev/null | head -1)
        else
            local sys_man=$(sudo dmidecode -s system-manufacturer 2>/dev/null | head -1)
            local sys_prod=$(sudo dmidecode -s system-product-name 2>/dev/null | head -1)
        fi

        if [[ -n "$sys_man" ]]; then
            echo "   制造商: $sys_man"
            echo "   产品: $sys_prod"

            # 虚拟化厂商检测
            if echo "$sys_man" | grep -qiE "vmware|microsoft|innotek|red hat|qemu|parallels|xen|kvm|amazon|google|alibaba|tencent|huawei|jd"; then
                VIRTUAL_INDICATORS+=("系统制造商: $sys_man")
            elif echo "$sys_man" | grep -qiE "dell|hp|ibm|supermicro|lenovo|cisco|fujitsu"; then
                PHYSICAL_INDICATORS+=("系统制造商: $sys_man")
            else
                INCONCLUSIVE_INDICATORS+=("系统制造商: $sys_man")
            fi
        else
            log_warning "无法获取系统制造商信息"
        fi
    else
        log_warning "dmidecode 命令不可用,跳过系统制造商检查"
        log_warning "可以安装: sudo apt-get install dmidecode"
    fi
}

# 2. 检查 BIOS 信息
check_bios_info() {
    if check_command dmidecode; then
        log_info "检查 BIOS 信息..."

        if check_root; then
            local bios_vendor=$(dmidecode -s bios-vendor 2>/dev/null | head -1)
            local bios_version=$(dmidecode -s bios-version 2>/dev/null | head -1)
        else
            local bios_vendor=$(sudo dmidecode -s bios-vendor 2>/dev/null | head -1)
            local bios_version=$(sudo dmidecode -s bios-version 2>/dev/null | head -1)
        fi

        if [[ -n "$bios_vendor" ]]; then
            echo "   BIOS厂商: $bios_vendor"
            echo "   BIOS版本: $bios_version"

            if echo "$bios_vendor" | grep -qiE "vmware|innotek|virtualbox|qemu|bochs|sea bios|american megatrends"; then
                VIRTUAL_INDICATORS+=("BIOS厂商: $bios_vendor")
            elif echo "$bios_vendor" | grep -qiE "dell|hp|ibm|insyde|phoenix"; then
                PHYSICAL_INDICATORS+=("BIOS厂商: $bios_vendor")
            fi
        fi
    fi
}

# 3. 检查 CPU 信息
check_cpu_info() {
    log_info "检查 CPU 信息..."

    # 检查 /proc/cpuinfo
    if [[ -f "/proc/cpuinfo" ]]; then
        local cpu_hypervisor=$(grep -i "hypervisor" /proc/cpuinfo | head -1)
        local cpu_vendor=$(grep -i "vendor" /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)

        echo "   CPU厂商: $cpu_vendor"

        if [[ -n "$cpu_hypervisor" ]]; then
            VIRTUAL_INDICATORS+=("CPU包含hypervisor标志")
            echo "   ⚠️ 检测到hypervisor标志"
        fi

        # 检查CPU型号特征
        if echo "$cpu_vendor" | grep -qi "GenuineIntel\|AuthenticAMD"; then
            if [[ ${#VIRTUAL_INDICATORS[@]} -eq 0 ]]; then
                PHYSICAL_INDICATORS+=("CPU厂商为物理硬件厂商")
            fi
        fi
    fi

    # 使用 lscpu 如果可用
    if check_command lscpu; then
        echo "   CPU架构信息:"
        lscpu | grep -E "(Architecture|CPU\(s\)|Thread|Core|Socket)" | sed 's/^/     /'
    else
        log_warning "lscpu 命令不可用"
    fi
}

# 4. 检查磁盘信息
check_disk_info() {
    log_info "检查磁盘信息..."

    # 使用 lsblk 检查磁盘模型
    if check_command lsblk; then
        local disk_info=$(lsblk -d -o NAME,MODEL,SIZE,TYPE 2>/dev/null | grep -v "NAME" | head -5)
        if [[ -n "$disk_info" ]]; then
            echo "   磁盘信息:"
            echo "$disk_info" | sed 's/^/     /'

            if echo "$disk_info" | grep -qiE "virtual|vhd|vdi|vmware|qemu|amazon|google|alibaba|tencent"; then
                VIRTUAL_INDICATORS+=("虚拟磁盘类型")
            elif echo "$disk_info" | grep -qiE "samsung|western digital|seagate|toshiba|hitachi"; then
                PHYSICAL_INDICATORS+=("物理磁盘型号")
            fi
        fi
    else
        log_warning "lsblk 命令不可用"
    fi

    # 检查 /sys/block 中的设备
    if [[ -d "/sys/block" ]]; then
        for device in /sys/block/sd* /sys/block/vd* /sys/block/xvd* /sys/block/nvme*; do
            if [[ -e "$device" ]]; then
                local device_name=$(basename "$device")
                if [[ "$device_name" == vd* ]] || [[ "$device_name" == xvd* ]]; then
                    VIRTUAL_INDICATORS+=("虚拟块设备: $device_name")
                elif [[ "$device_name" == sd* ]] || [[ "$device_name" == nvme* ]]; then
                    PHYSICAL_INDICATORS+=("物理块设备: $device_name")
                fi
            fi
        done
    fi

    # 使用 fdisk 作为备选
    if check_command fdisk; then
        echo "   磁盘列表:"
        fdisk -l 2>/dev/null | grep -E "^Disk /dev/" | head -3 | sed 's/^/     /'
    fi
}

# 5. 检查设备驱动
check_device_drivers() {
    log_info "检查设备驱动..."

    # 使用 lspci 检查设备
    if check_command lspci; then
        local virt_devices
        if check_root; then
            virt_devices=$(lspci 2>/dev/null | grep -iE "virtio|vmware|virtualbox|qemu|xen|red hat|amazon|alibaba")
        else
            virt_devices=$(sudo lspci 2>/dev/null | grep -iE "virtio|vmware|virtualbox|qemu|xen|red hat|amazon|alibaba")
        fi

        if [[ -n "$virt_devices" ]]; then
            echo "   虚拟化设备:"
            echo "$virt_devices" | sed 's/^/     /'
            VIRTUAL_INDICATORS+=("发现虚拟化PCI设备")
        fi

        # 检查物理设备
        local phys_devices
        if check_root; then
            phys_devices=$(lspci 2>/dev/null | grep -iE "broadcom|intel|realtek|marvell|qlogic" | head -5)
        else
            phys_devices=$(sudo lspci 2>/dev/null | grep -iE "broadcom|intel|realtek|marvell|qlogic" | head -5)
        fi

        if [[ -n "$phys_devices" ]]; then
            echo "   物理设备:"
            echo "$phys_devices" | sed 's/^/     /'
            PHYSICAL_INDICATORS+=("发现物理PCI设备")
        fi
    else
        log_warning "lspci 命令不可用,跳过PCI设备检查"
        log_warning "可以安装: sudo apt-get install pciutils"
    fi

    # 检查内核模块
    if check_command lsmod; then
        local virt_modules
        if check_root; then
            virt_modules=$(lsmod | grep -iE "virtio|vmw|vbox|qemu|xen|hv_")
        else
            virt_modules=$(sudo lsmod 2>/dev/null | grep -iE "virtio|vmw|vbox|qemu|xen|hv_")
        fi

        if [[ -n "$virt_modules" ]]; then
            echo "   虚拟化内核模块:"
            echo "$virt_modules" | sed 's/^/     /'
            VIRTUAL_INDICATORS+=("加载虚拟化内核模块")
        fi
    fi
}

# 6. 检查系统进程和服务
check_system_services() {
    log_info "检查系统进程和服务..."

    # 检查虚拟化相关进程
    local virt_processes=$(ps aux 2>/dev/null | grep -E "(vmtoolsd|qemu-ga|virtio|vboxadd|hyperv|aws|aliyun|tencent|jdcloud)" | grep -v grep)
    if [[ -n "$virt_processes" ]]; then
        echo "   虚拟化相关进程:"
        echo "$virt_processes" | sed 's/^/     /'
        VIRTUAL_INDICATORS+=("运行虚拟化相关进程")
    fi

    # 检查系统服务
    if check_command systemctl; then
        local virt_services=$(systemctl list-units 2>/dev/null | grep -iE "virtual|vmware|vbox|qemu|hyperv|aws|google|aliyun|tencent|jdcloud|huawei" | head -10)
        if [[ -n "$virt_services" ]]; then
            echo "   虚拟化相关服务:"
            echo "$virt_services" | sed 's/^/     /'
            VIRTUAL_INDICATORS+=("运行虚拟化相关服务")
        fi
    else
        # 对于使用 SysV init 的系统
        if [[ -d "/etc/init.d" ]]; then
            local init_services=$(ls /etc/init.d/ | grep -iE "vmware|vbox|aliyun|tencent" | head -5)
            if [[ -n "$init_services" ]]; then
                echo "   虚拟化相关服务 (init.d):"
                echo "$init_services" | sed 's/^/     /'
                VIRTUAL_INDICATORS+=("运行虚拟化相关服务")
            fi
        fi
    fi
}

# 7. 检查网络接口
check_network_interfaces() {
    log_info "检查网络接口..."

    if check_command ip; then
        local mac_addresses=$(ip addr show 2>/dev/null | grep -oE "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}" | tr '[:lower:]' '[:upper:]' | sort -u)

        if [[ -n "$mac_addresses" ]]; then
            echo "   MAC地址:"
            for mac in $mac_addresses; do
                echo "     $mac"

                # 检查MAC地址前三位
                local prefix=$(echo "$mac" | cut -d: -f1-3)
                case $prefix in
                    "00:0C:29"|"00:50:56") 
                        VIRTUAL_INDICATORS+=("VMware MAC地址: $mac")
                        ;;
                    "08:00:27") 
                        VIRTUAL_INDICATORS+=("VirtualBox MAC地址: $mac")
                        ;;
                    "00:15:5D") 
                        VIRTUAL_INDICATORS+=("Hyper-V MAC地址: $mac")
                        ;;
                    "00:16:3E") 
                        VIRTUAL_INDICATORS+=("Xen MAC地址: $mac")
                        ;;
                    "00:1C:42"|"00:03:FF") 
                        VIRTUAL_INDICATORS+=("Parallels MAC地址: $mac")
                        ;;
                    "52:54:00") 
                        VIRTUAL_INDICATORS+=("QEMU/KVM MAC地址: $mac")
                        ;;
                    "0A:00:27") 
                        VIRTUAL_INDICATORS+=("VirtualBox NAT MAC地址: $mac")
                        ;;
                    "02:42:AC"|"02:42:AD")
                        VIRTUAL_INDICATORS+=("Docker容器MAC地址: $mac")
                        ;;
                    "06:00:*"|"06:05:*"|"06:0A:*")
                        INCONCLUSIVE_INDICATORS+=("可能的云环境MAC地址: $mac")
                        ;;
                    "00:16:3E")
                        VIRTUAL_INDICATORS+=("阿里云MAC地址: $mac")
                        ;;
                esac
            done
        fi

        # 检查网络接口名称
        local interfaces=$(ip addr show 2>/dev/null | grep -E "^[0-9]+:" | awk '{print $2}' | tr -d ':')
        if [[ -n "$interfaces" ]]; then
            echo "   网络接口: $interfaces"
            # 检查虚拟网络接口
            if echo "$interfaces" | grep -qE "veth|docker|br-"; then
                VIRTUAL_INDICATORS+=("虚拟网络接口")
            fi
        fi
    else
        log_warning "ip 命令不可用"
        # 尝试使用 ifconfig
        if check_command ifconfig; then
            local mac_addresses=$(ifconfig 2>/dev/null | grep -oE "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}" | tr '[:lower:]' '[:upper:]' | sort -u)
            if [[ -n "$mac_addresses" ]]; then
                echo "   MAC地址:"
                for mac in $mac_addresses; do
                    echo "     $mac"
                done
            fi
        fi
    fi
}

# 8. 检查 dmesg 输出
check_dmesg() {
    log_info "检查内核消息..."

    if check_command dmesg; then
        local dmesg_virt
        if check_root; then
            dmesg_virt=$(dmesg 2>/dev/null | grep -iE "virtual|hypervisor|vmware|vbox|qemu|xen|hyper-v|cloud" | head -5)
        else
            dmesg_virt=$(sudo dmesg 2>/dev/null | grep -iE "virtual|hypervisor|vmware|vbox|qemu|xen|hyper-v|cloud" | head -5)
        fi

        if [[ -n "$dmesg_virt" ]]; then
            echo "   虚拟化相关内核消息:"
            echo "$dmesg_virt" | sed 's/^/     /'
            VIRTUAL_INDICATORS+=("内核消息包含虚拟化痕迹")
        fi

        # 检查物理硬件相关消息
        local dmesg_phys
        if check_root; then
            dmesg_phys=$(dmesg 2>/dev/null | grep -iE "memory:|cpu:|acpi:" | head -3)
        else
            dmesg_phys=$(sudo dmesg 2>/dev/null | grep -iE "memory:|cpu:|acpi:" | head -3)
        fi

        if [[ -n "$dmesg_phys" ]]; then
            echo "   硬件相关内核消息:"
            echo "$dmesg_phys" | sed 's/^/     /'
        fi
    fi
}

# 9. 检查容器环境(排除容器干扰)
check_container() {
    log_info "检查容器环境..."

    local container_detected=false

    # 检查常见的容器标识
    if [[ -f "/.dockerenv" ]]; then
        log_warning "当前运行在Docker容器中,检测结果可能不准确"
        container_detected=true
    fi

    if [[ -f "/run/.containerenv" ]]; then
        log_warning "当前运行在容器环境中,检测结果可能不准确"
        container_detected=true
    fi

    if grep -q "docker" /proc/1/cgroup 2>/dev/null; then
        log_warning "当前运行在Docker容器中,检测结果可能不准确"
        container_detected=true
    fi

    if grep -q "kubepods" /proc/1/cgroup 2>/dev/null; then
        log_warning "当前运行在Kubernetes Pod中,检测结果可能不准确"
        container_detected=true
    fi

    # 检查 PID 1 的进程名
    local pid1_process=$(ps -p 1 -o comm= 2>/dev/null)
    if [[ "$pid1_process" != "systemd" && "$pid1_process" != "init" && "$pid1_process" != "bash" && "$pid1_process" != "sh" ]]; then
        log_warning "PID 1 进程为 $pid1_process,可能运行在容器中"
        container_detected=true
    fi

    # 检查根文件系统类型
    local root_fs=$(stat -f -c %T / 2>/dev/null)
    if [[ "$root_fs" == "overlayfs" || "$root_fs" == "aufs" ]]; then
        log_warning "根文件系统为 $root_fs,可能运行在容器中"
        container_detected=true
    fi

    if [[ "$container_detected" == true ]]; then
        INCONCLUSIVE_INDICATORS+=("运行在容器环境中")
        return 1
    fi

    echo "   未检测到容器环境"
    return 0
}

# 10. 性能简单测试(可选)
check_performance() {
    log_info "执行简单性能测试..."

    # 检查是否有写入权限
    if [[ -w "/tmp" ]]; then
        # 磁盘写入测试
        local test_file="/tmp/vm_test_$$"
        local start_time=$(date +%s%N)

        # 使用 dd 进行测试,但处理可能的错误
        if dd if=/dev/zero of="$test_file" bs=1M count=16 oflag=dsync status=none 2>/dev/null; then
            local end_time=$(date +%s%N)
            local duration=$(( (end_time - start_time) / 1000000 ))

            echo "   16MB磁盘写入测试: ${duration}ms"

            # 简单性能判断
            if [[ $duration -gt 2000 ]]; then
                INCONCLUSIVE_INDICATORS+=("磁盘写入性能较慢: ${duration}ms")
            elif [[ $duration -lt 200 ]]; then
                PHYSICAL_INDICATORS+=("磁盘写入性能优秀: ${duration}ms")
            else
                INCONCLUSIVE_INDICATORS+=("磁盘写入性能一般: ${duration}ms")
            fi

            # 清理测试文件
            rm -f "$test_file"
        else
            log_warning "磁盘写入测试失败"
        fi

        # CPU性能简单测试
        start_time=$(date +%s%N)
        local count=0
        for i in {1..1000}; do
            count=$((count + i))
        done
        end_time=$(date +%s%N)
        local cpu_duration=$(( (end_time - start_time) / 1000000 ))

        echo "   CPU简单计算测试: ${cpu_duration}ms"

    else
        log_warning "没有/tmp目录写入权限,跳过性能测试"
    fi
}

# 11. 检查系统特定文件
check_system_files() {
    log_info "检查系统特定文件..."

    # 检查 /proc/scsi 目录
    if [[ -d "/proc/scsi" ]]; then
        local scsi_drivers=$(ls /proc/scsi/ 2>/dev/null)
        if echo "$scsi_drivers" | grep -qi "vmware"; then
            VIRTUAL_INDICATORS+=("VMware SCSI驱动")
        fi
    fi

    # 检查 /sys/class/dmi/id 目录
    if [[ -d "/sys/class/dmi/id" ]]; then
        if [[ -f "/sys/class/dmi/id/product_name" ]]; then
            local product_name=$(cat /sys/class/dmi/id/product_name 2>/dev/null)
            if [[ -n "$product_name" ]]; then
                echo "   产品名称: $product_name"
                if echo "$product_name" | grep -qiE "vmware|virtual|qemu|amazon|google|alibaba|tencent|jdcloud|huawei"; then
                    VIRTUAL_INDICATORS+=("DMI产品名称: $product_name")
                elif echo "$product_name" | grep -qiE "poweredge|proliant|system x|ucs"; then
                    PHYSICAL_INDICATORS+=("DMI产品名称: $product_name")
                fi
            fi
        fi

        if [[ -f "/sys/class/dmi/id/sys_vendor" ]]; then
            local sys_vendor=$(cat /sys/class/dmi/id/sys_vendor 2>/dev/null)
            if [[ -n "$sys_vendor" ]]; then
                echo "   系统供应商: $sys_vendor"
                if echo "$sys_vendor" | grep -qiE "vmware|innotek|microsoft|amazon|google|alibaba|tencent|jdcloud|huawei"; then
                    VIRTUAL_INDICATORS+=("DMI系统供应商: $sys_vendor")
                elif echo "$sys_vendor" | grep -qiE "dell|hp|ibm|lenovo|cisco"; then
                    PHYSICAL_INDICATORS+=("DMI系统供应商: $sys_vendor")
                fi
            fi
        fi

        if [[ -f "/sys/class/dmi/id/board_vendor" ]]; then
            local board_vendor=$(cat /sys/class/dmi/id/board_vendor 2>/dev/null)
            if [[ -n "$board_vendor" ]]; then
                echo "   主板供应商: $board_vendor"
            fi
        fi
    fi

    # 检查 /proc/device-tree (ARM架构)
    if [[ -d "/proc/device-tree" ]]; then
        echo "   检测到设备树(可能是ARM架构)"
        PHYSICAL_INDICATORS+=("使用设备树(通常为物理ARM设备)")
    fi
}

# 12. 检查特定的虚拟化技术特征
check_virt_specific() {
    log_info "检查虚拟化技术特定特征..."

    local virt_detected=false

    # 检查 VMware 特定特征
    if [[ -f /usr/bin/vmware-toolbox-cmd ]]; then
        VIRTUAL_INDICATORS+=("检测到VMware Tools")
        echo "   ✅ 发现VMware Tools"
        virt_detected=true
    fi

    if [[ -d /proc/vmware ]]; then
        VIRTUAL_INDICATORS+=("VMware专用proc目录")
        echo "   ✅ 发现/proc/vmware目录"
        virt_detected=true
    fi

    # 检查 VirtualBox 特定特征
    if [[ -f /usr/bin/VBoxService ]]; then
        VIRTUAL_INDICATORS+=("检测到VirtualBox Guest Additions")
        echo "   ✅ 发现VirtualBox Guest Additions"
        virt_detected=true
    fi

    # 检查 Hyper-V 特定特征
    if [[ -d /sys/bus/vmbus ]]; then
        VIRTUAL_INDICATORS+=("Hyper-V VMBus设备")
        echo "   ✅ 发现Hyper-V VMBus"
        virt_detected=true
    fi

    if lsmod | grep -q hv_; then
        VIRTUAL_INDICATORS+=("Hyper-V内核模块")
        echo "   ✅ 发现Hyper-V内核模块"
        virt_detected=true
    fi

    # 检查 KVM 特定特征
    if [[ -r /dev/kvm ]]; then
        echo "   ✅ 发现KVM设备 (/dev/kvm)"
        if check_command dmesg; then
            local kvm_dmesg
            if check_root; then
                kvm_dmesg=$(dmesg | grep -i "kvm" | head -3)
            else
                kvm_dmesg=$(sudo dmesg 2>/dev/null | grep -i "kvm" | head -3)
            fi

            if [[ -n "$kvm_dmesg" ]]; then
                VIRTUAL_INDICATORS+=("KVM虚拟化支持")
                echo "   ✅ 发现KVM相关日志"
                virt_detected=true
            fi
        fi
    fi

    # 检查 Xen 特定特征
    if [[ -d /proc/xen ]]; then
        VIRTUAL_INDICATORS+=("Xen虚拟化环境")
        echo "   ✅ 发现/proc/xen目录"
        virt_detected=true
    fi

    if lsmod | grep -q xen; then
        VIRTUAL_INDICATORS+=("Xen内核模块")
        echo "   ✅ 发现Xen内核模块"
        virt_detected=true
    fi

    # 检查云厂商特定文件
    if [[ -f /etc/aliyun-release ]]; then
        VIRTUAL_INDICATORS+=("阿里云环境")
        echo "   ✅ 发现阿里云标识文件"
        virt_detected=true
    fi

    if [[ -f /etc/tlinux-release ]]; then
        VIRTUAL_INDICATORS+=("腾讯云环境")
        echo "   ✅ 发现腾讯云标识文件"
        virt_detected=true
    fi

    if [[ "$virt_detected" == false ]]; then
        echo "   未发现特定虚拟化技术特征"
    fi
}

# 13. 检查时钟源,虚拟机和物理机通常使用不同的时钟源
check_clocksource() {
    log_info "检查系统时钟源..."

    if [[ -f /sys/devices/system/clocksource/clocksource0/current_clocksource ]]; then
        local clocksource=$(cat /sys/devices/system/clocksource/clocksource0/current_clocksource 2>/dev/null)
        if [[ -n "$clocksource" ]]; then
            echo "   当前时钟源: $clocksource"

            # 虚拟化环境常见的时钟源
            if echo "$clocksource" | grep -qiE "kvm-clock|hyperv|acpi_pm"; then
                VIRTUAL_INDICATORS+=("虚拟化时钟源: $clocksource")
            elif echo "$clocksource" | grep -qiE "tsc|hpet"; then
                PHYSICAL_INDICATORS+=("物理机时钟源: $clocksource")
            else
                INCONCLUSIVE_INDICATORS+=("未知时钟源: $clocksource")
            fi
        else
            log_warning "无法获取当前时钟源信息"
        fi
    else
        log_warning "无法访问时钟源信息文件"
    fi

    # 检查可用时钟源
    if [[ -f /sys/devices/system/clocksource/clocksource0/available_clocksource ]]; then
        local available_clocksources=$(cat /sys/devices/system/clocksource/clocksource0/available_clocksource 2>/dev/null)
        if [[ -n "$available_clocksources" ]]; then
            echo "   可用时钟源: $available_clocksources"
        fi
    fi
}

# 14. 检查内存信息,虚拟机和物理机在内存分配上有差异
check_memory_info() {
    log_info "检查内存信息..."

    # 检查内存总量和分布
    if [[ -f /proc/meminfo ]]; then
        local mem_total=$(grep -i "memtotal" /proc/meminfo | awk '{print $2}')
        local mem_available=$(grep -i "memavailable" /proc/meminfo | awk '{print $2}')

        if [[ -n "$mem_total" ]]; then
            local mem_total_mb=$((mem_total / 1024))
            local mem_total_gb=$((mem_total_mb / 1024))
            echo "   内存总量: ${mem_total_mb} MB (${mem_total_gb} GB)"

            # 检查内存是否为2的幂次方(物理机常见)
            if (( (mem_total & (mem_total - 1)) == 0 )); then
                PHYSICAL_INDICATORS+=("内存总量为2的幂次方(物理机特征)")
            else
                INCONCLUSIVE_INDICATORS+=("内存总量非2的幂次方")
            fi

            # 检查内存总量是否常见(如 1024, 2048, 4096, 8192 MB)
            if [[ $mem_total_mb -eq 1024 ]] || [[ $mem_total_mb -eq 2048 ]] || [[ $mem_total_mb -eq 4096 ]] || [[ $mem_total_mb -eq 8192 ]] || [[ $mem_total_mb -eq 16384 ]]; then
                echo "   内存配置为常见虚拟化规格"
            fi
        fi

        if [[ -n "$mem_available" ]]; then
            local mem_available_mb=$((mem_available / 1024))
            echo "   可用内存: ${mem_available_mb} MB"
        fi
    fi

    # 检查内存插槽信息(需要dmidecode)
    if check_command dmidecode; then
        log_info "检查内存插槽信息..."
        local memory_slots
        if check_root; then
            memory_slots=$(dmidecode -t memory 2>/dev/null | grep -c "Size:" | grep -v "No Module")
        else
            memory_slots=$(sudo dmidecode -t memory 2>/dev/null | grep -c "Size:" | grep -v "No Module")
        fi

        if [[ "$memory_slots" -gt 0 ]]; then
            echo "   检测到 $memory_slots 个内存插槽有模块"
            if [[ "$memory_slots" -ge 2 ]]; then
                PHYSICAL_INDICATORS+=("多内存插槽(物理机特征)")
            fi
        else
            echo "   无法获取内存插槽信息或没有检测到内存模块"
        fi
    fi
}

# 15. 检查CPU高级特征
check_advanced_cpu() {
    log_info "检查CPU高级特征..."

    if [[ -f /proc/cpuinfo ]]; then
        # 检查CPU核心数
        local core_count=$(grep -c "^processor" /proc/cpuinfo)
        echo "   CPU逻辑核心数: $core_count"

        # 检查物理核心数
        local physical_cores=$(grep "core id" /proc/cpuinfo | sort -u | wc -l)
        if [[ "$physical_cores" -gt 0 ]]; then
            echo "   CPU物理核心数: $physical_cores"

            # 如果逻辑核心数远大于物理核心数,可能是虚拟机
            if [[ $core_count -gt $((physical_cores * 2)) ]]; then
                INCONCLUSIVE_INDICATORS+=("逻辑核心数远超物理核心数(超线程或虚拟CPU)")
            elif [[ $core_count -eq $physical_cores ]]; then
                PHYSICAL_INDICATORS+=("逻辑与物理核心数一致")
            fi
        fi

        # 检查CPU频率缩放驱动(虚拟机和物理机不同)
        if [[ -d /sys/devices/system/cpu/cpu0/cpufreq ]]; then
            local scaling_driver=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver 2>/dev/null)
            if [[ -n "$scaling_driver" ]]; then
                echo "   CPU频率缩放驱动: $scaling_driver"
                if [[ "$scaling_driver" == "acpi-cpufreq" ]]; then
                    PHYSICAL_INDICATORS+=("使用ACPI CPU频率调节")
                elif [[ "$scaling_driver" == "intel_pstate" ]]; then
                    PHYSICAL_INDICATORS+=("使用Intel P-State驱动")
                fi
            fi
        fi

        # 检查CPU漏洞缓解状态
        local cpu_bugs=$(grep "bugs" /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)
        if [[ -n "$cpu_bugs" ]]; then
            echo "   CPU漏洞信息: $cpu_bugs"
        fi
    fi
}

# 16. 检查文件系统特征
check_filesystem_features() {
    log_info "检查文件系统特征..."

    # 检查根文件系统类型
    local root_fs=$(df -T / 2>/dev/null | awk 'NR==2 {print $2}')
    if [[ -n "$root_fs" ]]; then
        echo "   根文件系统类型: $root_fs"

        # 某些文件系统在虚拟化环境中更常见
        if [[ "$root_fs" == "overlay" ]] || [[ "$root_fs" == "aufs" ]]; then
            INCONCLUSIVE_INDICATORS+=("使用容器常用文件系统: $root_fs")
        fi
    fi

    # 检查是否有虚拟化特定的文件系统
    if mount | grep -q "fuse.vmware"; then
        VIRTUAL_INDICATORS+=("VMware FUSE文件系统")
        echo "   ✅ 发现VMware共享文件夹文件系统"
    fi

    if mount | grep -q "vboxsf"; then
        VIRTUAL_INDICATORS+=("VirtualBox共享文件夹文件系统")
        echo "   ✅ 发现VirtualBox共享文件夹文件系统"
    fi

    # 检查设备映射器(常用于虚拟化存储)
    if check_command dmsetup; then
        local dm_devices=$(dmsetup ls --target linear 2>/dev/null | wc -l)
        if [[ "$dm_devices" -gt 0 ]]; then
            echo "   设备映射器设备数: $dm_devices"
            if [[ "$dm_devices" -gt 2 ]]; then
                INCONCLUSIVE_INDICATORS+=("多个设备映射器设备(可能是LVM或虚拟化存储)")
            fi
        fi
    fi

    # 检查 /proc/mounts 中的特殊文件系统
    local special_mounts=$(grep -E "fuse|vbox|vmware" /proc/mounts 2>/dev/null | head -3)
    if [[ -n "$special_mounts" ]]; then
        echo "   特殊文件系统挂载:"
        echo "$special_mounts" | sed 's/^/     /'
    fi
}

# 17. 检查网络高级特征
check_advanced_network() {
    log_info "检查网络高级特征..."

    # 检查网络设备驱动
    if [[ -d /sys/class/net ]]; then
        local virt_net_detected=false
        local phys_net_detected=false

        for iface in /sys/class/net/*; do
            local iface_name=$(basename "$iface")
            # 跳过lo回环接口
            if [[ "$iface_name" != "lo" ]]; then
                if [[ -f "$iface/device/driver" ]]; then
                    local driver=$(basename $(readlink "$iface/device/driver") 2>/dev/null)
                    if [[ -n "$driver" ]]; then
                        echo "   接口 $iface_name 驱动: $driver"
                        if echo "$driver" | grep -qiE "virtio|veth|vif|vmxnet"; then
                            VIRTUAL_INDICATORS+=("虚拟网络驱动: $driver")
                            virt_net_detected=true
                        elif echo "$driver" | grep -qiE "e1000|igb|ixgbe|bnx2x|tg3"; then
                            PHYSICAL_INDICATORS+=("物理网络驱动: $driver")
                            phys_net_detected=true
                        fi
                    fi
                fi
            fi
        done

        if [[ "$virt_net_detected" == false ]] && [[ "$phys_net_detected" == false ]]; then
            echo "   无法确定网络驱动类型"
        fi
    fi

    # 检查网络时间协议(NTP)配置
    if check_command timedatectl; then
        local ntp_service=$(timedatectl show --property=NTPSynchronized --value 2>/dev/null)
        if [[ "$ntp_service" == "yes" ]]; then
            echo "   NTP同步: 已启用"
        else
            echo "   NTP同步: 未启用或无法确定"
        fi
    elif check_command ntpq; then
        local ntp_peers=$(ntpq -p 2>/dev/null | wc -l)
        if [[ $ntp_peers -gt 0 ]]; then
            echo "   NTP对等点: $((ntp_peers - 2)) 个"
        fi
    fi

    # 检查网络桥接信息
    if check_command brctl; then
        local bridges=$(brctl show 2>/dev/null | sed '1d' | wc -l)
        if [[ $bridges -gt 0 ]]; then
            echo "   网络桥接数量: $bridges"
            INCONCLUSIVE_INDICATORS+=("存在网络桥接(可能是虚拟化网络)")
        fi
    fi
}

# 18. 检查系统调用和性能计数器检测
check_syscall_features() {
    log_info "检查系统调用特征..."

    # 检查 /proc/cpuinfo 中的bugs字段
    local cpu_bugs=$(grep "bugs" /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)
    if [[ -n "$cpu_bugs" ]]; then
        echo "   CPU漏洞信息: $cpu_bugs"
        # 某些CPU漏洞在虚拟化环境中表现不同
        if echo "$cpu_bugs" | grep -qi "spectre"; then
            INCONCLUSIVE_INDICATORS+=("存在Spectre漏洞缓解")
        fi
        if echo "$cpu_bugs" | grep -qi "meltdown"; then
            INCONCLUSIVE_INDICATORS+=("存在Meltdown漏洞缓解")
        fi
    fi

    # 检查系统页大小
    if check_command getconf; then
        local page_size=$(getconf PAGE_SIZE)
        echo "   系统页大小: $page_size 字节"

        # 检查大页支持
        if [[ -d /sys/kernel/mm/hugepages ]]; then
            local hugepages=$(ls /sys/kernel/mm/hugepages/ 2>/dev/null | wc -l)
            if [[ $hugepages -gt 0 ]]; then
                echo "   大页支持: 已启用"
                PHYSICAL_INDICATORS+=("启用大页支持(物理机常见)")
            fi
        fi
    fi

    # 检查内核版本和构建选项
    local kernel_version=$(uname -r)
    echo "   内核版本: $kernel_version"

    # 检查内核是否包含虚拟化相关模块
    if [[ -d /lib/modules/$kernel_version ]]; then
        local kvm_modules=$(find /lib/modules/$kernel_version -name "*kvm*" -o -name "*virtio*" 2>/dev/null | wc -l)
        if [[ $kvm_modules -gt 0 ]]; then
            echo "   内核虚拟化模块: $kvm_modules 个"
        fi
    fi
}

# 19. 检查云环境特定检测
check_cloud_environment() {
    log_info "检查云环境特征..."

    local cloud_detected=false

    # AWS 检测
    if curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/ > /dev/null; then
        VIRTUAL_INDICATORS+=("AWS EC2实例")
        echo "   ☁️ 检测到AWS环境"
        cloud_detected=true

        # 尝试获取AWS实例类型
        local aws_instance_type=$(curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/instance-type 2>/dev/null)
        if [[ -n "$aws_instance_type" ]]; then
            echo "   AWS实例类型: $aws_instance_type"
        fi
    fi

    # 京东云检测 
    if curl -s --connect-timeout 2 -H "Metadata-Flavor: JDCloud" http://169.254.169.254/latest/meta-data/ > /dev/null; then
        VIRTUAL_INDICATORS+=("京东云实例")
        echo "   ☁️ 检测到京东云环境"
        cloud_detected=true

        # 尝试获取京东云实例信息
        local jd_metadata=$(curl -s --connect-timeout 2 -H "Metadata-Flavor: JDCloud" http://169.254.169.254/latest/meta-data/ 2>/dev/null | head -5)
        if [[ -n "$jd_metadata" ]]; then
            echo "   京东云元数据可用"
        fi
    fi

    # 华为云检测
    if curl -s --connect-timeout 2 -H "Metadata-Flavor: Huawei" http://169.254.169.254/latest/meta-data/ > /dev/null || 
       curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/ > /dev/null; then
        # 验证是否为华为云
        local huawei_meta=$(curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/ 2>/dev/null | head -10)
        if echo "$huawei_meta" | grep -qi "huawei\|ecs" || [[ -n "$huawei_meta" ]]; then
            VIRTUAL_INDICATORS+=("华为云实例")
            echo "   ☁️ 检测到华为云环境"
            cloud_detected=true

            # 尝试获取华为云实例信息
            local huawei_instance_id=$(curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null)
            if [[ -n "$huawei_instance_id" ]]; then
                echo "   华为云实例ID: $huawei_instance_id"
            fi
        fi
    fi

    # 腾讯云检测 
    if curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/ > /dev/null; then
        local tx_metadata=$(curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/ 2>/dev/null)
        if echo "$tx_metadata" | grep -q "qcloud" || echo "$tx_metadata" | grep -q "tencent" || 
           [[ -f /etc/tlinux-release ]] || systemctl list-unit-files | grep -q "qcloud"; then
            VIRTUAL_INDICATORS+=("腾讯云实例")
            echo "   ☁️ 检测到腾讯云环境"
            cloud_detected=true

            # 检查腾讯云特定服务
            if systemctl list-unit-files | grep -q "qcloud"; then
                echo "   发现腾讯云相关服务"
            fi

            # 尝试获取腾讯云实例信息
            local tx_instance_id=$(curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null)
            if [[ -n "$tx_instance_id" ]]; then
                echo "   腾讯云实例ID: $tx_instance_id"
            fi
        fi
    fi

    # 阿里云检测 
    if curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/ > /dev/null; then
        local aliyun_metadata=$(curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/ 2>/dev/null)
        if echo "$aliyun_metadata" | grep -q "aliyun" || echo "$aliyun_metadata" | grep -q "ecs" || 
           [[ -f /etc/aliyun-release ]] || systemctl list-unit-files | grep -q "aliyun"; then
            VIRTUAL_INDICATORS+=("阿里云实例")
            echo "   ☁️ 检测到阿里云环境"
            cloud_detected=true

            # 尝试获取阿里云实例信息
            local aliyun_instance_id=$(curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null)
            if [[ -n "$aliyun_instance_id" ]]; then
                echo "   阿里云实例ID: $aliyun_instance_id"
            fi

            local aliyun_region=$(curl -s --connect-timeout 2 http://169.254.169.254/latest/meta-data/region-id 2>/dev/null)
            if [[ -n "$aliyun_region" ]]; then
                echo "   阿里云区域: $aliyun_region"
            fi
        fi
    fi

    # Google Cloud 检测
    if curl -s --connect-timeout 2 -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/ > /dev/null; then
        VIRTUAL_INDICATORS+=("Google Cloud实例")
        echo "   ☁️ 检测到Google Cloud环境"
        cloud_detected=true
    fi

    # Azure 检测
    if curl -s --connect-timeout 2 -H "Metadata: true" http://169.254.169.254/metadata/instance > /dev/null; then
        VIRTUAL_INDICATORS+=("Azure虚拟机")
        echo "   ☁️ 检测到Azure环境"
        cloud_detected=true
    fi

    # DigitalOcean 检测
    if curl -s --connect-timeout 2 http://169.254.169.254/metadata/v1.json > /dev/null; then
        VIRTUAL_INDICATORS+=("DigitalOcean Droplet")
        echo "   ☁️ 检测到DigitalOcean环境"
        cloud_detected=true
    fi

    # Oracle Cloud 检测
    if curl -s --connect-timeout 2 http://169.254.169.254/opc/v1/instance/ > /dev/null; then
        VIRTUAL_INDICATORS+=("Oracle Cloud实例")
        echo "   ☁️ 检测到Oracle Cloud环境"
        cloud_detected=true
    fi

    # 检查云初始化标志
    if [[ -f /etc/cloud/cloud.cfg ]] || [[ -d /var/lib/cloud ]]; then
        echo "   ☁️ 发现云初始化配置"
        cloud_detected=true

        # 检查云初始化供应商
        if [[ -f /etc/cloud/cloud.cfg ]]; then
            local cloud_vendor=$(grep -i "cloud" /etc/cloud/cloud.cfg | head -1)
            if [[ -n "$cloud_vendor" ]]; then
                echo "   云初始化配置: $cloud_vendor"
            fi
        fi
    fi

    # 检查 cloud-init 服务
    if systemctl is-active cloud-init >/dev/null 2>&1 || systemctl is-enabled cloud-init >/dev/null 2>&1; then
        echo "   ☁️ cloud-init服务已启用"
        cloud_detected=true
    fi

    # 检查云厂商特定的驱动和服务
    check_cloud_specific_services

    if [[ "$cloud_detected" == false ]]; then
        echo "   未检测到主流云环境特征"
    else
        INCONCLUSIVE_INDICATORS+=("运行在云环境中")
    fi
}

# 辅助函数:检查云厂商特定的驱动和服务
check_cloud_specific_services() {
    log_info "检查云厂商特定服务..."

    # 检查阿里云特定服务 
    if systemctl list-unit-files | grep -q "aliyun"; then
        VIRTUAL_INDICATORS+=("阿里云服务")
        echo "   ✅ 发现阿里云相关服务"
    fi

    # 检查腾讯云特定服务 
    if systemctl list-unit-files | grep -q "qcloud\|tencent"; then
        VIRTUAL_INDICATORS+=("腾讯云服务")
        echo "   ✅ 发现腾讯云相关服务"
    fi

    # 检查华为云特定服务
    if systemctl list-unit-files | grep -q "huawei"; then
        VIRTUAL_INDICATORS+=("华为云服务")
        echo "   ✅ 发现华为云相关服务"
    fi

    # 检查京东云特定服务
    if systemctl list-unit-files | grep -q "jdcloud"; then
        VIRTUAL_INDICATORS+=("京东云服务")
        echo "   ✅ 发现京东云相关服务"
    fi

    # 检查云厂商特定的驱动模块
    local cloud_drivers=$(lsmod | grep -iE "virtio|vmw|vbox|qemu|xen|hv_" | head -5)
    if [[ -n "$cloud_drivers" ]]; then
        echo "   虚拟化驱动:"
        echo "$cloud_drivers" | sed 's/^/     /'
    fi

    # 检查云厂商特定的进程
    local cloud_processes=$(ps aux | grep -E "(aliyun|qcloud|jdcloud|huawei|aws|azure|gcp)" | grep -v grep | head -5)
    if [[ -n "$cloud_processes" ]]; then
        echo "   云厂商相关进程:"
        echo "$cloud_processes" | sed 's/^/     /'
    fi

    # 检查云厂商特定的配置文件
    local cloud_configs=$(find /etc -name "*cloud*" -type f 2>/dev/null | head -5)
    if [[ -n "$cloud_configs" ]]; then
        echo "   云相关配置文件:"
        echo "$cloud_configs" | sed 's/^/     /'
    fi

    # 检查云厂商特定的日志文件
    local cloud_logs=$(find /var/log -name "*cloud*" -type f 2>/dev/null | head -3)
    if [[ -n "$cloud_logs" ]]; then
        echo "   云相关日志文件:"
        echo "$cloud_logs" | sed 's/^/     /'
    fi
}

# 20. 检查系统架构和平台特定特征
check_system_architecture() {
    log_info "检查系统架构..."

    local architecture=$(uname -m)
    echo "   系统架构: $architecture"

    case $architecture in
        "x86_64")
            PHYSICAL_INDICATORS+=("x86_64架构")
            ;;
        "aarch64"|"arm64")
            echo "   ARM64架构"
            # ARM架构在虚拟化和物理机都有广泛应用
            ;;
        "ppc64"|"ppc64le")
            echo "   PowerPC架构"
            PHYSICAL_INDICATORS+=("PowerPC架构(通常为物理机)")
            ;;
        "s390x")
            echo "   IBM Z架构"
            PHYSICAL_INDICATORS+=("IBM Z架构(通常为物理机或大型机)")
            ;;
        *)
            echo "   其他架构: $architecture"
            ;;
    esac

    # 检查UEFI/BIOS引导
    if [[ -d /sys/firmware/efi ]]; then
        echo "   引导方式: UEFI"
        PHYSICAL_INDICATORS+=("UEFI引导")
    else
        echo "   引导方式: BIOS"
    fi
}

# 汇总结果显示
show_results() {
    echo
    echo "================================================"
    echo "              环境检测结果(增强版)"
    echo "================================================"

    local virtual_score=${#VIRTUAL_INDICATORS[@]}
    local physical_score=${#PHYSICAL_INDICATORS[@]}
    local inconclusive_score=${#INCONCLUSIVE_INDICATORS[@]}

    # 显示详细证据
    if [[ $virtual_score -gt 0 ]]; then
        echo -e "\n${RED}🚨 检测到虚拟机特征 ($virtual_score 个证据):${NC}"
        for indicator in "${VIRTUAL_INDICATORS[@]}"; do
            echo -e "  ❌ $indicator"
        done
    fi

    if [[ $physical_score -gt 0 ]]; then
        echo -e "\n${GREEN}✅ 检测到物理服务器特征 ($physical_score 个证据):${NC}"
        for indicator in "${PHYSICAL_INDICATORS[@]}"; do
            echo -e "  ✅ $indicator"
        done
    fi

    if [[ $inconclusive_score -gt 0 ]]; then
        echo -e "\n${YELLOW}⚠️  不确定的特征 ($inconclusive_score 个):${NC}"
        for indicator in "${INCONCLUSIVE_INDICATORS[@]}"; do
            echo -e "  ⚠️  $indicator"
        done
    fi

    echo
    echo "================================================"

    # 增强的判断逻辑
    local confidence_level=""
    local conclusion=""

    if [[ $virtual_score -ge 5 ]] && [[ $physical_score -le 1 ]]; then
        conclusion="${RED}🎯 结论: 这是一个虚拟机环境(高置信度)${NC}"
        confidence_level="高"
    elif [[ $physical_score -ge 5 ]] && [[ $virtual_score -le 1 ]]; then
        conclusion="${GREEN}🎯 结论: 这是一个物理服务器环境(高置信度)${NC}"
        confidence_level="高"
    elif [[ $virtual_score -ge 3 ]] && [[ $virtual_score -gt $physical_score ]]; then
        conclusion="${RED}🎯 结论: 这很可能是一个虚拟机环境(中等置信度)${NC}"
        confidence_level="中"
    elif [[ $physical_score -ge 3 ]] && [[ $physical_score -gt $virtual_score ]]; then
        conclusion="${GREEN}🎯 结论: 这很可能是一个物理服务器环境(中等置信度)${NC}"
        confidence_level="中"
    elif [[ $virtual_score -eq 0 ]] && [[ $physical_score -eq 0 ]]; then
        conclusion="${YELLOW}🎯 结论: 证据不足,无法明确判断环境类型${NC}"
        confidence_level="低"
    elif [[ $virtual_score -eq $physical_score ]] && [[ $virtual_score -gt 0 ]]; then
        conclusion="${YELLOW}🎯 结论: 环境类型存在矛盾特征,需要进一步分析${NC}"
        confidence_level="低"
    else
        conclusion="${YELLOW}🎯 结论: 环境类型不确定,证据相互矛盾${NC}"
        confidence_level="低"
    fi

    echo -e "$conclusion"
    echo -e "${BLUE}📊 检测置信度: $confidence_level${NC}"
    echo -e "${CYAN}🔍 检测维度: 20个${NC}"
    echo -e "${CYAN}📈 证据统计: 虚拟[$virtual_score] | 物理[$physical_score] | 不确定[$inconclusive_score]${NC}"

    # 显示建议
    echo "================================================"
    if ! check_root; then
        echo -e "${YELLOW}💡 建议: 使用root权限重新运行以获得更准确的结果${NC}"
        echo -e "${YELLOW}      sudo $0${NC}"
    fi

    local missing_tools=""
    if ! check_command dmidecode; then
        missing_tools="$missing_tools dmidecode"
    fi
    if ! check_command lspci; then
        missing_tools="$missing_tools pciutils"
    fi
    if ! check_command lsblk; then
        missing_tools="$missing_tools util-linux"
    fi

    if [[ -n "$missing_tools" ]]; then
        echo -e "${YELLOW}💡 建议: 安装缺失的工具以获得完整检测${NC}"
        echo -e "${YELLOW}      sudo apt-get install$missing_tools${NC}"
    fi

    # 新增:根据检测结果给出具体建议
    if [[ $confidence_level == "低" ]]; then
        echo -e "${YELLOW}💡 建议: 考虑使用多种工具交叉验证${NC}"
        echo -e "${YELLOW}      可尝试: virt-what, systemd-detect-virt, dmidecode -t system${NC}"
    fi

    if [[ $virtual_score -gt 0 ]]; then
        echo -e "${BLUE}💡 提示: 检测到虚拟化特征,可能是云服务器、VPS或企业虚拟化平台${NC}"
    fi

    if [[ $physical_score -gt 0 ]]; then
        echo -e "${BLUE}💡 提示: 检测到物理服务器特征,可能是裸金属服务器或专用硬件${NC}"
    fi

    echo "================================================"
}

# 显示脚本头信息
show_header() {
    echo -e "${CYAN}"
    echo "╔══════════════════════════════════════════════════════════════╗"
    echo "║                  服务器环境检测脚本 v2.0                    ║"
    echo "║               Enhanced Server Environment Detector          ║"
    echo "║                                                              ║"
    echo "║  功能: 物理机/虚拟机检测 • 云环境识别 • 容器环境排除        ║"
    echo "║  检测: 20个维度全方位分析 • 多证据链交叉验证 • 置信度评估   ║"
    echo "╚══════════════════════════════════════════════════════════════╝"
    echo -e "${NC}"
}

# 主函数
main() {
    show_header
    echo -e "${BLUE}开始检测系统环境类型...${NC}"
    echo "================================================"

    # 记录开始时间
    local start_time=$(date +%s)

    # 显示权限警告
    show_permission_warning

    # 检查容器环境
    check_container

    # 执行各项检测
    check_system_architecture
    check_system_manufacturer
    check_bios_info
    check_cpu_info
    check_advanced_cpu
    check_memory_info
    check_disk_info
    check_device_drivers
    check_system_services
    check_network_interfaces
    check_advanced_network
    check_dmesg
    check_system_files
    check_virt_specific
    check_clocksource
    check_filesystem_features
    check_syscall_features
    check_cloud_environment
    check_performance

    # 记录结束时间并计算耗时
    local end_time=$(date +%s)
    local duration=$((end_time - start_time))

    echo
    echo "================================================"
    echo -e "${GREEN}所有检测完成,总耗时: ${duration}秒${NC}"
    echo "================================================"

    # 显示结果
    show_results
}

# 脚本入口
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main
fi

3、赋予执行权限

chmod +x /usr/local/bin/server_detective.sh

4、运行检测

# 完整检测(使用root权限)
sudo /usr/local/bin/server_detective.sh

5、解读检测报告

脚本会提供清晰的证据清单和置信度评估:

🚨 红色:虚拟机证据

✅ 绿色:物理机证据

⚠️ 黄色:不确定特征

高置信度结论会明确告诉你服务器类型,低置信度结论会给出进一步排查建议。

这个脚本不仅仅是一堆命令的集合,它体现了系统检测的深层智慧:

智能证据权重
不同证据的可靠性不同。比如,云元数据服务是强证据,而性能测试结果是弱证据。脚本会智能权衡各种证据的可信度。

渐进式检测策略
从低成本检测开始,逐步深入到需要特权的操作。即使没有root权限,也能提供有价值的参考结果。

交叉验证机制
多个独立证据相互印证,避免单一特征的误判。就像多个目击证人的证词比单人证词更可靠。

容器环境识别
特别加入容器检测,避免在容器环境中得出误导性结论。

全面的云环境支持
不仅支持AWS、Azure等国际云厂商,还特别优化了对阿里云、腾讯云、华为云、京东云等国内主流云平台的检测。

结语:让服务器身份不再成谜

在这个混合云、虚拟化、容器化交织的复杂时代,准确识别服务器环境已经成为每个技术人员的必备技能。我们的脚本就像一位经验丰富的侦探,帮你拨开迷雾,看清真相。

无论你是:

运维工程师排查性能问题

架构师规划系统架构

安全专员进行合规检查

开发人员调试环境问题

这个工具都能为你提供可靠的环境洞察。下次当你面对一台陌生服务器时,不必再猜测它的真实身份——让脚本在60秒内给你确切的答案。

在IT的世界里,看清本质比盲目努力更重要。现在就开始使用这个脚本,让你的服务器管理变得更加精准和高效!

免责声明

本文及附带的检测脚本仅供技术参考和学习使用,不能保证在所有场景下100%准确识别服务器环境。限于技术发展的复杂性和多样性,以下情况可能影响检测结果的准确性:

新型虚拟化技术:随着虚拟化技术的不断发展,新的虚拟化方案可能采用未被脚本识别的新型特征和隐藏技术

特殊硬件配置:某些定制化硬件或特殊配置的服务器可能表现出非常规特征,导致误判

云厂商技术更新:各云服务提供商可能随时更新其底层技术架构,改变原有的识别特征

人为干扰因素:故意伪装或安全加固措施可能有意掩盖环境特征,干扰检测结果

边缘案例和特殊情况:某些混合环境或边缘计算场景可能无法被现有检测逻辑完全覆盖

使用者应意识到:

本脚本的检测结果应作为参考依据之一,而非唯一决策标准

重要环境判断建议结合多种工具和手动验证

生产环境的关键决策应基于更全面的技术评估

作者不对因使用本脚本而产生的任何直接或间接损失负责