#!/usr/bin/env bash
# ==============================================================================
# LinuxCheck - Linux Server Self-Troubleshooting Diagnostic Script
# Version  : v1.0.0
# Compat   : CentOS 7/8/9, Ubuntu 18~24, Debian 10~12, Rocky/Alma Linux
# Usage    : sudo bash LinuxCheckFull.sh
# NOTE     : Requires root/sudo for full security log access.
#            All output is UTF-8. Chinese labels appear in TXT report.
# ==============================================================================

set -uo pipefail

# ANSI Color Codes
C_RESET="\033[0m"; C_CYAN="\033[0;36m"; C_YELLOW="\033[0;33m"
C_GREEN="\033[0;32m"; C_RED="\033[0;31m"; C_GRAY="\033[0;90m"
C_BOLD_RED="\033[1;31m"; C_BOLD_YELLOW="\033[1;33m"
C_BOLD_GREEN="\033[1;32m"; C_BOLD_CYAN="\033[1;36m"

# Global Variables
SCRIPT_VERSION="v1.0.0"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
HOSTNAME_VAL=$(hostname -s 2>/dev/null || hostname)
MAIN_IP=$(ip route get 1.1.1.1 2>/dev/null | grep -oP 'src \K[\d.]+' | head -1)
[[ -z "${MAIN_IP:-}" ]] && MAIN_IP=$(hostname -I 2>/dev/null | awk '{print $1}')
[[ -z "${MAIN_IP:-}" ]] && MAIN_IP="UnknownIP"
REPORT_DIR="/tmp/LinuxCheck_${HOSTNAME_VAL}_${TIMESTAMP}"
TXT_REPORT="${REPORT_DIR}/LinuxCheck_${HOSTNAME_VAL}_${TIMESTAMP}.txt"

declare -a CRITICALS=()
declare -a WARNINGS=()
declare -a TXT_LINES=()

SYS_OS=""; SYS_KERNEL=""; SYS_UPTIME=""; SYS_LASTBOOT=""
SYS_CPU_MODEL=""; SYS_CPU_CORES=""; SYS_TOTAL_RAM=""
RES_CPU_PCT=""; RES_RAM_USAGE=""; RES_SWAP_USAGE=""
NET_TCP_TOTAL="0"; NET_ESTABLISHED="0"; NET_TIME_WAIT="0"
NET_CLOSE_WAIT="0"; NET_SYN_RECV="0"; NET_LISTEN="0"; NET_TOP_IPS=""
ROUTE_GW=""; ROUTE_GW_MAC=""; ROUTE_NIC_MAC=""; ROUTE_BAD_ROUTES=""
SSH_PORT=""; SSH_STATUS=""; SSH_PERMIT_ROOT=""; SSH_PASSWD_AUTH=""; SSH_MAX_AUTH=""
SECURITY_FAILED_24H="0"; SECURITY_ASSESSMENT=""

# ==============================================================================
# Helper Functions
# ==============================================================================
log() { TXT_LINES+=("$1"); }

# Evidence-aware add helpers: add_crit "message" ["evidence_text"]
# Evidence is stored inline using |EV| separator
add_crit() {
    local msg="$1" ev="${2:-}"
    if [[ -n "$ev" ]]; then
        CRITICALS+=("${msg}|EV|${ev}")
    else
        CRITICALS+=("$msg")
    fi
}
add_warn() {
    local msg="$1" ev="${2:-}"
    if [[ -n "$ev" ]]; then
        WARNINGS+=("${msg}|EV|${ev}")
    else
        WARNINGS+=("$msg")
    fi
}


print_item() {
    local status="${1:-INFO}" label="${2:-}" value="${3:-}"
    local prefix color
    case "$status" in
        OK)   prefix="[+]"; color="$C_GREEN"  ;;
        WARN) prefix="[!]"; color="$C_YELLOW" ;;
        CRIT) prefix="[X]"; color="$C_RED"    ;;
        *)    prefix="[*]"; color="$C_CYAN"   ;;
    esac
    printf "${color}${prefix}${C_RESET}  %-32s: %s\n" "$label" "$value"
    log "  ${prefix}  $(printf '%-32s' "$label"): ${value}"
}

print_raw() {
    local color="${1:-$C_GRAY}" text="${2:-}"
    printf "${color}%s${C_RESET}\n" "$text"
    log "$text"
}

print_section() {
    local title="$1"
    printf "\n${C_YELLOW}>>> %s${C_RESET}\n" "$title"
    log ""; log "--- ${title} ---"
}

print_header() {
    local title="$1"
    local sep; sep=$(printf '%0.s=' {1..72})
    printf "\n${C_BOLD_CYAN}%s${C_RESET}\n" "$sep"
    printf "${C_BOLD_YELLOW}  %s${C_RESET}\n" "$title"
    printf "${C_BOLD_CYAN}%s${C_RESET}\n" "$sep"
    log ""; log "$sep"; log "  $title"; log "$sep"
}

detect_pkg_manager() {
    command -v apt-get &>/dev/null && echo "apt" && return
    command -v dnf    &>/dev/null && echo "dnf" && return
    command -v yum    &>/dev/null && echo "yum" && return
    echo "unknown"
}

cmd_exists() { command -v "$1" &>/dev/null; }

# ==============================================================================
# Pre-flight
# ==============================================================================
preflight_check() {
    if [[ $EUID -ne 0 ]]; then
        printf "${C_BOLD_YELLOW}[!] WARNING: Not running as root.${C_RESET}\n"
        printf "${C_YELLOW}[!] Security logs/SSH audit require sudo. Run: sudo bash %s${C_RESET}\n\n" "$0"
    fi
    mkdir -p "$REPORT_DIR" || { echo "ERROR: Cannot create $REPORT_DIR"; exit 1; }
}

# ==============================================================================
# MODULE 1: System Overview
# ==============================================================================
collect_system_info() {
    print_header "1. System Overview & Health"

    if [[ -f /etc/os-release ]]; then
        SYS_OS=$(. /etc/os-release && echo "${PRETTY_NAME:-$NAME ${VERSION:-}}")
    elif cmd_exists lsb_release; then
        SYS_OS=$(lsb_release -sd 2>/dev/null | tr -d '"')
    else
        SYS_OS="Unknown Linux"
    fi
    SYS_KERNEL=$(uname -r)

    local uptime_sec
    uptime_sec=$(awk '{print int($1)}' /proc/uptime 2>/dev/null || echo 0)
    local days=$(( uptime_sec / 86400 ))
    local hours=$(( (uptime_sec % 86400) / 3600 ))
    local mins=$(( (uptime_sec % 3600) / 60 ))
    SYS_UPTIME="${days}d ${hours}h ${mins}m"

    SYS_LASTBOOT=$(who -b 2>/dev/null | awk '{print $3, $4}')
    [[ -z "${SYS_LASTBOOT:-}" ]] && SYS_LASTBOOT=$(uptime -s 2>/dev/null || echo "Unknown")

    SYS_CPU_MODEL=$(grep -m1 "model name" /proc/cpuinfo 2>/dev/null | cut -d: -f2 | sed 's/^ //')
    [[ -z "${SYS_CPU_MODEL:-}" ]] && SYS_CPU_MODEL=$(lscpu 2>/dev/null | grep "Model name" | cut -d: -f2 | sed 's/^ //' || echo "Unknown")
    SYS_CPU_CORES=$(nproc 2>/dev/null || grep -c "^processor" /proc/cpuinfo 2>/dev/null || echo "?")

    local total_kb
    total_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}')
    SYS_TOTAL_RAM=$(awk "BEGIN {printf \"%.1f GB\", $total_kb/1048576}")

    print_item "OK"   "Hostname"   "$HOSTNAME_VAL"
    print_item "INFO" "Main IP"    "$MAIN_IP"
    print_item "INFO" "OS"         "$SYS_OS"
    print_item "INFO" "Kernel"     "$SYS_KERNEL"

    local uptime_status="OK"
    if [[ $days -gt 180 ]]; then
        uptime_status="WARN"
        add_warn "[警告] 系统已运行 ${days} 天未重启，建议评估是否需要维护性重启以应用内核更新。"
    elif [[ $days -lt 1 && $hours -lt 1 && $mins -lt 30 ]]; then
        uptime_status="WARN"
        add_warn "[警告] 系统运行时间不足30分钟，可能刚刚发生过意外重启或崩溃！"
    fi
    print_item "$uptime_status" "Uptime"    "$SYS_UPTIME"
    print_item "INFO"           "Last Boot" "$SYS_LASTBOOT"
    print_item "INFO"           "CPU"       "${SYS_CPU_MODEL} (${SYS_CPU_CORES} cores)"
    print_item "INFO"           "Total RAM" "$SYS_TOTAL_RAM"
}

# ==============================================================================
# MODULE 2: System Update Status
# ==============================================================================
collect_update_info() {
    print_header "2. System Update & Patch Status"

    local pkg_mgr; pkg_mgr=$(detect_pkg_manager)
    print_item "INFO" "Package Manager" "$pkg_mgr"

    local pending_count=0 pending_str="Unable to check" recent_pkgs="N/A"

    case "$pkg_mgr" in
        apt)
            pending_count=$(apt-get --simulate upgrade 2>/dev/null | grep "^Inst " | wc -l)
            pending_str="${pending_count} packages pending"
            recent_pkgs=$(grep " install " /var/log/dpkg.log 2>/dev/null | tail -5 | awk '{print $5}' | tr '\n' ' ' || echo "(no log)")
            ;;
        dnf|yum)
            pending_count=$("$pkg_mgr" check-update --quiet 2>/dev/null | grep -v "^$\|^Last\|^Loaded\|^Loading\|^Obsoleting" | wc -l || true); pending_count=${pending_count:-0}
            pending_str="${pending_count} packages pending"
            recent_pkgs=$(rpm -qa --last 2>/dev/null | head -5 | awk '{print $1}' | tr '\n' ' ' || echo "(no log)")
            ;;
        *)
            pending_str="Unknown pkg manager, check manually"
            ;;
    esac

    local update_status="OK"
    if   [[ $pending_count -gt 100 ]]; then
        update_status="CRIT"
        local pkg_list; pkg_list=$(apt-get --simulate upgrade 2>/dev/null | grep "^Inst " | head -10 | awk '{print $2}' | tr '\n' ' ' || true)
        add_crit "[严重] 系统有 ${pending_count} 个待更新包，安全补丁严重滞后，建议立即更新！" "待更新包(前10): ${pkg_list}"
    elif [[ $pending_count -gt 20  ]]; then
        update_status="WARN"
        add_warn "[警告] 系统有 ${pending_count} 个待更新包，建议尽快安排更新。"
    fi
    print_item "$update_status" "Pending Updates"       "$pending_str"
    print_item "INFO"           "Recent Installs (top5)" "${recent_pkgs:-N/A}"

    # Kernel reboot check
    local running_kernel installed_kernel
    running_kernel=$(uname -r)
    installed_kernel=""
    if   [[ "$pkg_mgr" == "apt" ]]; then
        # Extract full version string from package name, e.g. linux-image-6.1.0-32-amd64 -> 6.1.0-32-amd64
        installed_kernel=$(dpkg -l 'linux-image-[0-9]*' 2>/dev/null | awk '/^ii/{print $2}' | sed 's/linux-image-//' | sort -V | tail -1)
        # Fallback: check installed kernel packages without the version filter
        [[ -z "${installed_kernel:-}" ]] && installed_kernel=$(dpkg -l 'linux-image-*' 2>/dev/null | awk '/^ii/{print $2}' | grep -v "extra\|modules\|dbg" | sort -V | tail -1 | sed 's/linux-image-//')
    elif [[ "$pkg_mgr" == "dnf" || "$pkg_mgr" == "yum" ]]; then
        installed_kernel=$(rpm -q kernel --qf '%{VERSION}-%{RELEASE}.%{ARCH}\n' 2>/dev/null | sort -V | tail -1)
    fi

    if [[ -n "${installed_kernel:-}" && "$installed_kernel" != "$running_kernel" ]]; then
        print_item "WARN" "Kernel Reboot Needed" "YES | Running: ${running_kernel} | Latest: ${installed_kernel}"
        add_warn "[警告] 内核已更新但未重启生效，运行中 ${running_kernel}，最新 ${installed_kernel}，建议安排重启。" "运行: ${running_kernel}  已安装最新: ${installed_kernel}"
    else
        print_item "OK" "Kernel Reboot Needed" "No (clean)"
    fi
}

# ==============================================================================
# MODULE 3: Resource Usage
# ==============================================================================
collect_resource_usage() {
    print_header "3. CPU / RAM / Swap / Disk / Processes"

    # CPU (1s sample via /proc/stat)
    local -a cpu1 cpu2
    read -ra cpu1 < <(grep '^cpu ' /proc/stat)
    sleep 1
    read -ra cpu2 < <(grep '^cpu ' /proc/stat)
    local t1=$(( cpu1[1]+cpu1[2]+cpu1[3]+cpu1[4]+cpu1[5]+cpu1[6]+cpu1[7] ))
    local t2=$(( cpu2[1]+cpu2[2]+cpu2[3]+cpu2[4]+cpu2[5]+cpu2[6]+cpu2[7] ))
    local i1=${cpu1[4]} i2=${cpu2[4]}
    local tdiff=$(( t2-t1 )) idiff=$(( i2-i1 ))
    local cpu_pct=0
    [[ $tdiff -gt 0 ]] && cpu_pct=$(( 100*(tdiff-idiff)/tdiff ))
    RES_CPU_PCT="${cpu_pct}%"
    local cpu_status="OK"
    if   [[ $cpu_pct -ge 90 ]]; then cpu_status="CRIT"; CRITICALS+=("[严重] CPU使用率 ${cpu_pct}%，已达临界值，可能正遭受攻击或存在异常进程！")
    elif [[ $cpu_pct -ge 75 ]]; then cpu_status="WARN"; WARNINGS+=("[警告] CPU使用率 ${cpu_pct}%，负载较高，建议排查高CPU进程。")
    fi
    print_item "$cpu_status" "CPU Usage" "$RES_CPU_PCT"

    # Load average
    local load_avg; load_avg=$(awk '{print $1, $2, $3}' /proc/loadavg)
    local load1; load1=$(echo "$load_avg" | awk '{print $1}')
    local load1_int; load1_int=$(echo "$load1" | awk '{printf "%d", $1*10}')
    local cores_int=$(( SYS_CPU_CORES * 10 ))
    local load_status="OK"
    if   [[ $load1_int -gt $(( cores_int*2 )) ]]; then load_status="CRIT"; CRITICALS+=("[严重] 系统负载 ${load1} 超过CPU核数 ${SYS_CPU_CORES} 的2倍，系统严重过载！")
    elif [[ $load1_int -gt $cores_int         ]]; then load_status="WARN"; WARNINGS+=("[警告] 系统1分钟负载 ${load1} 超过CPU核数 ${SYS_CPU_CORES}，建议排查原因。")
    fi
    print_item "$load_status" "Load Average (1/5/15m)" "$load_avg"

    # RAM
    local mem_total mem_avail mem_used mem_pct
    mem_total=$(grep MemTotal    /proc/meminfo | awk '{print $2}')
    mem_avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
    mem_used=$(( mem_total - mem_avail ))
    mem_pct=$(awk "BEGIN {printf \"%d\", ($mem_used/$mem_total)*100}")
    local used_gb; used_gb=$(awk "BEGIN {printf \"%.1f\", $mem_used/1048576}")
    local tot_gb;  tot_gb=$(awk  "BEGIN {printf \"%.1f\", $mem_total/1048576}")
    RES_RAM_USAGE="${mem_pct}% (${used_gb}GB / ${tot_gb}GB)"
    local ram_status="OK"
    if   [[ $mem_pct -ge 90 ]]; then ram_status="CRIT"; add_crit "[严重] 内存使用率 ${mem_pct}%，内存严重不足，可能导致OOM kill或系统崩溃！" "使用: ${RES_RAM_USAGE}"
    elif [[ $mem_pct -ge 80 ]]; then ram_status="WARN"; add_warn "[警告] 内存使用率 ${mem_pct}%，建议关注并考虑扩容。" "使用: ${RES_RAM_USAGE}"
    fi
    print_item "$ram_status" "RAM Usage" "$RES_RAM_USAGE"

    # Swap
    local swap_total swap_free swap_used
    swap_total=$(grep SwapTotal /proc/meminfo | awk '{print $2}')
    swap_free=$(grep  SwapFree  /proc/meminfo | awk '{print $2}')
    swap_used=$(( swap_total - swap_free ))
    if [[ $swap_total -gt 0 ]]; then
        local swap_pct; swap_pct=$(awk "BEGIN {printf \"%d\", ($swap_used/$swap_total)*100}")
        local su_gb; su_gb=$(awk "BEGIN {printf \"%.1f\", $swap_used/1048576}")
        local st_gb; st_gb=$(awk "BEGIN {printf \"%.1f\", $swap_total/1048576}")
        RES_SWAP_USAGE="${swap_pct}% (${su_gb}GB / ${st_gb}GB)"
        local swap_status="OK"
        if   [[ $swap_pct -ge 90 ]]; then swap_status="CRIT"; add_crit "[严重] Swap使用率 ${swap_pct}%，物理内存严重不足，性能急剧下降！" "Swap使用: ${RES_SWAP_USAGE}"
        elif [[ $swap_pct -ge 60 ]]; then swap_status="WARN"; add_warn "[警告] Swap使用率 ${swap_pct}%，建议增加内存或优化应用。" "Swap使用: ${RES_SWAP_USAGE}"
        fi
        print_item "$swap_status" "Swap Usage" "$RES_SWAP_USAGE"
    else
        RES_SWAP_USAGE="No Swap configured"
        print_item "WARN" "Swap Usage" "No Swap - 建议配置Swap作为内存缓冲"
        add_warn "[警告] 未配置Swap分区，内存耗尽时系统将直接OOM崩溃。"
    fi

    # Top 5 CPU processes
    print_section "Top 5 CPU Processes"
    log "  PID       CPU%  MEM%  RSS     START   COMMAND"
    while IFS= read -r line; do
        local u pid cpu mem vsz rss tty stat start time cmd
        read -r u pid cpu mem vsz rss tty stat start time cmd <<< "$line"
        local rss_mb; rss_mb=$(awk "BEGIN {printf \"%.0f\", $rss/1024}")
        printf "${C_GRAY}    PID:%-7s CPU:%-6s MEM:%-6s RSS:%-7sMB Start:%-7s %s${C_RESET}\n" \
            "$pid" "${cpu}%" "${mem}%" "$rss_mb" "$start" "$cmd"
        log "    PID:$(printf '%-7s' "$pid") CPU:$(printf '%-6s' "${cpu}%") RSS:${rss_mb}MB Start:$start $cmd"
    done < <(ps aux --no-headers 2>/dev/null | sort -rk3 | head -5)

    # Top 5 RAM processes
    print_section "Top 5 RAM Processes"
    while IFS= read -r line; do
        local u pid cpu mem vsz rss tty stat start time cmd
        read -r u pid cpu mem vsz rss tty stat start time cmd <<< "$line"
        local rss_mb; rss_mb=$(awk "BEGIN {printf \"%.0f\", $rss/1024}")
        printf "${C_GRAY}    PID:%-7s MEM:%-6s RSS:%-7sMB Start:%-7s %s${C_RESET}\n" \
            "$pid" "${mem}%" "$rss_mb" "$start" "$cmd"
        log "    PID:$(printf '%-7s' "$pid") MEM:$(printf '%-6s' "${mem}%") RSS:${rss_mb}MB Start:$start $cmd"
    done < <(ps aux --no-headers 2>/dev/null | sort -rk6 | head -5)

    # Disk space
    print_section "Disk Space (df -h)"
    log "  [Status] Filesystem           Size  Used  Avail Use%  Mounted"
    while IFS= read -r line; do
        [[ "$line" == Filesystem* ]] && continue
        local fs size used avail pct mnt
        read -r fs size used avail pct mnt <<< "$line"
        [[ -z "${pct:-}" ]] && continue
        local pct_num="${pct//%/}"
        [[ ! "$pct_num" =~ ^[0-9]+$ ]] && continue

        local avail_val avail_unit avail_mb=99999
        avail_val=$(echo "$avail" | grep -oP '[0-9.]+' | head -1)
        avail_unit=$(echo "$avail" | grep -oP '[GMKT]' | head -1)
        case "${avail_unit:-G}" in
            G) avail_mb=$(awk "BEGIN {printf \"%d\", ${avail_val:-0}*1024}") ;;
            M) avail_mb=$(awk "BEGIN {printf \"%d\", ${avail_val:-0}}") ;;
            K) avail_mb=$(awk "BEGIN {printf \"%d\", ${avail_val:-0}/1024}") ;;
            T) avail_mb=$(awk "BEGIN {printf \"%d\", ${avail_val:-0}*1048576}") ;;
        esac

        local disk_status="OK"
        # /boot is a small partition by design (typically <1GB), use percentage only
        # For large filesystems, also check absolute free space
        local is_boot=0
        [[ "$mnt" == "/boot" || "$mnt" == "/boot/efi" ]] && is_boot=1

        if [[ $is_boot -eq 1 ]]; then
            # /boot: only trigger on very high usage percentage (>90%)
            if   [[ $pct_num -ge 90 ]]; then
                disk_status="CRIT"
                add_crit "[严重] /boot分区 (${fs}) 使用率 ${pct}，剩余仅 ${avail}，可能无法安装新内核更新！" "${fs}  大小:${size}  已用:${used}  剩余:${avail}  挂载:${mnt}"
            elif [[ $pct_num -ge 75 ]]; then
                disk_status="WARN"
                add_warn "[警告] /boot分区 (${fs}) 使用率 ${pct}，剩余 ${avail}，建议清理旧内核: apt autoremove" "${fs}  大小:${size}  已用:${used}  剩余:${avail}  挂载:${mnt}"
            fi
        else
            # Regular partitions: check both percentage and absolute free space
            if   [[ $pct_num -ge 95 || $avail_mb -lt 3072  ]]; then
                disk_status="CRIT"
                add_crit "[严重] 磁盘 ${mnt} (${fs}) 使用率 ${pct}，剩余仅 ${avail}，磁盘即将写满，可能导致服务崩溃！" "${fs}  大小:${size}  已用:${used}  剩余:${avail}  挂载:${mnt}"
            elif [[ $pct_num -ge 85 || $avail_mb -lt 10240 ]]; then
                disk_status="WARN"
                add_warn "[警告] 磁盘 ${mnt} (${fs}) 使用率 ${pct}，剩余 ${avail}，请关注增长趋势。" "${fs}  大小:${size}  已用:${used}  剩余:${avail}  挂载:${mnt}"
            fi
        fi
        local color="$C_GREEN"
        [[ "$disk_status" == "WARN" ]] && color="$C_YELLOW"
        [[ "$disk_status" == "CRIT" ]] && color="$C_RED"
        printf "${color}  [%-4s] %-20s %-6s %-6s %-6s %-6s %s${C_RESET}\n" \
            "$disk_status" "$fs" "$size" "$used" "$avail" "$pct" "$mnt"
        log "  [$disk_status] $(printf '%-20s' "$fs") $size $used $avail $pct $mnt"
    done < <(df -h 2>/dev/null | grep -v "^tmpfs\|^devtmpfs\|^udev\|^none\|^overlay\|^/dev/loop" || true)

    # Inode usage (Linux-specific)
    print_section "Inode Usage (df -i) - Linux特有关键检查"
    local inode_warn=0
    while IFS= read -r line; do
        [[ "$line" == Filesystem* ]] && continue
        local fs inodes iused ifree ipct mnt
        read -r fs inodes iused ifree ipct mnt <<< "$line"
        [[ -z "${ipct:-}" || "$ipct" == "-" ]] && continue
        local ipct_num="${ipct//%/}"
        [[ ! "$ipct_num" =~ ^[0-9]+$ ]] && continue

        local inode_status="OK"
        if   [[ $ipct_num -ge 95 ]]; then
            inode_status="CRIT"; inode_warn=1
            CRITICALS+=("[严重] ${mnt} Inode使用率 ${ipct}！Inode耗尽后即使磁盘有空间也无法创建文件，服务将崩溃！")
        elif [[ $ipct_num -ge 80 ]]; then
            inode_status="WARN"; inode_warn=1
            WARNINGS+=("[警告] ${mnt} Inode使用率 ${ipct}，请清理小文件（session/cache/log碎片）。")
        fi
        [[ "$inode_status" != "OK" ]] && {
            local color="$C_YELLOW"
            [[ "$inode_status" == "CRIT" ]] && color="$C_RED"
            printf "${color}  [%-4s] %-20s Inodes:%-10s Used:%-10s Free:%-10s Use%%:%s  %s${C_RESET}\n" \
                "$inode_status" "$fs" "$inodes" "$iused" "$ifree" "$ipct" "$mnt"
            log "  [$inode_status] $fs Inodes:$inodes Used:$iused Free:$ifree Use%:$ipct $mnt"
        }
    done < <(df -i 2>/dev/null | grep -v "^tmpfs\|^devtmpfs\|^udev\|^none\|^Filesystem\|^/dev/loop" || true)
    [[ $inode_warn -eq 0 ]] && print_item "OK" "Inode Usage" "All filesystems normal"

    # Optional iostat
    if cmd_exists iostat; then
        print_section "Disk I/O Summary (iostat 1s sample)"
        local io_out
        io_out=$(iostat -d -x 1 1 2>/dev/null | grep -v "^Linux\|^Device\|^$" | head -10 || true)
        [[ -n "$io_out" ]] && while IFS= read -r ioline; do
            printf "${C_GRAY}    %s${C_RESET}\n" "$ioline"
            log "    $ioline"
        done <<< "$io_out"
    fi
}

# ==============================================================================
# MODULE 4: Network Connections & Attack Detection
# ==============================================================================
collect_network_info() {
    print_header "4. Network Connections & DDoS/CC Attack Detection"

    local tc_out
    tc_out=$(ss -tn 2>/dev/null || netstat -tn 2>/dev/null || true)
    if [[ -z "$tc_out" ]]; then
        print_item "WARN" "TCP Connections" "Unable to query (ss/netstat not found)"
        return
    fi

    # Use grep | wc -l instead of grep -c to avoid "0\n0" with set -o pipefail
    local total established time_wait close_wait syn_recv listen_count
    total=$(echo "$tc_out" | grep -v "^State\|^Netid" | wc -l)
    established=$(echo "$tc_out" | grep -E "ESTAB|ESTABLISHED" | wc -l)
    time_wait=$(echo "$tc_out" | grep -E "TIME-WAIT|TIME_WAIT" | wc -l)
    close_wait=$(echo "$tc_out" | grep -E "CLOSE-WAIT|CLOSE_WAIT" | wc -l)
    syn_recv=$(echo "$tc_out" | grep -E "SYN-RECV|SYN_RECV" | wc -l)
    listen_count=$(ss -tnl 2>/dev/null | grep "LISTEN" | wc -l || netstat -tnl 2>/dev/null | grep "LISTEN" | wc -l || echo 0)
    # Strip leading whitespace from wc -l output
    total=$(echo "$total" | tr -d ' '); established=$(echo "$established" | tr -d ' ')
    time_wait=$(echo "$time_wait" | tr -d ' '); close_wait=$(echo "$close_wait" | tr -d ' ')
    syn_recv=$(echo "$syn_recv" | tr -d ' '); listen_count=$(echo "$listen_count" | tr -d ' ')

    NET_TCP_TOTAL="$total"; NET_ESTABLISHED="$established"; NET_TIME_WAIT="$time_wait"
    NET_CLOSE_WAIT="$close_wait"; NET_SYN_RECV="$syn_recv"; NET_LISTEN="$listen_count"

    local net_status="OK"
    if   [[ $syn_recv -gt 200 || $total -gt 10000 ]]; then
        net_status="CRIT"
        add_crit "[严重] TCP异常！SYN_RECV:${syn_recv} 总连接:${total}，疑似正遭受SYN Flood/DDoS攻击！" "Total:${total} ESTAB:${established} SYN_RECV:${syn_recv} TIME_WAIT:${time_wait}"
    elif [[ $syn_recv -gt 50  || $total -gt 3000  ]]; then
        net_status="WARN"
        add_warn "[警告] TCP连接数偏高。SYN_RECV:${syn_recv} 总连接:${total}，请关注是否有异常访问。" "Total:${total} ESTAB:${established} SYN_RECV:${syn_recv}"
    fi
    [[ $close_wait -gt 200 ]] && add_warn "[警告] CLOSE_WAIT ${close_wait} 过多，可能存在连接泄漏，建议排查应用连接管理。" "CLOSE_WAIT当前值: ${close_wait}"
    [[ $time_wait  -gt 2000 ]] && add_warn "[警告] TIME_WAIT ${time_wait} 过多，建议调整内核 tcp_tw_reuse 参数。" "TIME_WAIT当前值: ${time_wait}"
    print_item "$net_status" "TCP Summary" \
        "Total:${total} ESTAB:${established} SYN_RECV:${syn_recv} TIME_WAIT:${time_wait} CLOSE_WAIT:${close_wait} LISTEN:${listen_count}"

    # Top 10 external IPs
    print_section "Top 10 External Remote IPs (by connection count)"
    local top_ips
    top_ips=$(ss -tn 2>/dev/null | awk 'NR>1{print $5}' \
        | grep -v "^$\|127\.0\.0\.\|^::1\|^10\.\|^172\.1[6-9]\.\|^172\.2[0-9]\.\|^172\.3[0-1]\.\|^192\.168\." \
        | sed 's/:[0-9]*$//' | sort | uniq -c | sort -rn | head -10 || true)
    if [[ -n "$top_ips" ]]; then
        NET_TOP_IPS=$(echo "$top_ips" | awk '{print $2":"$1}' | tr '\n' '; ')
        while IFS= read -r ipline; do
            local count ip
            count=$(echo "$ipline" | awk '{print $1}')
            ip=$(echo "$ipline" | awk '{print $2}')
            local color="$C_GRAY"
            [[ $count -ge 100 ]] && color="$C_RED"
            [[ $count -ge 20 && $count -lt 100 ]] && color="$C_YELLOW"
            printf "${color}    [%5d conns] %s${C_RESET}\n" "$count" "$ip"
            log "    [$(printf '%5d' "$count") conns] $ip"
        done <<< "$top_ips"
    else
        print_raw "$C_GRAY" "    No significant external connections detected"
    fi

    # Listening ports
    print_section "Listening Ports (ss -tlnp)"
    while IFS= read -r line; do
        [[ "$line" =~ ^(State|Netid|Active) ]] && continue
        printf "${C_GRAY}    %s${C_RESET}\n" "$line"
        log "    $line"
    done < <(ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null | head -30 || true)
}

# ==============================================================================
# MODULE 4.5: Network Routing & Gateway Analysis
# ==============================================================================
collect_network_routing() {
    print_header "4.5 Network Routing & Gateway Analysis"

    ROUTE_GW=$(ip route show default 2>/dev/null | awk '/default/{print $3; exit}')
    [[ -z "${ROUTE_GW:-}" ]] && ROUTE_GW=$(route -n 2>/dev/null | awk '$4~/UG/{print $2; exit}' || echo "Unknown")
    [[ -z "${ROUTE_GW:-}" ]] && ROUTE_GW="Unknown"
    print_item "INFO" "Default Gateway" "$ROUTE_GW"

    if [[ "$ROUTE_GW" != "Unknown" ]]; then
        ROUTE_GW_MAC=$(arp -n "$ROUTE_GW" 2>/dev/null | awk '/ether/{print $3}')
        [[ -z "${ROUTE_GW_MAC:-}" ]] && ROUTE_GW_MAC=$(ip neigh show "$ROUTE_GW" 2>/dev/null | awk '{print $5}')
        [[ -z "${ROUTE_GW_MAC:-}" ]] && ROUTE_GW_MAC="Not in ARP cache"
        print_item "INFO" "Gateway ARP MAC" "$ROUTE_GW_MAC"
    fi

    local default_iface
    default_iface=$(ip route show default 2>/dev/null | awk '/default/{print $5; exit}')
    if [[ -n "${default_iface:-}" ]]; then
        ROUTE_NIC_MAC=$(ip link show "$default_iface" 2>/dev/null | awk '/ether/{print $2}')
        print_item "INFO" "NIC (${default_iface}) MAC" "${ROUTE_NIC_MAC:-N/A}"
    fi

    local bad_routes
    bad_routes=$(ip route 2>/dev/null | grep -E "^0\.0\.0\.0/1 |^128\.0\.0\.0/1 " || true)
    if [[ -n "$bad_routes" ]]; then
        ROUTE_BAD_ROUTES="$bad_routes"
        print_item "WARN" "VPN/Proxy Override Routes" "DETECTED: $(echo "$bad_routes" | tr '\n' ' ')"
        add_warn "[警告] 检测到VPN/代理覆盖路由(0.0.0.0/1 + 128.0.0.0/1)，所有流量可能被重定向，请确认是否为预期配置。" "$(echo "$bad_routes" | tr '\n' ' ')"
    else
        print_item "OK" "Suspicious Routes" "None detected"
    fi

    print_section "Route Table (ip route)"
    while IFS= read -r rline; do
        printf "${C_GRAY}    %s${C_RESET}\n" "$rline"
        log "    $rline"
    done < <(ip route 2>/dev/null | head -20 || true)

    print_section "Traceroute to 1.1.1.1 (max 8 hops)"
    printf "${C_GRAY}    Running traceroute, please wait...${C_RESET}\n"
    local tr_out="traceroute/tracepath not available"
    if   cmd_exists traceroute; then tr_out=$(traceroute -n -m 8 -w 2 1.1.1.1 2>/dev/null | head -15 || echo "Failed")
    elif cmd_exists tracepath;  then tr_out=$(tracepath  -n -m 8      1.1.1.1 2>/dev/null | head -15 || echo "Failed")
    fi
    while IFS= read -r trline; do
        printf "${C_GRAY}    %s${C_RESET}\n" "$trline"
        log "    $trline"
    done <<< "$tr_out"
}

# ==============================================================================
# MODULE 5: NIC Health
# ==============================================================================
collect_nic_health() {
    print_header "5. Network Adapter Health & Link Speed"

    local interfaces
    interfaces=$(ip link show 2>/dev/null | awk -F': ' '/^[0-9]+:/{print $2}' \
        | grep -v "^lo\|^docker\|^br-\|^veth\|^virbr\|^tun\|^tap" || true)

    if [[ -z "$interfaces" ]]; then
        print_item "WARN" "NIC" "No physical interfaces detected"
        return
    fi

    for iface in $interfaces; do
        local state speed mac rx_err tx_err rx_drop tx_drop total_err
        state=$(cat "/sys/class/net/${iface}/operstate" 2>/dev/null || echo "unknown")
        speed=$(cat "/sys/class/net/${iface}/speed"     2>/dev/null || echo "-1")
        mac=$(cat   "/sys/class/net/${iface}/address"   2>/dev/null || echo "N/A")
        rx_err=$(cat  "/sys/class/net/${iface}/statistics/rx_errors"   2>/dev/null || echo 0)
        tx_err=$(cat  "/sys/class/net/${iface}/statistics/tx_errors"   2>/dev/null || echo 0)
        rx_drop=$(cat "/sys/class/net/${iface}/statistics/rx_dropped"  2>/dev/null || echo 0)
        tx_drop=$(cat "/sys/class/net/${iface}/statistics/tx_dropped"  2>/dev/null || echo 0)
        # On virtual machines, rx_drop is often normal (ring buffer overruns, etc.)
        # Only count actual hardware errors (rx_err + tx_err) as fault indicators
        # rx_drop alone on virtual NIC is not a hardware fault
        local hw_err=$(( rx_err + tx_err ))
        local any_drop=$(( rx_drop + tx_drop ))
        local total_err=$(( hw_err + any_drop ))

        local nic_status="OK"; [[ "$state" != "up" ]] && nic_status="WARN"
        local err_status="OK"
        if   [[ $hw_err -gt 100 ]]; then
            # Real hardware errors (rx/tx errors): always alert
            err_status="CRIT"
            add_crit "[严重] 网卡 ${iface} 硬件错误包 ${hw_err} (rx_err:${rx_err} tx_err:${tx_err})，网络链路可能存在故障！" "rx_err:${rx_err}  tx_err:${tx_err}  rx_drop:${rx_drop}  tx_drop:${tx_drop}"
        elif [[ $hw_err -gt 10 ]]; then
            err_status="WARN"
            add_warn "[警告] 网卡 ${iface} 存在 ${hw_err} 个硬件错误包，建议检查链路质量。" "rx_err:${rx_err}  tx_err:${tx_err}"
        elif [[ $any_drop -gt 500000 ]]; then
            # High rx_drop on physical NICs may indicate RSS/RPS config issues
            # On virtual NICs this is normal, so only warn at very high levels
            err_status="WARN"
            add_warn "[警告] 网卡 ${iface} drop包数 ${any_drop} 较高，虚拟机可能正常，物理机建议检查RSS/RPS配置。" "rx_drop:${rx_drop}  tx_drop:${tx_drop}"
        fi

        local drop_note=""
        [[ $any_drop -gt 0 && $hw_err -eq 0 ]] && drop_note=" (rx_drop正常于虚拟机)"

        local speed_str="${speed}Mb/s"
        [[ "$speed" == "-1" || "$speed" == "N/A" ]] && speed_str="N/A (virtual/unknown)"

        print_item "$nic_status" "NIC: $iface" "State:${state} Speed:${speed_str} MAC:${mac}"
        print_item "$err_status" "  Errors/Drops" "rx_err:${rx_err} tx_err:${tx_err} rx_drop:${rx_drop} tx_drop:${tx_drop}${drop_note}"
    done
}

# ==============================================================================
# MODULE 6: SSH Status & Firewall
# ==============================================================================
collect_ssh_info() {
    print_header "6. SSH Service, Port & Firewall"

    local ssh_svc_status="unknown"
    if cmd_exists systemctl; then
        ssh_svc_status=$(systemctl is-active sshd 2>/dev/null || systemctl is-active ssh 2>/dev/null || echo "unknown")
        local ssh_enabled
        ssh_enabled=$(systemctl is-enabled sshd 2>/dev/null || systemctl is-enabled ssh 2>/dev/null || echo "unknown")
        SSH_STATUS="${ssh_svc_status} (enabled: ${ssh_enabled})"
    else
        SSH_STATUS=$(service sshd status 2>/dev/null | grep -oE "running|stopped" | head -1 || echo "unknown")
        ssh_svc_status="$SSH_STATUS"
    fi
    local ssh_svc_ok="OK"
    if [[ "$ssh_svc_status" != "active" && "$ssh_svc_status" != "running" ]]; then
        ssh_svc_ok="CRIT"
        add_crit "[严重] SSH服务(sshd)未在运行，远程连接可能即将断开！" "sshd状态: ${ssh_svc_status}"
    fi
    print_item "$ssh_svc_ok" "SSH Service (sshd)" "$SSH_STATUS"

    # SSH Port
    SSH_PORT=$(ss -tlnp 2>/dev/null | grep -E ':22\s|sshd' | awk '{print $4}' | grep -oE '[0-9]+$' | head -1 || true)
    [[ -z "${SSH_PORT:-}" ]] && SSH_PORT=$(grep -E "^Port\s" /etc/ssh/sshd_config 2>/dev/null | awk '{print $2}' | head -1 || true)
    [[ -z "${SSH_PORT:-}" ]] && SSH_PORT="22"
    local port_num="${SSH_PORT//[^0-9]/}"
    [[ -z "$port_num" ]] && port_num="22"
    local listening; listening=$(ss -tlnp 2>/dev/null | grep ":${port_num}\b" | grep -c "LISTEN" || echo 0)
    local listen_str="LISTENING" listen_ok="OK"
    if [[ "$listening" -eq 0 ]]; then
        listen_str="NOT LISTENING!"; listen_ok="CRIT"
        CRITICALS+=("[严重] SSH端口 ${SSH_PORT} 未在监听，SSH连接可能已中断！")
    fi
    print_item "$listen_ok" "SSH Port" "${SSH_PORT} (${listen_str})"

    # sshd_config baseline
    print_section "sshd_config Security Baseline"
    local sshd_conf="/etc/ssh/sshd_config"
    if [[ -r "$sshd_conf" ]]; then
        SSH_PERMIT_ROOT=$(grep -E "^PermitRootLogin"        "$sshd_conf" | awk '{print $2}' | tail -1)
        SSH_PASSWD_AUTH=$(grep -E "^PasswordAuthentication" "$sshd_conf" | awk '{print $2}' | tail -1)
        SSH_MAX_AUTH=$(grep -E    "^MaxAuthTries"           "$sshd_conf" | awk '{print $2}' | tail -1)
        [[ -z "${SSH_PERMIT_ROOT:-}" ]] && SSH_PERMIT_ROOT="yes (default)"
        [[ -z "${SSH_PASSWD_AUTH:-}" ]] && SSH_PASSWD_AUTH="yes (default)"
        [[ -z "${SSH_MAX_AUTH:-}"    ]] && SSH_MAX_AUTH="6 (default)"

        local root_ok="OK"
        if [[ "$SSH_PERMIT_ROOT" == "yes" || "$SSH_PERMIT_ROOT" == *"default"* ]]; then
            root_ok="WARN"
            WARNINGS+=("[警告] SSH允许root直接登录(PermitRootLogin yes)，建议改为 prohibit-password 或 no。")
        fi
        local port_cfg; port_cfg=$(grep -E "^Port\s" "$sshd_conf" | awk '{print $2}' | tail -1 || echo "22 (default)")
        [[ -z "$port_cfg" ]] && port_cfg="22 (default)"
        [[ "$port_cfg" == "22" ]] && WARNINGS+=("[警告] SSH使用默认22端口，建议修改为高位端口以减少扫描攻击。")

        print_item "$root_ok" "PermitRootLogin"       "$SSH_PERMIT_ROOT"
        print_item "INFO"     "PasswordAuthentication" "$SSH_PASSWD_AUTH"
        print_item "INFO"     "MaxAuthTries"           "$SSH_MAX_AUTH"
        print_item "INFO"     "Configured Port"        "$port_cfg"
    else
        print_item "WARN" "sshd_config" "Cannot read /etc/ssh/sshd_config"
    fi

    # Firewall
    print_section "Firewall Status"
    local fw_detected=0
    if cmd_exists ufw; then
        local ufw_out; ufw_out=$(ufw status 2>/dev/null | head -5)
        printf "${C_GRAY}    UFW:\n"; while IFS= read -r l; do printf "${C_GRAY}      %s${C_RESET}\n" "$l"; log "    UFW: $l"; done <<< "$ufw_out"
        fw_detected=1
    fi
    if cmd_exists firewall-cmd; then
        print_item "INFO" "FirewallD" "$(firewall-cmd --state 2>/dev/null)"
        fw_detected=1
    fi
    if cmd_exists iptables; then
        local ipt_rules; ipt_rules=$(iptables -L -n 2>/dev/null | grep -c "^ACCEPT\|^DROP\|^REJECT" || echo 0)
        print_item "INFO" "iptables rules" "${ipt_rules} relevant rules"
        fw_detected=1
    fi
    if [[ $fw_detected -eq 0 ]]; then
        print_item "WARN" "Firewall" "No firewall found (ufw/firewalld/iptables)"
        WARNINGS+=("[警告] 未检测到启用的防火墙！建议配置 ufw 或 firewalld 限制入站访问。")
    fi

    # Active sessions
    print_section "Current SSH Sessions (who)"
    local who_out; who_out=$(who 2>/dev/null || true)
    if [[ -n "$who_out" ]]; then
        while IFS= read -r l; do printf "${C_GRAY}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$who_out"
    else
        print_raw "$C_GRAY" "    No active sessions"
    fi
}

# ==============================================================================
# MODULE 7: SSH Login History
# ==============================================================================
collect_ssh_history() {
    print_header "7. SSH Login History (Last 7 Days)"

    print_section "Successful Logins (last)"
    local success_log
    success_log=$(last -F -n 30 2>/dev/null | grep -v "^reboot\|^wtmp\|^$" | head -20 || true)
    if [[ -n "$success_log" ]]; then
        while IFS= read -r l; do printf "${C_GRAY}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$success_log"
    else
        print_raw "$C_GRAY" "    No successful login records found"
    fi

    print_section "Failed Logins / Auth Failures"
    local fail_log
    if [[ -f /var/log/btmp && -r /var/log/btmp ]]; then
        local fail_total; fail_total=$(lastb 2>/dev/null | grep -c "." || echo 0)
        fail_log=$(lastb -n 20 2>/dev/null | grep -v "^btmp\|^$" | head -20 || true)
        [[ -n "$fail_log" ]] && {
            print_item "WARN" "Total Failed Records in btmp" "$fail_total"
            while IFS= read -r l; do printf "${C_RED}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$fail_log"
        }
    elif [[ -f /var/log/auth.log ]]; then
        fail_log=$(grep -i "failed\|invalid\|authentication failure" /var/log/auth.log 2>/dev/null | tail -20 || true)
        [[ -n "$fail_log" ]] && while IFS= read -r l; do printf "${C_RED}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$fail_log"
    elif [[ -f /var/log/secure ]]; then
        fail_log=$(grep -i "failed\|invalid" /var/log/secure 2>/dev/null | tail -20 || true)
        [[ -n "$fail_log" ]] && while IFS= read -r l; do printf "${C_RED}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$fail_log"
    else
        print_raw "$C_GRAY" "    Cannot access btmp or auth.log (try running as root)"
    fi
}

# ==============================================================================
# MODULE 7.5: 30-Day Login IP Audit
# ==============================================================================
collect_30day_audit() {
    print_header "7.5 30-Day SSH Login IP Audit"
    printf "${C_CYAN}    [!] Scanning auth logs for last 30 days...${C_RESET}\n"
    log "  [!] Scanning auth logs for last 30 days..."

    local auth_log=""
    [[ -f /var/log/auth.log && -r /var/log/auth.log ]] && auth_log="/var/log/auth.log"
    [[ -f /var/log/secure   && -r /var/log/secure   ]] && auth_log="/var/log/secure"

    print_section "Successful Login IPs (Top 20)"
    if [[ -n "$auth_log" ]]; then
        local suc_ips
        suc_ips=$(grep "Accepted" "$auth_log" 2>/dev/null \
            | grep -oE "from [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" \
            | awk '{print $2}' | sort | uniq -c | sort -rn | head -20 || true)
        if [[ -n "$suc_ips" ]]; then
            while IFS= read -r l; do printf "${C_GRAY}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$suc_ips"
        else
            print_raw "$C_GRAY" "    No successful login IPs in log"
        fi
    else
        print_raw "$C_GRAY" "    Cannot access auth log (run as root)"
    fi

    print_section "Failed Login IPs - Brute Force Sources (Top 20)"
    if [[ -n "$auth_log" ]]; then
        local fail_ips
        fail_ips=$(grep -i "Failed\|Invalid\|authentication failure" "$auth_log" 2>/dev/null \
            | grep -oE "from [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" \
            | awk '{print $2}' | sort | uniq -c | sort -rn | head -20 || true)
        if [[ -n "$fail_ips" ]]; then
            while IFS= read -r ipline; do
                local count ip
                count=$(echo "$ipline" | awk '{print $1}')
                ip=$(echo "$ipline" | awk '{print $2}')
                local color="$C_GRAY"
                [[ $count -ge 500 ]] && color="$C_RED"
                [[ $count -ge 100 && $count -lt 500 ]] && color="$C_YELLOW"
                printf "${color}    [%6d attempts] %s${C_RESET}\n" "$count" "$ip"
                log "    [$(printf '%6d' "$count") attempts] $ip"
            done <<< "$fail_ips"
        else
            print_raw "$C_GRAY" "    No failed login IPs found"
        fi
    fi

    if cmd_exists journalctl; then
        print_section "Journald Auth Failures (last 30d, top 10 IPs)"
        local jfails
        jfails=$(journalctl -u sshd --since "30 days ago" 2>/dev/null \
            | grep -i "Failed\|Invalid" \
            | grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" \
            | sort | uniq -c | sort -rn | head -10 || true)
        if [[ -n "$jfails" ]]; then
            while IFS= read -r l; do printf "${C_GRAY}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$jfails"
        else
            print_raw "$C_GRAY" "    No journald SSH failure records (or no access)"
        fi
    fi
}

# ==============================================================================
# MODULE 8: Crash / OOM Logs
# ==============================================================================
collect_crash_logs() {
    print_header "8. Abnormal Shutdown / Crash / OOM Logs"

    print_section "OOM Killer Events"
    local oom_events=""
    cmd_exists journalctl && oom_events=$(journalctl -k --since "7 days ago" 2>/dev/null \
        | grep -i "out of memory\|oom_kill\|killed process" | tail -10 || true)
    [[ -z "$oom_events" ]] && oom_events=$(dmesg 2>/dev/null \
        | grep -i "out of memory\|oom_kill\|killed process" | tail -10 || true)
    if [[ -n "$oom_events" ]]; then
        local cnt; cnt=$(echo "$oom_events" | wc -l)
        print_item "CRIT" "OOM Killer Events" "${cnt} events detected!"
        CRITICALS+=("[严重] 检测到 ${cnt} 次OOM Killer事件！系统内存严重不足，进程被强制终止！")
        while IFS= read -r l; do printf "${C_RED}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$oom_events"
    else
        print_item "OK" "OOM Killer" "No OOM events detected"
    fi

    print_section "Kernel Panic Records"
    local panic_events=""
    cmd_exists journalctl && panic_events=$(journalctl -k --since "30 days ago" 2>/dev/null \
        | grep -i "kernel panic\|BUG:\|general protection\|segfault" | tail -10 || true)
    [[ -z "$panic_events" ]] && panic_events=$(dmesg 2>/dev/null \
        | grep -i "kernel panic\|BUG:\|general protection" | tail -10 || true)
    if [[ -n "$panic_events" ]]; then
        local cnt; cnt=$(echo "$panic_events" | wc -l)
        print_item "CRIT" "Kernel Panic/BUG" "${cnt} events!"
        CRITICALS+=("[严重] 检测到 ${cnt} 次内核Panic/BUG事件（等同于Windows BSOD），需要立即排查！")
        while IFS= read -r l; do printf "${C_RED}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$panic_events"
    else
        print_item "OK" "Kernel Panic" "No panic records found"
    fi

    print_section "System Reboot Timeline (last reboot)"
    while IFS= read -r l; do printf "${C_GRAY}    %s${C_RESET}\n" "$l"; log "    $l"; done \
        < <(last reboot 2>/dev/null | head -10 || true)

    print_section "Recent Kernel Error Messages (dmesg)"
    local dmesg_errs
    dmesg_errs=$(dmesg -l err,crit,alert,emerg 2>/dev/null | tail -15 || true)
    if [[ -n "$dmesg_errs" ]]; then
        while IFS= read -r l; do printf "${C_YELLOW}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$dmesg_errs"
    else
        print_item "OK" "Kernel Errors (dmesg)" "No critical kernel errors"
    fi
}

# ==============================================================================
# MODULE 9: Service Crash
# ==============================================================================
collect_service_crash() {
    print_header "9. Service Crash & Failed Services (Last 48h)"

    print_section "Currently Failed Services (systemctl --failed)"
    if cmd_exists systemctl; then
        local failed_svcs
        failed_svcs=$(systemctl --failed --no-legend --no-pager 2>/dev/null | grep -v "^$" | grep -v "sys-init.service\|systemd-sysctl.service" || true)
        if [[ -n "$failed_svcs" ]]; then
            local cnt; cnt=$(echo "$failed_svcs" | wc -l)
            print_item "CRIT" "Failed Services" "${cnt} service(s) in failed state!"
            add_crit "[严重] 有 ${cnt} 个系统服务处于失败状态！可能影响服务可用性。" "$(echo "$failed_svcs" | awk '{print $1}' | tr '\n' ' ')"
            while IFS= read -r l; do printf "${C_RED}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$failed_svcs"
        else
            print_item "OK" "Failed Services" "No failed services"
        fi

        print_section "Service Error Events (journalctl last 48h)"
        local svc_crashes
        svc_crashes=$(journalctl --since "48 hours ago" -p err --no-pager 2>/dev/null \
            | grep -i "failed\|crash\|core dump\|killed\|segfault" | tail -20 || true)
        if [[ -n "$svc_crashes" ]]; then
            local cnt; cnt=$(echo "$svc_crashes" | wc -l)
            print_item "WARN" "Service Error Events (48h)" "${cnt} error events"
            add_warn "[警告] 过去48h检测到 ${cnt} 个服务错误事件，建议排查相关服务日志。" "$(echo "$svc_crashes" | head -3)"
            while IFS= read -r l; do printf "${C_YELLOW}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$svc_crashes"
        else
            print_item "OK" "Service Error Events (48h)" "No service crash events"
        fi
    else
        print_raw "$C_YELLOW" "    systemctl not available (SysV system?)"
        log "    Available init.d: $(ls /etc/init.d/ 2>/dev/null | tr '\n' ' ')"
    fi

    print_section "Key Service Status Check"
    local key_services=("nginx" "apache2" "httpd" "mysql" "mysqld" "mariadb" "postgresql"
        "redis" "redis-server" "memcached" "docker" "php-fpm"
        "php8.1-fpm" "php8.2-fpm" "php8.3-fpm" "mongodb")
    for svc in "${key_services[@]}"; do
        if cmd_exists systemctl; then
            local svc_st; svc_st=$(systemctl is-active "$svc" 2>/dev/null || true)
            if [[ "$svc_st" == "active" ]]; then
                print_item "OK" "Service: $svc" "active (running)"
            elif [[ "$svc_st" == "failed" ]]; then
                # Only warn on "failed" - "inactive" just means not installed/not running (normal)
                print_item "WARN" "Service: $svc" "$svc_st (check: journalctl -u $svc)"
            fi
            # "inactive" = not installed or not needed on this server, skip silently
        fi
    done
}

# ==============================================================================
# MODULE 10: Security Checks
# ==============================================================================
collect_security() {
    print_header "10. Security: Brute Force, Intrusion Indicators & System Hardening"

    # Brute force analysis
    print_section "SSH Brute Force Analysis (last 24h)"
    local auth_log=""
    [[ -f /var/log/auth.log && -r /var/log/auth.log ]] && auth_log="/var/log/auth.log"
    [[ -f /var/log/secure   && -r /var/log/secure   ]] && auth_log="/var/log/secure"

    local fail_24h=0 fail_ips_24h=""
    if [[ -n "$auth_log" ]]; then
        # Use wc -l instead of grep -c to avoid "0\n0" with set -o pipefail
        fail_24h=$(grep -i "Failed\|Invalid" "$auth_log" 2>/dev/null | wc -l | tr -d ' ')
        fail_24h=${fail_24h:-0}
        fail_ips_24h=$(grep -i "Failed\|Invalid" "$auth_log" 2>/dev/null \
            | grep -oE "from [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" \
            | awk '{print $2}' | sort | uniq -c | sort -rn | head -10 || true)
    elif cmd_exists journalctl; then
        fail_24h=$(journalctl -u sshd --since "24 hours ago" 2>/dev/null \
            | grep -i "Failed\|Invalid" | wc -l | tr -d ' ')
        fail_24h=${fail_24h:-0}
        fail_ips_24h=$(journalctl -u sshd --since "24 hours ago" 2>/dev/null \
            | grep -i "Failed\|Invalid" | grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" \
            | sort | uniq -c | sort -rn | head -10 || true)
    fi
    SECURITY_FAILED_24H="$fail_24h"

    local bf_status="OK"
    if   [[ $fail_24h -gt 1000 ]]; then
        bf_status="CRIT"
        add_crit "[严重] 过去24h SSH失败登录 ${fail_24h} 次！遭受高强度暴力破解，建议立即封锁攻击IP并启用fail2ban！" "$(echo "$fail_ips_24h" | head -5)"
        SECURITY_ASSESSMENT="【高风险 Critical】检测到高频暴力破解攻击，立即封锁攻击IP并启用fail2ban！"
    elif [[ $fail_24h -gt 100 ]]; then
        bf_status="WARN"
        add_warn "[警告] 过去24h SSH失败登录 ${fail_24h} 次，存在中等强度暴力破解，建议配置fail2ban。" "$(echo "$fail_ips_24h" | head -5)"
        SECURITY_ASSESSMENT="【中风险 Warning】检测到暴力破解活动，建议配置fail2ban并考虑修改SSH默认端口。"
    else
        SECURITY_ASSESSMENT="【低风险 Safe】过去24h仅 ${fail_24h} 次失败登录，SSH安全状态正常。"
    fi
    print_item "$bf_status" "Failed SSH Logins (24h)" "${fail_24h} attempts"

    if [[ -n "$fail_ips_24h" ]]; then
        log "  --- Top Brute Force Source IPs ---"
        while IFS= read -r ipline; do
            local count ip
            count=$(echo "$ipline" | awk '{print $1}')
            ip=$(echo "$ipline" | awk '{print $2}')
            local color="$C_GRAY"
            [[ $count -ge 100 ]] && color="$C_RED"
            [[ $count -ge 20 && $count -lt 100 ]] && color="$C_YELLOW"
            printf "${color}    [%6d attempts] %s${C_RESET}\n" "$count" "$ip"
            log "    [$(printf '%6d' "$count") attempts] $ip"
        done <<< "$fail_ips_24h"
    fi
    print_item "INFO" "Security Assessment" "$SECURITY_ASSESSMENT"

    # fail2ban
    if cmd_exists fail2ban-client; then
        local f2b_jails; f2b_jails=$(fail2ban-client status 2>/dev/null | grep "Jail list" | cut -d: -f2 | tr -d ' ')
        print_item "OK" "fail2ban" "Installed | Jails: ${f2b_jails:-none}"
    else
        print_item "WARN" "fail2ban" "NOT installed - 强烈建议安装 fail2ban"
        add_warn "[警告] 未安装fail2ban，SSH暴力破解防护缺失！建议: apt install fail2ban 或 yum install fail2ban" "安装命令: apt install fail2ban -y && systemctl enable --now fail2ban"
    fi

    # UID=0 backdoor check
    print_section "UID=0 Accounts (Root-level backdoor check)"
    local uid0_accounts
    uid0_accounts=$(awk -F: '$3==0{print $1}' /etc/passwd 2>/dev/null | tr '\n' ' ')
    local uid0_count; uid0_count=$(awk -F: '$3==0' /etc/passwd 2>/dev/null | wc -l)
    if [[ $uid0_count -gt 1 ]] || [[ $uid0_count -eq 1 && "$uid0_accounts" != "root "* ]]; then
        print_item "CRIT" "UID=0 Accounts" "$uid0_accounts"
        add_crit "[严重] 发现除root外的UID=0账户：${uid0_accounts}！这是典型的入侵后门，请立即排查！" "UID=0账户列表: ${uid0_accounts}  来源: /etc/passwd"
    else
        print_item "OK" "UID=0 Accounts" "Only root (normal)"
    fi

    # Local users (UID >= 1000)
    print_section "Local User Accounts (UID >= 1000)"
    while IFS= read -r uline; do
        printf "${C_GRAY}    %s${C_RESET}\n" "$uline"
        log "    $uline"
    done < <(awk -F: '$3>=1000 && $3!=65534{print $1, "UID:"$3, "Shell:"$7}' /etc/passwd 2>/dev/null || true)

    # sudoers check
    print_section "Sudo Privilege Check (broad ALL=ALL entries)"
    local sudo_broad
    sudo_broad=$(grep -v "^#\|^$" /etc/sudoers 2>/dev/null | grep -E "ALL.*ALL" | head -10 || true)
    sudo_broad+=$(grep -rh -v "^#\|^$" /etc/sudoers.d/ 2>/dev/null | grep -E "ALL.*ALL" | head -5 || true)
    if [[ -n "$sudo_broad" ]]; then
        while IFS= read -r l; do printf "${C_YELLOW}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$sudo_broad"
    else
        print_item "INFO" "sudoers" "No broad ALL=ALL entries (or no access)"
    fi

    # Crontab backdoor
    print_section "Crontab Backdoor Check (wget/curl/bash -i in cron)"
    local suspicious_cron
    # Whitelist known-legitimate patterns:
    #   certbot renewal (perl -e 'sleep rand'), dpkg temp files (# comment lines), apt hooks
    suspicious_cron=$(grep -rn "wget\|curl\|bash -i\|/dev/shm\|nc \|ncat\|python.*-c\|perl.*-e" \
        /etc/cron* /var/spool/cron/ 2>/dev/null \
        | grep -v "^Binary\|^grep" \
        | grep -v "certbot.*perl.*sleep\|perl.*rand.*certbot\|#.*crontab.*installed\|/usr/bin/certbot" \
        | grep -v ":[0-9]*:#" \
        | head -20 || true)
    # Separately check /tmp references but exclude comment lines (file:linenum:#...) and known dpkg temp patterns
    local tmp_cron
    tmp_cron=$(grep -rn "/tmp" /etc/cron* /var/spool/cron/ 2>/dev/null \
        | grep -v "^Binary\|^grep" \
        | grep -v ":[0-9]*:#" \
        | grep -v "crontab\.[a-zA-Z0-9]*/crontab\|dpkg\|apt" \
        | head -10 || true)
    [[ -n "$tmp_cron" ]] && suspicious_cron+="
${tmp_cron}"
    if [[ -n "$suspicious_cron" ]]; then
        print_item "CRIT" "Suspicious Cron Entries" "DETECTED!"
        add_crit "[严重] 发现可疑计划任务（含wget/curl/bash -i等），可能是恶意持久化后门！" "$(echo "$suspicious_cron" | head -5)"
        while IFS= read -r l; do
            [[ -z "$l" ]] && continue
            printf "${C_RED}    %s${C_RESET}\n" "$l"; log "    [SUSPICIOUS_CRON] $l"
        done <<< "$suspicious_cron"
    else
        print_item "OK" "Cron Backdoor Check" "No suspicious entries found"
    fi

    # /tmp and /dev/shm suspicious executables
    print_section "Suspicious Executables in /tmp and /dev/shm"
    local tmp_sus
    tmp_sus=$(find /tmp /dev/shm 2>/dev/null \
        \( -executable -o -name "*.sh" -o -name "*.py" -o -name "*.pl" -o -name "*.elf" \) \
        -type f 2>/dev/null | grep -v "tcpquality-entry" | head -20 || true)
    if [[ -n "$tmp_sus" ]]; then
        print_item "WARN" "Executables in /tmp//dev/shm" "FOUND - Review manually!"
        WARNINGS+=("[警告] 在/tmp或/dev/shm发现可执行文件，可能是无文件挖矿或恶意程序！")
        while IFS= read -r l; do printf "${C_YELLOW}    %s${C_RESET}\n" "$l"; log "    [SUSPICIOUS_FILE] $l"; done <<< "$tmp_sus"
    else
        print_item "OK" "Suspicious /tmp Files" "No suspicious executables found"
    fi

    # SUID in non-standard paths
    print_section "SUID/SGID Files in Non-standard Paths"
    local suid_files
    suid_files=$(find /usr/local /opt /home /tmp /var/tmp /dev 2>/dev/null \
        -type f \( -perm -4000 -o -perm -2000 \) -ls 2>/dev/null | head -20 || true)
    if [[ -n "$suid_files" ]]; then
        print_item "WARN" "SUID/SGID non-std" "FOUND - Review manually!"
        WARNINGS+=("[警告] 在非标准路径发现SUID/SGID文件，可能被用于权限提升！")
        while IFS= read -r l; do printf "${C_YELLOW}    %s${C_RESET}\n" "$l"; log "    [SUID] $l"; done <<< "$suid_files"
    else
        print_item "OK" "SUID/SGID (non-std)" "None found"
    fi

    # Suspicious process names
    print_section "Suspicious Process Scan (Miner / Backdoor Signatures)"
    local sus_names=("xmrig" "xmr-stak" "cpuminer" "minerd" "kworkerds"
        "kdevtmpfsi" "kinsing" "masscan" "zmap" "tsm" "bioset" "pastebin")
    local found_sus=0
    for pname in "${sus_names[@]}"; do
        local match; match=$(pgrep -la "$pname" 2>/dev/null | grep -v "pgrep\|grep" || true)
        if [[ -n "$match" ]]; then
            found_sus=1
            print_item "CRIT" "Suspicious Process: $pname" "$match"
            add_crit "[严重] 发现可疑进程 '${pname}'！已知挖矿程序/恶意软件特征，请立即排查处理！" "进程信息: ${match}"
        fi
    done
    [[ $found_sus -eq 0 ]] && print_item "OK" "Suspicious Process Scan" "No known miner/backdoor signatures"

    # Recently modified sensitive files
    print_section "Recently Modified Files in /etc (last 24h)"
    local recently_modified
    recently_modified=$(find /etc -mtime -1 -type f 2>/dev/null | grep -v "\.swp\|~$" | head -20 || true)
    if [[ -n "$recently_modified" ]]; then
        local cnt; cnt=$(echo "$recently_modified" | wc -l)
        print_item "WARN" "/etc files modified <24h" "${cnt} files - Verify if expected"
        add_warn "[警告] /etc 目录下有 ${cnt} 个文件在过去24h被修改，如非计划内变更请排查！" "$(echo "$recently_modified" | head -10 | tr '\n' '  ')"
        while IFS= read -r l; do printf "${C_YELLOW}    %s${C_RESET}\n" "$l"; log "    $l"; done <<< "$recently_modified"
    else
        print_item "OK" "Recent /etc Modifications" "No unexpected recent changes"
    fi
}

# ==============================================================================
# MODULE 10.5: Advanced Intrusion Detection (Rootkits & Persistence)
# ==============================================================================
collect_advanced_intrusion() {
    print_header "10.5 Advanced Intrusion Detection (Rootkits & Anomalies)"

    # 1. LD_PRELOAD Check
    print_section "Global Dynamic Linker Hijack (ld.so.preload)"
    if [[ -s /etc/ld.so.preload ]]; then
        local preload_content; preload_content=$(cat /etc/ld.so.preload 2>/dev/null || true)
        print_item "CRIT" "ld.so.preload" "NON-EMPTY! Potential Rootkit!"
        add_crit "[严重] /etc/ld.so.preload 非空！这是典型的用户态Rootkit(如隐藏进程/网络)全局注入特征，请立即排查该so文件！" "文件内容: ${preload_content}"
    else
        print_item "OK" "ld.so.preload" "Empty (Clean)"
    fi

    # 2. Process Anomalies (kworker masquerading, memfd, deleted)
    print_section "Process Anomalies (Masquerading / In-Memory)"
    local proc_anomalies=""
    for p in /proc/[0-9]*; do
        [[ -d "$p" ]] || continue
        local pid="${p##*/}"
        local cmd=""; cmd=$(cat "$p/cmdline" 2>/dev/null | tr '\0' ' ' || true)
        local exe=""; exe=$(readlink -f "$p/exe" 2>/dev/null || true)
        
        # Anomaly 1: Masquerading as kernel thread (starts with [ but has an 'exe')
        if [[ "$cmd" == \[*\] && -n "$exe" && "$exe" != *" (deleted)" ]]; then
            proc_anomalies+="PID: $pid | CMD: $cmd | EXE: $exe (Fake Kernel Thread!)\n"
        fi
        # Anomaly 2: Executing from memfd (fileless malware)
        if [[ "$exe" == *"memfd:"* ]]; then
            proc_anomalies+="PID: $pid | CMD: $cmd | EXE: $exe (Fileless Execution!)\n"
        fi
        # Anomaly 3: Executable deleted but process running (suspicious if in /tmp or /var/cache)
        if [[ "$exe" == *" (deleted)" && ("$exe" == *"/tmp/"* || "$exe" == *"/var/cache/"* || "$exe" == *"/dev/shm/"*) ]]; then
            proc_anomalies+="PID: $pid | CMD: $cmd | EXE: $exe (Deleted Malicious Payload?)\n"
        fi
    done
    
    if [[ -n "$proc_anomalies" ]]; then
        local cnt; cnt=$(echo -e "$proc_anomalies" | grep -v "^$" | wc -l | tr -d ' ')
        print_item "CRIT" "Process Anomalies" "${cnt} suspicious processes found!"
        add_crit "[严重] 发现 ${cnt} 个高级异常进程 (伪装内核线程 / memfd无文件执行 / 异常态删除残留)！" "$(echo -e "$proc_anomalies")"
    else
        print_item "OK" "Process Anomalies" "No obvious masquerading/memfd found"
    fi

    # 3. Systemd Persistence Anomalies
    print_section "Systemd Persistence Anomalies"
    local sysd_anomalies=""
    if cmd_exists systemctl; then
        local services; services=$(systemctl list-units --type=service --all --no-legend 2>/dev/null | awk '{print $1}' || true)
        for svc in $services; do
            # Exclude snapd mount units, sys-init, man-db, and apparmor to prevent false positives
            [[ "$svc" == snap-* || "$svc" == snap.* || "$svc" == "sys-init.service" || "$svc" == "man-db.service" || "$svc" == "apparmor.service" ]] && continue
            local execstart; execstart=$(systemctl show -p ExecStart --value "$svc" 2>/dev/null || true)
            # Checking if ExecStart path contains /tmp, /var/cache, /dev/shm, or hidden directories (/.xxxx/)
            if [[ "$execstart" == *"/tmp/"* || "$execstart" == *"/var/cache/"* || "$execstart" == *"/dev/shm/"* || "$execstart" =~ \/\.[a-zA-Z0-9]+ ]]; then
                sysd_anomalies+="Service: $svc | ExecStart: $execstart\n"
            fi
        done
    fi
    if [[ -n "$sysd_anomalies" ]]; then
        local cnt; cnt=$(echo -e "$sysd_anomalies" | grep -v "^$" | wc -l | tr -d ' ')
        print_item "CRIT" "Systemd Anomalies" "${cnt} suspicious services found!"
        add_crit "[严重] 发现 ${cnt} 个系统服务(Systemd)的启动路径极为可疑 (位于缓存/临时目录/隐藏目录)，极大概率是恶意持久化！" "$(echo -e "$sysd_anomalies")"
    else
        print_item "OK" "Systemd Anomalies" "No suspicious ExecStart paths"
    fi

    # 4. Hidden Files/Dirs in /var/cache and /tmp
    print_section "Hidden Files/Directories in Cache/Tmp"
    local hidden_files
    hidden_files=$(find /var/cache /tmp /var/tmp /dev/shm -path "*/\.*" -type f 2>/dev/null | grep -v "fontconfig\|/var/cache/snapd\|/var/cache/man\|apparmor" | head -30 || true)
    
    if [[ -n "$hidden_files" ]]; then
         local cnt; cnt=$(echo "$hidden_files" | wc -l | tr -d ' ')
         print_item "WARN" "Hidden Files in Cache" "${cnt} hidden files found!"
         add_warn "[警告] 在 /var/cache 或临时目录中发现隐藏文件/目录 (以.开头)，请排查是否为恶意负载或Rootkit配置！" "$(echo "$hidden_files" | head -10)"
    else
         print_item "OK" "Cache/Tmp Hidden Files" "None found"
    fi

    # 5. Suspicious Environment Variables
    print_section "Suspicious Environment Variables (LD_PRELOAD)"
    local env_anomalies=""
    env_anomalies=$(grep -a -l -E "LD_PRELOAD=|PRELOAD_ACTIVE=" /proc/[0-9]*/environ 2>/dev/null | head -10 || true)
    if [[ -n "$env_anomalies" ]]; then
        print_item "CRIT" "Process Env Anomalies" "Found PRELOAD env vars!"
        add_crit "[严重] 发现运行中进程的环境变量被注入了 LD_PRELOAD 或相关隐藏标志，极大概率为动态库劫持(Rootkit)！" "$(echo "$env_anomalies" | xargs -I{} sh -c 'echo "PID: $(basename $(dirname {})) -> $(tr "\0" "\n" < {} | grep -a -E "LD_PRELOAD|PRELOAD_ACTIVE" | tr "\n" " ")"' 2>/dev/null)"
    else
        print_item "OK" "Process Env Anomalies" "Clean"
    fi
}

# ==============================================================================
# MODULE 11: Generate TXT Report
# ==============================================================================
generate_report() {
    print_header "11. Generating Report Files"

    local sep; sep=$(printf '%0.s=' {1..72})
    local report_time; report_time=$(date "+%Y-%m-%d %H:%M:%S")
    local final_lines=()

    final_lines+=("$sep")
    final_lines+=("       ${MAIN_IP}  Linux服务器安全自检报告 ${SCRIPT_VERSION}")
    final_lines+=("$sep")
    final_lines+=("生成时间   : ${report_time}")
    final_lines+=("主机名     : ${HOSTNAME_VAL}")
    final_lines+=("操作系统   : ${SYS_OS}")
    final_lines+=("内核版本   : ${SYS_KERNEL}")
    final_lines+=("运行时长   : ${SYS_UPTIME}")
    final_lines+=("上次重启   : ${SYS_LASTBOOT}")
    final_lines+=("CPU型号    : ${SYS_CPU_MODEL} (${SYS_CPU_CORES} 核)")
    final_lines+=("总内存     : ${SYS_TOTAL_RAM}")
    final_lines+=("")

    # Critical summary - with evidence
    final_lines+=("$sep")
    final_lines+=("  [严重告警 CRITICAL - ${#CRITICALS[@]} 项]")
    final_lines+=("$sep")
    if [[ ${#CRITICALS[@]} -gt 0 ]]; then
        for c in "${CRITICALS[@]}"; do
            if [[ "$c" == *"|EV|"* ]]; then
                local cmsg; cmsg="${c%%|EV|*}"
                local cev;  cev="${c#*|EV|}"
                final_lines+=("  ${cmsg}")
                # Print evidence indented, wrapped at ~70 chars
                while IFS= read -r evline; do
                    [[ -z "$evline" ]] && continue
                    final_lines+=("      └─ 凭据: ${evline}")
                done <<< "$cev"
            else
                final_lines+=("  $c")
            fi
        done
    else
        final_lines+=("  [✓] 无严重告警，所有关键指标正常 (All Clear)")
    fi
    final_lines+=("")

    # Warning summary - with evidence
    final_lines+=("$sep")
    final_lines+=("  [警告 WARNING - ${#WARNINGS[@]} 项]")
    final_lines+=("$sep")
    if [[ ${#WARNINGS[@]} -gt 0 ]]; then
        for w in "${WARNINGS[@]}"; do
            if [[ "$w" == *"|EV|"* ]]; then
                local wmsg; wmsg="${w%%|EV|*}"
                local wev;  wev="${w#*|EV|}"
                final_lines+=("  ${wmsg}")
                while IFS= read -r evline; do
                    [[ -z "$evline" ]] && continue
                    final_lines+=("      └─ 凭据: ${evline}")
                done <<< "$wev"
            else
                final_lines+=("  $w")
            fi
        done
    else
        final_lines+=("  [✓] 无警告项，系统状态良好 (All Clear)")
    fi
    final_lines+=("")

    # Security assessment
    final_lines+=("$sep")
    final_lines+=("  [安全评估结论]")
    final_lines+=("$sep")
    final_lines+=("  ${SECURITY_ASSESSMENT}")
    final_lines+=("")

    # Key metrics
    final_lines+=("$sep")
    final_lines+=("  [关键指标速览]")
    final_lines+=("$sep")
    final_lines+=("  CPU使用率          : ${RES_CPU_PCT}")
    final_lines+=("  内存使用率         : ${RES_RAM_USAGE}")
    final_lines+=("  Swap使用率         : ${RES_SWAP_USAGE}")
    final_lines+=("  TCP连接汇总        : Total:${NET_TCP_TOTAL} ESTAB:${NET_ESTABLISHED} SYN_RECV:${NET_SYN_RECV} TIME_WAIT:${NET_TIME_WAIT} CLOSE_WAIT:${NET_CLOSE_WAIT} LISTEN:${NET_LISTEN}")
    final_lines+=("  高频远端IP         : ${NET_TOP_IPS:-无}")
    final_lines+=("  默认网关           : ${ROUTE_GW}")
    final_lines+=("  网关ARP MAC        : ${ROUTE_GW_MAC:-N/A}")
    final_lines+=("  异常路由           : ${ROUTE_BAD_ROUTES:-无}")
    final_lines+=("  SSH端口            : ${SSH_PORT}")
    final_lines+=("  SSH服务状态        : ${SSH_STATUS}")
    final_lines+=("  PermitRootLogin    : ${SSH_PERMIT_ROOT}")
    final_lines+=("  PasswordAuth       : ${SSH_PASSWD_AUTH}")
    final_lines+=("  24h失败登录次数    : ${SECURITY_FAILED_24H} 次")
    final_lines+=("")

    # Full detail
    final_lines+=("$sep")
    final_lines+=("  [详细检查数据 / Detailed Scan Output]")
    final_lines+=("$sep")
    for tline in "${TXT_LINES[@]}"; do
        final_lines+=("$tline")
    done
    final_lines+=("")
    final_lines+=("$sep")
    final_lines+=("                  Linux服务器自检报告完毕 (END OF REPORT)")
    final_lines+=("         LinuxCheck ${SCRIPT_VERSION}  |  Generated: ${report_time}")
    final_lines+=("$sep")

    printf '%s\n' "${final_lines[@]}" > "$TXT_REPORT"

    print_item "OK" "Report Directory" "$REPORT_DIR"
    print_item "OK" "TXT Report"       "$TXT_REPORT"
    printf "\n${C_BOLD_GREEN}  [✓] Report saved!${C_RESET}\n"
    printf "${C_CYAN}  View  : cat \"%s\"${C_RESET}\n" "$TXT_REPORT"
    printf "${C_CYAN}  Download: scp root@<server>:\"%s\" ~/Desktop/${C_RESET}\n" "$TXT_REPORT"
}

# ==============================================================================
# Final Summary
# ==============================================================================
print_final_summary() {
    local sep; sep=$(printf '%0.s=' {1..72})
    printf "\n${C_BOLD_CYAN}%s${C_RESET}\n" "$sep"
    printf "${C_BOLD_YELLOW}  ★  SUMMARY / 检查结果摘要  ★${C_RESET}\n"
    printf "${C_BOLD_CYAN}%s${C_RESET}\n" "$sep"

    if [[ ${#CRITICALS[@]} -gt 0 ]]; then
        printf "\n${C_BOLD_RED}  [严重告警 CRITICAL - ${#CRITICALS[@]} 项]${C_RESET}\n"
        for c in "${CRITICALS[@]}"; do
            local cmsg="$c"
            [[ "$c" == *"|EV|"* ]] && cmsg="${c%%|EV|*}"
            printf "${C_RED}  ✗ %s${C_RESET}\n" "$cmsg"
        done
    else
        printf "\n${C_BOLD_GREEN}  [✓] 严重告警: 无 (All Clear)${C_RESET}\n"
    fi

    if [[ ${#WARNINGS[@]} -gt 0 ]]; then
        printf "\n${C_BOLD_YELLOW}  [警告 WARNING - ${#WARNINGS[@]} 项]${C_RESET}\n"
        for w in "${WARNINGS[@]}"; do
            local wmsg="$w"
            [[ "$w" == *"|EV|"* ]] && wmsg="${w%%|EV|*}"
            printf "${C_YELLOW}  ! %s${C_RESET}\n" "$wmsg"
        done
    else
        printf "\n${C_BOLD_GREEN}  [✓] 警告: 无 (All Clear)${C_RESET}\n"
    fi

    printf "\n${C_BOLD_CYAN}  安全评估结论: ${C_RESET}%s\n" "$SECURITY_ASSESSMENT"
    printf "\n${C_BOLD_GREEN}  📄 TXT报告: ${C_RESET}%s\n" "$TXT_REPORT"
    printf "${C_GRAY}     (复制TXT内容发送给AI进行深入分析)${C_RESET}\n"
    printf "\n${C_BOLD_CYAN}%s${C_RESET}\n\n" "$sep"
}

# ==============================================================================
# MAIN
# ==============================================================================
main() {
    local sep; sep=$(printf '%0.s=' {1..72})
    printf "\n${C_BOLD_CYAN}%s${C_RESET}\n" "$sep"
    printf "${C_BOLD_YELLOW}    Linux Server Self-Diagnostic Script %s${C_RESET}\n" "$SCRIPT_VERSION"
    printf "${C_BOLD_YELLOW}    Linux 服务器安全自助排障脚本${C_RESET}\n"
    printf "${C_GRAY}    Host: %s  IP: %s  Time: %s${C_RESET}\n" "$HOSTNAME_VAL" "$MAIN_IP" "$(date '+%Y-%m-%d %H:%M:%S')"
    printf "${C_BOLD_CYAN}%s${C_RESET}\n\n" "$sep"

    preflight_check
    collect_system_info
    collect_update_info
    collect_resource_usage
    collect_network_info
    collect_network_routing
    collect_nic_health
    collect_ssh_info
    collect_ssh_history
    collect_30day_audit
    collect_crash_logs
    collect_service_crash
    collect_security
    collect_advanced_intrusion
    generate_report
    print_final_summary
}

main "$@"

